Skip to main content

attrbox: attribute-based data structures

Otto the Otter
Otto the Otter

Build PyPI Supported Python Versions

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

The vendorized version of docopt-ng is also licensed under the MIT License.

Metadata

Release files for attrbox 0.1.6

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for attrbox 0.1.6
File Size Uploaded Provenance Actions
attrbox-0.1.6.tar.gz 32.3 kB Without provenance Details for attrbox-0.1.6.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for attrbox 0.1.6
File Interpreter ABI Platform Actions
attrbox-0.1.6-py3-none-any.whl Python 3 none any Details for attrbox-0.1.6-py3-none-any.whl

Total release size: 63.2 kB

Release files / attrbox-0.1.6.tar.gz

Download URL attrbox-0.1.6.tar.gz
Size 32.3 kB
Tags Source
SHA-256 checksum
How to use checksums
499098f61f32209b46e82cc885c1d3a2e078fbf3c2b7381b7980510f22ff05c9
BLAKE2b-256 checksum
How to use checksums
4f647b33735c69bb07086383e8c6a05ad222f21bfb129ce494e8d5f74c35f236
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.2

Release files / attrbox-0.1.6-py3-none-any.whl

Download URL attrbox-0.1.6-py3-none-any.whl
Size 30.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d935533c3057bcc90bc9a68c54c455a930e22780e0679b30cafe28bee0140a24
BLAKE2b-256 checksum
How to use checksums
cdb9f3e7a821647bff14e416a2da6130cdbff14c4f3be3c9657db1f06e71d2c2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.1.0 CPython/3.13.2

Security for attrbox 0.1.6

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page