attrmap is an open source tool with read-only protection to help users get rid of dictionary in Python.
attrmap maps the dict to an object of AttrMap, so users can avoid using the annoying [""] syntax.
Users are welcome to report issues or request new features.
The API references can be found here.
- 2023-10-06: Put the package on conda-forge (Issue #3).
- 2023-10-06: Fix the missing docs problem.
- 2022-12-20: Fix the annoying warning when creating an AttrMap instance.
- 2022-08-27: Add utilities for AttrMap, see docs.
- 2022-08-27: Add deprecated warnings.
- 2022-08-13: Fix the
delattrbug, users can delete an item viadel obj.attrwhen theAttrMapobject is modifiable. - 2022-08-13: Fix the improper use of type hint, now
attrmapis available for python>=3.6. - 2022-08-13: Update the document.
You can install attrmap via pip:
pip install -U attrmapAssuming you have an instance of dict, then you can build an object of AttrMap as follows:
from attrmap import AttrMap
import attrmap.utils as au
CONFIGS = {
"attr1": 1,
"attr2": ["hello", " ", "world"],
"attr3": {
"subattr1": "subattr1",
"subattr2": {
"subsubattr1": "subsubattr1",
}
}
}
configs = AttrMap(CONFIGS)
# Set the object unmodifiable.
configs = au.convert_state(configs, read_only=True)
# Equivalent to:
# au.convert_state(configs, read_only=True)
print(configs) # The outputs is more human readable.
# Object Contains Following Attributes
# attr1: 1
# attr2: ['hello', ' ', 'world']
# attr3:
# subattr1: subattr1
# subattr2:
# subsubattr1: subsubattr1You can also assign the attributes and their values in a more simple way:
# Assume you have import AttrMap
# Create an empty AttrMap object.
configs = AttrMap()
configs.attr1 = 1
configs.attr2 = ["hello", " ", "world"]
configs.attr3.subattr1 = "subattr1"
configs.attr3.subattr2.subsubattr1 = "subsubattr1"
print(configs)
# Object Contains Following Attributes
# attr1: 1
# attr2: ['hello', ' ', 'world']
# attr3:
# subattr1: subattr1
# subattr2:
# subsubattr2: subsubattr1You can convert the AttrMap object to Python dict anytime:
configs_dict = au.todict(configs)
print(configs_dict)
# {'attr1': 1, 'attr2': ['hello', ' ', 'world'], 'attr3': {'subattr1': 'subattr1', 'subattr2': {'subsubattr1': 'subsubattr1'}}}
print(type(configs_dict))
# <class 'dict'>
# AttrMap object doesn't store the original dict.
print(id(configs_dict))
# 139881853477376
print(id(CONFIGS))
# 139881853478464
# But it do not change the items:
print(configs_dict == CONFIGS)
# Trueattrmap has the read-only protection to protect you from unintentional modification:
# Assume you have the above AttrMap object named configs
# Now set the AttrMap object as read-only.
configs = au.convert_state(configs, read_only=True)
# Try to create a new attribute.
configs.attr4 = "unintentional modification"
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "/xxxx/attrmap.py", line 558, in __setattr__
# self._check_modifiable()
# File "/xxxx/attrmap.py", line 643, in _check_modifiable
# raise AttributeError(
# AttributeError: Modifying the attributes of a read-only AttrMap instance is not allowed.
# Try to modify the value of an existing attribute:
configs.attr1 = "unintentional modification"
# Traceback (most recent call last):
# File "<stdin>", line 1, in <module>
# File "/xxxx/attrmap.py", line 558, in __setattr__
# self._check_modifiable()
# File "/xxxx/attrmap.py", line 643, in _check_modifiable
# raise AttributeError(
# AttributeError: Modifying the attributes of a read-only AttrMap instance is not allowed.The read-only protection is quite useful when you use the AttrMap object to store the configuration of any system, any unintentional modification is not allowed. If you want to update the attribute's value, just set the read_only of the AttrMap instance as False via au.convert_state(obj, read_only=False).
If the AttrMap object should be unmodifiable, setting the object as read-only is recommended.
You can also build an AttrMap instance from a .json or .yaml file. For example, assume you have a file.json file:
{
"language": ["python", "cpp", "java"],
"value": [["one", "two"]],
"structure":{
"tree":["left tree", "right tree"]
}
}Then you can build AttrMap object via:
from attrmap import AttrMap
configs = AttrMap(path2file="/PATH_TO_YOUR_DIRECTORY/file.json") # .yaml file works too.
print(configs)
# Object Contains Following Attributes
# language: ['python', 'cpp', 'java']
# value: [['one', 'two']]
# structure:
# tree: ['left tree', 'right tree']NOTE: The read-only protection should be explicitly enabled, AttrMap assumes you are still setting the attributes and their values.
- The API reference is missing, I will try to fix it in the next few days.
- Attributes starting with
_might be conflict withAttrMappreserved methods/properties. Attributes can still be accessed via dict-style ([""]), but the attribute-style will return the "protected" (not the term of python, only means it's not "public") method such as_build_from_dict. - Some publicly available properties and methods are reserved, they can only accessed via the dict-style.
Open bash shell and execute:
bash -i ./auto_test.shAttrMap is an open source tool under Apache 2.0 license.