Skip to main content

traversify

Handy python classes for manipulating json data, providing syntactic sugar for less verbose, easier to write code.

Traverser class allows one to:

  • traverse complex trees of data with dotted syntax rather than the verbose dictionary dereferencing.
  • treat nodes on the tree as lists even if they are singleton dictionaries, eliminating a lot of type-checking code.
  • add or delete branches of the tree with simple dotted syntax.
  • treat missing keys on the tree as None rather than throwing a key exception, much as JavaScript returns undefined.
  • linkage to Filter class (defined next) for powerful tree comparisons or tree pruning.

Filter class allows one to:

  • define a set of criteria for comparing two partially incongruous trees by limiting the sets of fields compared.
  • apply said criteria to prune a tree of any unwanted fields.

Traverser

Pass tree data to Traverser, either as a list, dictionary, json string or any class offering a json method, and the resultant object will provide the syntactic sugar for traversing with dotted syntax, treating singleston nodes as lists:

>>> from traversify import Traverser
>>> obj = Traverser({'id': 1, 'username': 'jdoe'})
>>> obj.id
1
>>> obj.username
'jdoe'
>>> obj.bad_key is None
True
>>> [node.id for node in obj]
[1]
>>> obj[0].id
1
>>> {'id': 1, 'username': 'jdoe'} in obj
True

Not only can singletons be addressed as lists, but append and extend methods are available to turn singletons into lists on the fly:

>>> obj = Traverser({'id': 1})
>>> obj.append({'id': 2})
>>> obj.extend([{'id': 3, 'id': 4}])
>>> [node.id for node in obj]
[1, 2, 3, 4]

At any time, a Traverser instance will return the underlying value when called:

>>> obj = Traverser({'id': 1})
>>> obj()
{'id': 1}

The tree can be updated using dotted syntax. Note that by default, a Traverser instance makes a deepcopy of the json data so that there are no unintended side effects:

>>> data = {'id': 1, 'username': 'jdoe'}
>>> obj = Traverser(data)
>>> obj.id = 2
>>> del obj.username
>>> obj()
{'id': 2}
>>> data
{'id': 1, 'username': 'jdoe'}

However, if the side-effect of updating the data passed is desired (perhaps due to memory constaints), then pass deepcopy=False:

>>> data = {'id': 1}
>>> obj = Traverser(data, deepcopy=False)
>>> obj.id = 2
>>> obj()
{'id': 2}
>>> data
{'id': 2}

In case there are keys that are not identifiers, then dictionary dereferencing can still be used:

>>> obj = Traverser({'@xsi.type': 'textarea'})
>>> obj['@xsi.type']
'textarea'

The get method allows traversing multiple levels in one call, using dots to set off the levels:

>>> obj = Traverser({'root': {'username': 'any'}})
>>> obj.get('root.username')
'any'

Also, the get method supports dot-escaping so that keys containing dots can still be traversed:

>>> obj = Traverser({'@xsi.type': 'textarea'})
>>> obj.get('@xsi..type')
'textarea'

There's a set method that will update a node multiple levels down and even build out branches that aren't already there:

>>> obj = Traverser({'stats': {'id': 1}})
>>> obj.set('stats.id', 2)
>>> obj()
{'stats': {'id': 2}}
>>> obj.set('users.0.username', 'any')
>>> obj()
{'stats': {'id': 2}, 'users': [{'username': 'any'}]}

To save the trouble of importing json and using dumps, there's a handy to_json method:

>>> obj = Traverser({'id': 1})
>>> obj.to_json()
'{"id": 1}'

Filter

Often one needs to compare two trees without taking into account irrelavant fields, like when records in the tree have ids, but a new record doesn't have it yet. Filter provides a way to make this less verbose by providing blacklist and whitelist attributes for controlled comparison:

>>> from traversify import Traverser, Filter
>>> id_exclude_filter = Filter(blacklist='id')
>>> record = Traverser({'id': 1, 'username': 'jdoe'})
>>> id_exclude_filter.are_equal(record, {'username': 'jdoe'})
True

The same filter can be used to prune a tree of its unwanted fields:

>>> id_exclude_filter.prune(record)
>>> record()
{'username': 'jdoe'}

If a filter is passed while creating a Traverser instance, then ==, in and the prune() method will use it to do the comparison or pruning:

>>> record = Traverser({'id': 1, 'username': 'jdoe'}, filter=Filter(blacklist='id'))
>>> record == {'username': 'jdoe'}
True
>>> {'username': 'jdoe'} in record
True
>>> record.prune()
>>> record()
{'username': 'jdoe'}

Traverser's prune method will accept a filter to override the default (or supply one not already supplied):

>>> record = Traverser({'id': 1, 'username': 'jdoe'})
>>> record.prune(filter=Filter(blacklist='id'))
>>> record()
{'username': 'jdoe'}

Metadata

Release files for traversify 1.1.2

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

Source distribution (sdist)

Source distribution for traversify 1.1.2
File Size Uploaded Provenance Actions
traversify-1.1.2.tar.gz 5.5 kB Without provenance Details for traversify-1.1.2.tar.gz

Built distribution (wheel)

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

Total release size: 25.8 kB

Release files / traversify-1.1.2.tar.gz

Download URL traversify-1.1.2.tar.gz
Size 5.5 kB
Tags Source
SHA-256 checksum
How to use checksums
d127880c5f8d5a3be0651fcfc655996bede2434b8eedc9a9b7f67710f882e70b
BLAKE2b-256 checksum
How to use checksums
2b1fc554628d82cf58ee97c4b5a22c91d43bafc4477f78ed933e9736b5810ed9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.8

Release files / traversify-1.1.2-py3-none-any.whl

Download URL traversify-1.1.2-py3-none-any.whl
Size 20.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
66955ea198270b499dd6b1f7af49b2baf794572c4b74e228b4e563451f8619f2
BLAKE2b-256 checksum
How to use checksums
076730c6e6393b8ed82be287a7ad3d99f73c66fc08837faa0309a502ef9afde7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/1.13.0 pkginfo/1.5.0.1 requests/2.21.0 setuptools/40.6.2 requests-toolbelt/0.9.1 tqdm/4.31.1 CPython/3.6.8

Security for traversify 1.1.2

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