Assignment & Mutation

By default, glom aims to safely return a transformed copy of your data. But sometimes you really need to transform an existing object.

When you already have a large or complex bit of nested data that you are sure you want to modify in-place, glom has you covered, with the assign() function, and the Assign() specifier type.

Assignment

Deeply assign within an existing structure, given a path and a value.

glom.assign(obj, path, val, missing=None)[source]

New in glom 18.3.0

The assign() function provides convenient “deep set” functionality, modifying nested data structures in-place:

>>> target = {'a': [{'b': 'c'}, {'d': None}]}
>>> _ = assign(target, 'a.1.d', 'e')  # let's give 'd' a value of 'e'
>>> pprint(target)
{'a': [{'b': 'c'}, {'d': 'e'}]}

Missing structures can also be automatically created with the missing parameter. For more information and examples, see the Assign specifier type, which this function wraps.

class glom.Assign(path, val, missing=None)[source]

New in glom 18.3.0

The Assign specifier type enables glom to modify the target, performing a “deep-set” to mirror glom’s original deep-get use case.

Assign can be used to perform spot modifications of large data structures when making a copy is not desired:

# deep assignment into a nested dictionary
>>> target = {'a': {}}
>>> spec = Assign('a.b', 'value')
>>> _ = glom(target, spec)
>>> pprint(target)
{'a': {'b': 'value'}}

The value to be assigned can also be a Spec, which is useful for copying values around within the data structure:

# copying one nested value to another
>>> _ = glom(target, Assign('a.c', Spec('a.b')))
>>> pprint(target)
{'a': {'b': 'value', 'c': 'value'}}

Another handy use of Assign is to deep-apply a function:

# sort a deep nested list
>>> target={'a':{'b':[3,1,2]}}
>>> _ = glom(target, Assign('a.b', Spec(('a.b',sorted))))
>>> pprint(target)
{'a': {'b': [1, 2, 3]}}

Like many other specifier types, Assign’s destination path can be a T expression, for maximum control:

# changing the error message of an exception in an error list
>>> err = ValueError('initial message')
>>> target = {'errors': [err]}
>>> _ = glom(target, Assign(T['errors'][0].args, ('new message',)))
>>> str(err)
'new message'

Assign has built-in support for assigning to attributes of objects, keys of mappings (like dicts), and indexes of sequences (like lists). Additional types can be registered through register() using the "assign" operation name.

Attempting to assign to an immutable structure, like a tuple, will result in a PathAssignError. Attempting to assign to a path that doesn’t exist will raise a PathAccessError.

To automatically backfill missing structures, you can pass a callable to the missing argument. This callable will be called for each path segment along the assignment which is not present.

>>> target = {}
>>> assign(target, 'a.b.c', 'hi', missing=dict)
{'a': {'b': {'c': 'hi'}}}

Deletion

Delete attributes from objects and keys from containers.

glom.delete(obj, path, ignore_missing=False)[source]

The delete() function provides “deep del” functionality, modifying nested data structures in-place:

>>> target = {'a': [{'b': 'c'}, {'d': None}]}
>>> delete(target, 'a.0.b')
{'a': [{}, {'d': None}]}

Attempting to delete missing keys, attributes, and indexes will raise a PathDeleteError. To ignore these errors, use the ignore_missing argument:

>>> delete(target, 'does_not_exist', ignore_missing=True)
{'a': [{}, {'d': None}]}

For more information and examples, see the Delete specifier type, which this convenience function wraps.

New in version 20.5.0.

class glom.Delete(path, ignore_missing=False)[source]

In addition to glom’s core “deep-get” and Assign’s “deep-set”, the Delete specifier type performs a “deep-del”, which can remove items from larger data structures by key, attribute, and index.

>>> target = {'dict': {'x': [5, 6, 7]}}
>>> glom(target, Delete('dict.x.1'))
{'dict': {'x': [5, 7]}}
>>> glom(target, Delete('dict.x'))
{'dict': {}}

If a target path is missing, a PathDeleteError will be raised. To ignore missing targets, use the ignore_missing flag:

>>> glom(target, Delete('does_not_exist', ignore_missing=True))
{'dict': {}}

Delete has built-in support for deleting attributes of objects, keys of dicts, and indexes of sequences (like lists). Additional types can be registered through register() using the "delete" operation name.

New in version 20.5.0.

Exceptions

class glom.PathAssignError(exc, path, dest_name)[source]

This GlomError subtype is raised when an assignment fails, stemming from an assign() call or other Assign usage.

One example would be assigning to an out-of-range position in a list:

>>> assign(["short", "list"], Path(5), 'too far')  
Traceback (most recent call last):
...
PathAssignError: could not assign 5 on object at Path(), got error: IndexError(...

Other assignment failures could be due to assigning to an @property or exception being raised inside a __setattr__().

class glom.PathDeleteError(exc, path, dest_name)[source]

This GlomError subtype is raised when an assignment fails, stemming from an delete() call or other Delete usage.

One example would be deleting an out-of-range position in a list:

>>> delete(["short", "list"], Path(5))
Traceback (most recent call last):
...
PathDeleteError: could not delete 5 on object at Path(), got error: IndexError(...

Other assignment failures could be due to deleting a read-only @property or exception being raised inside a __delattr__().