Attribute-based data structures.
Project description
attrbox: attribute-based data structures
Why?
I have common use cases where I want to improve python's dict and list:
AttrDict: attribute-baseddictwith better merge and deep value accessAttrList:listthat broadcasts operations to its members- Environment: reading environment files
- Configuration: loading command-line arguments and configuration files
JSend: sending JSON responses
Install
python -m pip install attrbox
AttrDict
AttrDict features:
-
Attribute Syntax for
dictsimilar to accessing properties in JavaScript:thing.propmeansthing["prop"]for get / set / delete. -
No
KeyError: if a key is missing, just returnNone(likedict.get()). -
Deep Indexing: use a list of keys and
intto get and set deeply nested values. This is similar to lodash.get except that only the array-like syntax is supported and you must use actualintto index acrosslistobjects. -
Deep Merge: combine two
dictobjects by extending deeply-nested keys where possible. This is different than the newdictunion operator (PEP 584).
from attrbox import AttrDict
items = AttrDict(a=1, b=[{"c": {"d": 5}}], e={"f": {"g": 7}})
items.a
# => 1
items.x is None
# => True
items.x = 10
items['x']
# => 10
items.get(["b", 0, "c", "d"])
# => 5
items <<= {"e": {"f": {"g": 20, "h": [30, 40]}}}
items.e.f.g
# => 20
items[['e', 'f', 'h', 1]]
# => 40
AttrList
AttrList provides member broadcast: performing operations on the list performs the operation on all the items in the list. I typically use this to achieve the Composite design pattern.
from attrbox import AttrDict, AttrList
numbers = AttrList([complex(1, 2), complex(3, 4), complex(5, 6)])
numbers.real
# => [1.0, 3.0, 5.0]
words = AttrList(["Apple", "Bat", "Cat"])
words.lower()
# => ['apple', 'bat', 'cat']
items = AttrList([AttrDict(a=1, b=2), AttrDict(a=5)])
items.a
# => [1, 5]
items.b
# => [2, None]
Environment
attrbox.env is similar to python-dotenv, but uses the AttrDict ability to do deep indexing to allow for things like dotted variable names. Typically, you'll use it by calling attrbox.load_env() which will find the nearest .env file and load it into os.environ.
Configuration
attrbox supports loading configuration files from .json, .toml, and .env files. By default, load_config() looks for a key imports and will recursively import those files (relative to the current file) before loading the rest of the current file (data is merged using AttrDict). This allows you to create templates or smaller configurations that build up to a larger configuration.
For CLI applications, attrbox.parse_docopt() let's you use the power of docopt with the flexibility of AttrDict. By default, --config and <config> arguments will load the file using the load_config()
"""Usage: prog.py [--help] [--version] [-c CONFIG] --file FILE
Options:
--help show this message and exit
--version show the version number and exit
-c, --config CONFIG load this configuration file (supported: .toml, .json, .env)
--file FILE the file to process
"""
def main():
args = parse_docopt(__doc__, version=__version__)
args.file # has the value of --file
if __name__ == "__main__":
main()
Building on top of docopt we strip off leading dashes and convert them to underscores so that we can access the arguments as AttrDict attributes.
Read more about attrbox.config
JSend
JSend is an approximate implementation of the JSend specification that makes it easy to create standard JSON responses. The main difference is that I added an ok attribute to make it easy to tell if there was a problem (fail or error).
from attrbox import JSend
def some_function(arg1):
result = JSend() # default is "success"
if not is_good(arg1):
# fail = controlled problem
return result.fail(message="You gone messed up.")
try:
result.success(data=process(arg1))
except Exception:
# error = uncontrolled problem
return result.error(message="We have a problem.")
return result
Because the JSend object is an AttrDict, it acts like a dict in every other respect (e.g., it is JSON-serializable).
License
The vendorized version of docopt-ng is also licensed under the MIT License.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file attrbox-0.1.6.tar.gz.
File metadata
- Download URL: attrbox-0.1.6.tar.gz
- Upload date:
- Size: 32.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
499098f61f32209b46e82cc885c1d3a2e078fbf3c2b7381b7980510f22ff05c9
|
|
| MD5 |
36b026353799b217b46adbad34bba41e
|
|
| BLAKE2b-256 |
4f647b33735c69bb07086383e8c6a05ad222f21bfb129ce494e8d5f74c35f236
|
File details
Details for the file attrbox-0.1.6-py3-none-any.whl.
File metadata
- Download URL: attrbox-0.1.6-py3-none-any.whl
- Upload date:
- Size: 30.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d935533c3057bcc90bc9a68c54c455a930e22780e0679b30cafe28bee0140a24
|
|
| MD5 |
068de25e1a05f3f83f48e5b0eda03928
|
|
| BLAKE2b-256 |
cdb9f3e7a821647bff14e416a2da6130cdbff14c4f3be3c9657db1f06e71d2c2
|