Skip to main content

Recursively convert lists to tuples, sets to frozensets, dicts to mappingproxy etc.

Project description

Recursively convert list to tuple, set to frozenset, dict to mappingproxy etc.

Example usage:

   import freezedata

   data = [{'a': [1,2,3], 'b': {1,2,3}}, {1:1, 2:2, 3:3}]
   frozendata = freezedata.freeze_data(data)
   print(frozendata)
   >> (mappingproxy({'a': (1, 2, 3), 'b': frozenset({1, 2, 3})}),
mappingproxy({1: 1, 2: 2, 3: 3}))

This is a read-only data structure, that is; there is no direct way to alter this data structure from within frozendata itself (without using some special modules (gc, inspect)).

For example:

frozendata[0]['a'][0] = 4
>> TypeError: 'tuple' object does not support item assignment
del frozendata[1][1]
>> TypeError: 'mappingproxy' object does not support item deletion

Notice: Since a mappingproxy is not hashable, frozen data structures containing mappingproxy (i.e. based on dict) will not be hashable either:

hash(frozendata)
>> TypeError: unhashable type: 'mappingproxy'

On the other hand, if the frozen data structure contains only hashable elements, the whole structure will be hashable (and immutable) as well:

frozendata = freezedata.freeze_data([[1,2,3], {4,5,6}])
print(frozendata)
>> ((1, 2, 3), frozenset({4, 5, 6}))
hash(frozendata)
>> -11948691520864899

Relaxing requirements (accepting functions, modules, classes and instances):

Functions, modules, (user-created) classes and instances are mutable in Python, and therefore neither immutable or read-only. By default, using these will result in errors, but setting parameter allow as one, several or all of functions, modules , classes and instances, these can be used in the new new data structure.

Functions have mutable attributes in Python, but sometimes you still want a function in a new data structure that won’t affect the parent data structure / parent function. By setting allow='functions' or allow=['functions'], the new data structure will contain a copy of the included functions and its public attributes:

def func(n):
    return n*2
func.a = 'a'
data = [func]
frozendata = freezedata.freeze_data(data, allow='functions')
data[0] == frozendata[0]
>> False
frozendata[0].a = 'b'
print(data[0].a, frozendata[0].a)
>> a b

modules will be converted to a namedtuple, if you’re freezing a module. If a module is in the data structure, but it’s not top level, an error will by default be raised. If allow={'modules'} is set, non-top-level modules will be allowed and kept unchanged.

classes and class instances may be converted into namedtuple and used in the frozen data structure by setting allow={'classes', 'instances} or only one, e.g. allow={'classes'}, as needed. By converting to namedtuple, information may be lost, as attributes with leading underscores will be ignored:

class Test:
    a = 1
    def __init__(self, a):
        self.a = a
test = Test(2)
frozendata = freezedata.freeze_data([Test, test], allow={'classes', 'instances'})
print(frozendata)
>> (Test(a=1), Test(a=2))
print(type(frozendata[0]), type(frozendata[1]))
>> <class 'freezedata.freezedata.Test'> <class 'freezedata.freezedata.Test'>  # two namedtuples

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

freezedata-2.2.7.tar.gz (5.0 kB view hashes)

Uploaded Source

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page