Last updated:
0 purchases
attrbox 0.1.5
attrbox
Attribute-based data structures.
Changelog - Issues - Documentation
Why?
I have common use cases where I want to improve python's dict and list:
AttrDict: attribute-based dict with better merge and deep value access
AttrList: list that 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 dict similar to accessing properties in JavaScript: thing.prop means thing["prop"] for get / set / delete.
No KeyError: if a key is missing, just return None (like dict.get()).
Deep Indexing: use a list of keys and int to 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 actual int to index across list objects.
Deep Merge: combine two dict objects by extending deeply-nested keys where possible. This is different than the new dict union 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
Read more about AttrDict
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]
Read more about AttrList
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.
Read more about attrbox.env
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).
Read more about JSend
License
MIT License
For personal and professional use. You cannot resell or redistribute these repositories in their original state.
There are no reviews.