[![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://GitHub.com/Naereen/StrapDown.js/graphs/commit-activity)
[![Code Style: Blue](https://img.shields.io/badge/code%20style-blue-0000ff.svg)](https://github.com/psf/blue)
[![License: MIT](https://img.shields.io/badge/License-MIT-blueviolet.svg)](https://opensource.org/licenses/MIT)
[![codecov](https://codecov.io/gh/tybruno/modifiable-items-dictionary/branch/main/graph/badge.svg?token=ZO94EJFI3G)](https://codecov.io/gh/tybruno/modifiable-items-dictionary)
[![Pylint](https://img.shields.io/badge/Pylint-10.0%2F10-green)](10.0/10)
[![Mypy](https://img.shields.io/badge/Mypy-checked-blue)](10.0/10)
# modifiable-items-dict
A simple, fast, typed, and tested implementation for a python3.6+ Modifiable Items dictionary. `ModifiableItemsDict`
extends `dict` with the ability to modify keys and values on creation, insertion, and retrieval. This class extends and
maintains the original functionality of the builtin `dict`.
In addition to `ModifiableItemsDict`, this implementation also includes `ModifiableItemsAttrDict`,
a class that inherits from `ModifiableItemsDict` and adds attribute-style access to dictionary items.
This means you can access dictionary items as if they were attributes of the object, providing an alternative,
often more readable way to access dictionary items.
Like `ModifiableItemsDict`, `ModifiableItemsAttrDict` also allows modification of keys and values on creation,
insertion, and retrieval, ensuring consistency and flexibility in handling dictionary items.
#### Key Features:
* **Easy**: Flexible and easy to add Key and/or Value modifiers to
the `ModifiableItemsDict` and `ModifiableItemsAttrDict`.
* **Attribute Access**: `ModifiableItemsAttrDict` allows attribute-style access to dictionary items, providing an
alternative, often more readable way to access dictionary items.
* **Great Developer Experience**: Being fully typed makes it great for editor
support.
* **Fully Tested**: Our test suite fully tests the functionality to ensure
that `ModifiableItemsDict` and `ModifiableItemsAttrDict` run as expected.
* **There is More!!!**:
* [CaselessDict](https://github.com/tybruno/caseless-dictionary): `CaselessDict`
extends `ModifiableItemsDict` and `ModifiableItemsAttrDict` which
is a `CaselessDict` and `CaselessAttrDict` that ignores the case of the keys.
## Installation
`pip install modifiable-items-dictionary`
## ModifiableItemsDict and ModifiableItemsAttrDict
The `ModifiableItemsDict` and `ModifiableItemsAttrDict` classes are part of the `modifiable_items_dictionary` module.
They provide advanced dictionary functionalities with additional features for modifying keys and values.
### ModifiableItemsDict
The `ModifiableItemsDict` class is a dictionary class that allows modification of keys and values during creation,
insertion, and retrieval. It provides the following features:
- **Key Modifiers**: This class allows you to specify functions that modify keys on creation, insertion, and retrieval.
This can be useful for ensuring that all keys adhere to a certain format or standard.
- **Value Modifiers**: Similar to key modifiers, you can also specify functions that modify values. This can be useful
for transforming or sanitizing data as it's added to the dictionary.
- **Thread Safety**: This class is designed to be thread-safe, making it suitable for use in multi-threaded
applications.
- **Fully Tested**: The functionality of this class is fully tested to ensure reliable operation.
#### Example
```python
from modifiable_items_dictionary import ModifiableItemsDict
def _add_1(_value):
if isinstance(_value, int):
_value += 1
return _value
def _case_fold_string(_value):
if isinstance(_value, str):
_value = _value.casefold()
return _value
ModifiableItemsDict._key_modifiers = [str.casefold]
ModifiableItemsDict._value_modifiers = (
_add_1, _case_fold_string)
# Or
# ModifiableItemsDict._key_modifiers = staticmethod(str.casefold)
# ModifiableItemsDict._value_modifiers = [_case_fold_string, _add_1]
modifiable_items_dictionary = ModifiableItemsDict(
{"lower": 1, "UPPER": 2},
CamelCase=3,
snake_case="FoUR"
)
print(
modifiable_items_dictionary
) # {'lower': 2, 'upper': 3, 'camelcase': 4, 'snake_case': 'four'}
del modifiable_items_dictionary["LOWER"]
del modifiable_items_dictionary["UPPER"]
modifiable_items_dictionary.pop("SNAKE_CAse")
modifiable_items_dictionary["HeLLO"] = 5
print(modifiable_items_dictionary) # {'camelcase': 4, 'hello': 6}
```
### ModifiableItemsAttrDict
The `ModifiableItemsAttrDict` class is an extension of the `ModifiableItemsDict` class, inheriting all its features
while adding attribute-style access to dictionary items. This class maintains the same key and value modifiers, ensuring
consistency and flexibility in handling dictionary items.
Like `ModifiableItemsDict`, `ModifiableItemsAttrDict` is designed with thread safety in mind, making it suitable for use
in multi-threaded applications. It is also fully tested to ensure reliable operation.
In addition to these features, `ModifiableItemsAttrDict` offers:
- **Attribute-style Access**: This feature allows you to access dictionary items as if they were attributes of the
object. For example, you can use `dict.key` instead of `dict['key']`. This provides an alternative, often more
readable way to access dictionary items, while still retaining the traditional dictionary access methods.
This combination of features makes `ModifiableItemsAttrDict` a powerful tool for managing dictionaries in a way that is
both flexible and intuitive, while maintaining the robustness and reliability of the `ModifiableItemsDict` class.
#### Example
```python
import modifiable_items_dictionary
def _add_1(_value):
if isinstance(_value, int):
_value += 1
return _value
def _case_fold_string(_value):
if isinstance(_value, str):
_value = _value.casefold()
return _value
modifiable_items_dictionary.ModifiableItemsAttrDict._key_modifiers = [
str.casefold
]
modifiable_items_dictionary.ModifiableItemsAttrDict._value_modifiers = (
_add_1,
_case_fold_string,
)
modifiable_items_attr_dict = (
modifiable_items_dictionary.ModifiableItemsAttrDict(
{'lower': 1, 'UPPER': 2}, CamelCase=3, snake_case='FoUR'
)
)
print(
modifiable_items_attr_dict
) # {'lower': 2, 'upper': 3, 'camelcase': 4, 'snake_case': 'four'}
# Key-based access
del modifiable_items_attr_dict['LOWER']
modifiable_items_attr_dict['HeLLO'] = 5
# Attribute-based access
del modifiable_items_attr_dict.UPPER
modifiable_items_attr_dict.HeLLO = 6
print(modifiable_items_attr_dict.hELlo) # 6
print(modifiable_items_attr_dict) # {'camelcase': 4, 'hello': 6}
```
## Use Case Example
Let's say that there is a `.json` file that has Url hosts and their IP address.
Our Goal is to load the json data into a dictionary like structure that will
have it's items modified during creation,
insertion, and retrieval.
This example highlights how to inherit from `ModifiableItemsDict` and had key
and value modifiers.
```python
import ipaddress
from modifiable_items_dictionary import ModifiableItemsDict
class HostDict(ModifiableItemsDict):
_key_modifiers = [str.casefold, str.strip]
_value_modifiers = [ipaddress.ip_address]
# Or
# _value_modifiers = @staticmethod(ipaddress.ip_address)
browsers = HostDict(
{
" GooGle.com ": "142.250.69.206",
" duckDUCKGo.cOM ": "52.250.42.157",
}
)
print(browsers)
# {'google.com': IPv4Address('142.250.69.206'), 'duckduckgo.com': IPv4Address('52.250.42.157')}
_old_browser = browsers.pop(" gOOgle.com ")
# or
# del host_dict[" GooGle.com "]
browsers[" BrAvE.com "] = "2600:9000:234c:5a00:6:d0d2:780:93a1"
print(browsers)
# {'duckduckgo.com': IPv4Address('52.250.42.157'), 'brave.com': IPv6Address('2600:9000:234c:5a00:6:d0d2:780:93a1')}
```
### Threading Example
It is easy to add Threading to a `ModifiableItemsDict`.
*NOTE: Since `ModifiableItemsDict` is not pickable it does not work with
Multiprocessing. It only works with Multithreading.*
```python
import multiprocessing.pool
import string
import time
from modifiable_items_dictionary import ModifiableItemsDict
pool = multiprocessing.pool.ThreadPool(10)
def _slow_function(x):
time.sleep(.05)
return x
class TimeDictWithThreading(ModifiableItemsDict):
_key_modifiers = (_slow_function,)
_value_modifiers = (_slow_function,)
_map_function = pool.imap_unordered
# or if order matters
# _map_function = pool.imap
class TimeDict(ModifiableItemsDict):
_key_modifiers = (_slow_function,)
_value_modifiers = (_slow_function,)
iterable = {_letter: _index for _index, _letter in
enumerate(string.ascii_letters)}
# Without Threading
start = time.perf_counter()
TimeDict(iterable)
end = time.perf_counter()
print(f"{end - start:.2f} seconds") # 5.54 seconds
# With Threading
start = time.perf_counter()
TimeDictWithThreading(iterable)
end = time.perf_counter()
print(f"{end - start:.2f} seconds") # 0.64 seconds
```
## Reference
This project was inspired by Raymond
Hettinger ([rhettinger](https://github.com/rhettinger)).
- Hettinger, R. (2023). (Advanced) Python For Engineers: Part 3.
Raw data
{
"_id": null,
"home_page": "https://github.com/tybruno/modifiable-items-dictionary",
"name": "modifiable-items-dictionary",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.6",
"maintainer_email": null,
"keywords": "python dict attribute dictionary attrdict mapping key-mangling value-mangling",
"author": "Tyler Bruno",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/e3/6f/9d8ea5bb307e1ee26c7d583136425adfe350176e95cfcc42581a572d4cea/modifiable_items_dictionary-3.0.2.tar.gz",
"platform": null,
"description": "[![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",
"bugtrack_url": null,
"license": "MIT",
"summary": "Typed and Tested Modifiable Items Dict and ModifiableItemsAttrDict which allow keys and values to be modified at run time. ModifiableItemsAttrDict additionally provides attribute-style access to dictionary items.",
"version": "3.0.2",
"project_urls": {
"Homepage": "https://github.com/tybruno/modifiable-items-dictionary"
},
"split_keywords": [
"python",
"dict",
"attribute",
"dictionary",
"attrdict",
"mapping",
"key-mangling",
"value-mangling"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "8e0f795ffbbe0989e3100e0e9ac7825e7b4b71a102c232a12f4d53991871e302",
"md5": "3528c72c9f72e07c83abca3084e261eb",
"sha256": "ed0ff334ea95981c5e3d01c5e367396c92b0037c6a8c3caa06febc19016f013c"
},
"downloads": -1,
"filename": "modifiable_items_dictionary-3.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "3528c72c9f72e07c83abca3084e261eb",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.6",
"size": 9607,
"upload_time": "2024-06-20T21:04:10",
"upload_time_iso_8601": "2024-06-20T21:04:10.431476Z",
"url": "https://files.pythonhosted.org/packages/8e/0f/795ffbbe0989e3100e0e9ac7825e7b4b71a102c232a12f4d53991871e302/modifiable_items_dictionary-3.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "e36f9d8ea5bb307e1ee26c7d583136425adfe350176e95cfcc42581a572d4cea",
"md5": "6965b4189d9d8efca45a5fa63b82ffe1",
"sha256": "1f3d2ba84e0be5b7c523c5304e53f3663415aacc49517d18f0d578429f17e20a"
},
"downloads": -1,
"filename": "modifiable_items_dictionary-3.0.2.tar.gz",
"has_sig": false,
"md5_digest": "6965b4189d9d8efca45a5fa63b82ffe1",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.6",
"size": 13925,
"upload_time": "2024-06-20T21:04:14",
"upload_time_iso_8601": "2024-06-20T21:04:14.251895Z",
"url": "https://files.pythonhosted.org/packages/e3/6f/9d8ea5bb307e1ee26c7d583136425adfe350176e95cfcc42581a572d4cea/modifiable_items_dictionary-3.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-06-20 21:04:14",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "tybruno",
"github_project": "modifiable-items-dictionary",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "modifiable-items-dictionary"
}