{"id":15444705,"url":"https://github.com/tybruno/modifiable-items-dictionary","last_synced_at":"2026-01-30T22:39:32.491Z","repository":{"id":65762996,"uuid":"596748951","full_name":"tybruno/modifiable-items-dictionary","owner":"tybruno","description":"Modifiable Items Dictionary is a python3.6+ library offering enhanced, tested, typed, and thread-safe dictionary classes. ModifiableItemsDict and ModifiableItemsAttrDict are classes that allow for key and value modifications during creation, insertion, and retrieval. ModifiableItemsAttrDict also provides attribute-style access to dictionary items. ","archived":false,"fork":false,"pushed_at":"2024-06-20T21:03:38.000Z","size":49,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-08-31T20:26:16.055Z","etag":null,"topics":["attr-dict","attribute-dic","dict","dictionaries-in-python","dictionary","modifiable-dict","modifiable-items-dict","python","python3"],"latest_commit_sha":null,"homepage":"https://pypi.org/project/modifiable-items-dictionary/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tybruno.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2023-02-02T21:12:24.000Z","updated_at":"2024-06-20T21:02:08.000Z","dependencies_parsed_at":"2025-05-14T05:31:00.536Z","dependency_job_id":"3525f3cd-1316-4737-b9ee-a140c16e5898","html_url":"https://github.com/tybruno/modifiable-items-dictionary","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/tybruno/modifiable-items-dictionary","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tybruno%2Fmodifiable-items-dictionary","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tybruno%2Fmodifiable-items-dictionary/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tybruno%2Fmodifiable-items-dictionary/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tybruno%2Fmodifiable-items-dictionary/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tybruno","download_url":"https://codeload.github.com/tybruno/modifiable-items-dictionary/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tybruno%2Fmodifiable-items-dictionary/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28921469,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T22:32:35.345Z","status":"ssl_error","status_checked_at":"2026-01-30T22:32:31.927Z","response_time":66,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["attr-dict","attribute-dic","dict","dictionaries-in-python","dictionary","modifiable-dict","modifiable-items-dict","python","python3"],"created_at":"2024-10-01T19:42:20.104Z","updated_at":"2026-01-30T22:39:32.475Z","avatar_url":"https://github.com/tybruno.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)\n[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-0000ff.svg)](https://github.com/psf/blue)\n[![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT)\n[![codecov](https://codecov.io/gh/tybruno/modifiable-items-dictionary/branch/main/graph/badge.svg?token=ZO94EJFI3G)](https://codecov.io/gh/tybruno/modifiable-items-dictionary)\n[![Pylint](https://img.shields.io/badge/Pylint-10.0%2F10-green)](10.0/10)\n[![Mypy](https://img.shields.io/badge/Mypy-checked-blue)](10.0/10)\n# modifiable-items-dict\n\nA simple, fast, typed, and tested implementation for a python3.6+ Modifiable Items dictionary. `ModifiableItemsDict`\nextends `dict` with the ability to modify keys and values on creation, insertion, and retrieval. This class extends and\nmaintains the original functionality of the builtin `dict`.\n\nIn addition to `ModifiableItemsDict`, this implementation also includes `ModifiableItemsAttrDict`,\na class that inherits from `ModifiableItemsDict` and adds attribute-style access to dictionary items.\nThis means you can access dictionary items as if they were attributes of the object, providing an alternative,\noften more readable way to access dictionary items.\nLike `ModifiableItemsDict`, `ModifiableItemsAttrDict` also allows modification of keys and values on creation,\ninsertion, and retrieval, ensuring consistency and flexibility in handling dictionary items.\n\n#### Key Features:\n\n* **Easy**: Flexible and easy to add Key and/or Value modifiers to\n  the `ModifiableItemsDict` and `ModifiableItemsAttrDict`.\n* **Attribute Access**: `ModifiableItemsAttrDict` allows attribute-style access to dictionary items, providing an\n  alternative, often more readable way to access dictionary items.\n* **Great Developer Experience**: Being fully typed makes it great for editor\n  support.\n* **Fully Tested**: Our test suite fully tests the functionality to ensure\n  that `ModifiableItemsDict` and `ModifiableItemsAttrDict` run as expected.\n* **There is More!!!**:\n    * [CaselessDict](https://github.com/tybruno/caseless-dictionary): `CaselessDict`\n      extends `ModifiableItemsDict` and `ModifiableItemsAttrDict` which\n      is a `CaselessDict`  and `CaselessAttrDict` that ignores the case of the keys.\n\n## Installation\n\n`pip install modifiable-items-dictionary`\n\n## ModifiableItemsDict and ModifiableItemsAttrDict\n\nThe `ModifiableItemsDict` and `ModifiableItemsAttrDict` classes are part of the `modifiable_items_dictionary` module.\nThey provide advanced dictionary functionalities with additional features for modifying keys and values.\n\n### ModifiableItemsDict\n\nThe `ModifiableItemsDict` class is a dictionary class that allows modification of keys and values during creation,\ninsertion, and retrieval. It provides the following features:\n\n- **Key Modifiers**: This class allows you to specify functions that modify keys on creation, insertion, and retrieval.\n  This can be useful for ensuring that all keys adhere to a certain format or standard.\n- **Value Modifiers**: Similar to key modifiers, you can also specify functions that modify values. This can be useful\n  for transforming or sanitizing data as it's added to the dictionary.\n- **Thread Safety**: This class is designed to be thread-safe, making it suitable for use in multi-threaded\n  applications.\n- **Fully Tested**: The functionality of this class is fully tested to ensure reliable operation.\n\n#### Example\n\n```python\nfrom modifiable_items_dictionary import ModifiableItemsDict\n\n\ndef _add_1(_value):\n    if isinstance(_value, int):\n        _value += 1\n    return _value\n\n\ndef _case_fold_string(_value):\n    if isinstance(_value, str):\n        _value = _value.casefold()\n    return _value\n\n\nModifiableItemsDict._key_modifiers = [str.casefold]\nModifiableItemsDict._value_modifiers = (\n    _add_1, _case_fold_string)\n# Or\n# ModifiableItemsDict._key_modifiers = staticmethod(str.casefold)\n# ModifiableItemsDict._value_modifiers = [_case_fold_string, _add_1]\n\nmodifiable_items_dictionary = ModifiableItemsDict(\n    {\"lower\": 1, \"UPPER\": 2},\n    CamelCase=3,\n    snake_case=\"FoUR\"\n)\n\nprint(\n    modifiable_items_dictionary\n)  # {'lower': 2, 'upper': 3, 'camelcase': 4, 'snake_case': 'four'}\n\ndel modifiable_items_dictionary[\"LOWER\"]\ndel modifiable_items_dictionary[\"UPPER\"]\nmodifiable_items_dictionary.pop(\"SNAKE_CAse\")\n\nmodifiable_items_dictionary[\"HeLLO\"] = 5\n\nprint(modifiable_items_dictionary)  # {'camelcase': 4, 'hello': 6}\n```\n\n### ModifiableItemsAttrDict\n\nThe `ModifiableItemsAttrDict` class is an extension of the `ModifiableItemsDict` class, inheriting all its features\nwhile adding attribute-style access to dictionary items. This class maintains the same key and value modifiers, ensuring\nconsistency and flexibility in handling dictionary items.\n\nLike `ModifiableItemsDict`, `ModifiableItemsAttrDict` is designed with thread safety in mind, making it suitable for use\nin multi-threaded applications. It is also fully tested to ensure reliable operation.\n\nIn addition to these features, `ModifiableItemsAttrDict` offers:\n\n- **Attribute-style Access**: This feature allows you to access dictionary items as if they were attributes of the\n  object. For example, you can use `dict.key` instead of `dict['key']`. This provides an alternative, often more\n  readable way to access dictionary items, while still retaining the traditional dictionary access methods.\n\nThis combination of features makes `ModifiableItemsAttrDict` a powerful tool for managing dictionaries in a way that is\nboth flexible and intuitive, while maintaining the robustness and reliability of the `ModifiableItemsDict` class.\n\n#### Example\n\n```python\nimport modifiable_items_dictionary\n\n\ndef _add_1(_value):\n    if isinstance(_value, int):\n        _value += 1\n    return _value\n\n\ndef _case_fold_string(_value):\n    if isinstance(_value, str):\n        _value = _value.casefold()\n    return _value\n\n\nmodifiable_items_dictionary.ModifiableItemsAttrDict._key_modifiers = [\n    str.casefold\n]\nmodifiable_items_dictionary.ModifiableItemsAttrDict._value_modifiers = (\n    _add_1,\n    _case_fold_string,\n)\n\nmodifiable_items_attr_dict = (\n    modifiable_items_dictionary.ModifiableItemsAttrDict(\n        {'lower': 1, 'UPPER': 2}, CamelCase=3, snake_case='FoUR'\n    )\n)\n\nprint(\n    modifiable_items_attr_dict\n)  # {'lower': 2, 'upper': 3, 'camelcase': 4, 'snake_case': 'four'}\n\n# Key-based access\ndel modifiable_items_attr_dict['LOWER']\nmodifiable_items_attr_dict['HeLLO'] = 5\n\n# Attribute-based access\ndel modifiable_items_attr_dict.UPPER\nmodifiable_items_attr_dict.HeLLO = 6\nprint(modifiable_items_attr_dict.hELlo)  # 6\nprint(modifiable_items_attr_dict)  # {'camelcase': 4, 'hello': 6}\n```\n\n## Use Case Example\n\nLet's say that there is a `.json` file that has Url hosts and their IP address.\nOur Goal is to load the json data into a dictionary like structure that will\nhave it's items modified during creation,\ninsertion, and retrieval.\nThis example highlights how to inherit from `ModifiableItemsDict` and had key\nand value modifiers.\n\n```python\nimport ipaddress\n\nfrom modifiable_items_dictionary import ModifiableItemsDict\n\n\nclass HostDict(ModifiableItemsDict):\n    _key_modifiers = [str.casefold, str.strip]\n    _value_modifiers = [ipaddress.ip_address]\n    # Or\n    # _value_modifiers = @staticmethod(ipaddress.ip_address)\n\n\nbrowsers = HostDict(\n    {\n        \"  GooGle.com    \": \"142.250.69.206\",\n        \" duckDUCKGo.cOM   \": \"52.250.42.157\",\n    }\n)\n\nprint(browsers)\n# {'google.com': IPv4Address('142.250.69.206'), 'duckduckgo.com': IPv4Address('52.250.42.157')}\n\n_old_browser = browsers.pop(\"  gOOgle.com  \")\n# or \n# del host_dict[\"   GooGle.com  \"]\n\nbrowsers[\"   BrAvE.com   \"] = \"2600:9000:234c:5a00:6:d0d2:780:93a1\"\n\nprint(browsers)\n# {'duckduckgo.com': IPv4Address('52.250.42.157'), 'brave.com': IPv6Address('2600:9000:234c:5a00:6:d0d2:780:93a1')}\n```\n\n### Threading Example\n\nIt is easy to add Threading to a `ModifiableItemsDict`.\n\n*NOTE: Since `ModifiableItemsDict` is not pickable it does not work with\nMultiprocessing. It only works with Multithreading.*\n\n```python\nimport multiprocessing.pool\nimport string\nimport time\n\nfrom modifiable_items_dictionary import ModifiableItemsDict\n\npool = multiprocessing.pool.ThreadPool(10)\n\n\ndef _slow_function(x):\n    time.sleep(.05)\n    return x\n\n\nclass TimeDictWithThreading(ModifiableItemsDict):\n    _key_modifiers = (_slow_function,)\n    _value_modifiers = (_slow_function,)\n    _map_function = pool.imap_unordered\n    # or if order matters\n    # _map_function = pool.imap\n\n\nclass TimeDict(ModifiableItemsDict):\n    _key_modifiers = (_slow_function,)\n    _value_modifiers = (_slow_function,)\n\n\niterable = {_letter: _index for _index, _letter in\n            enumerate(string.ascii_letters)}\n\n# Without Threading\nstart = time.perf_counter()\nTimeDict(iterable)\nend = time.perf_counter()\nprint(f\"{end - start:.2f} seconds\")  # 5.54 seconds\n\n# With Threading\nstart = time.perf_counter()\nTimeDictWithThreading(iterable)\nend = time.perf_counter()\nprint(f\"{end - start:.2f} seconds\")  # 0.64 seconds\n```\n\n## Reference\n\nThis project was inspired by Raymond\nHettinger ([rhettinger](https://github.com/rhettinger)).\n\n- Hettinger, R. (2023). (Advanced) Python For Engineers: Part 3.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftybruno%2Fmodifiable-items-dictionary","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftybruno%2Fmodifiable-items-dictionary","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftybruno%2Fmodifiable-items-dictionary/lists"}