Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pyrsistent/_helpers.py: 20%
35 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-07-01 06:54 +0000
1from functools import wraps
2from pyrsistent._pmap import PMap, pmap
3from pyrsistent._pset import PSet, pset
4from pyrsistent._pvector import PVector, pvector
6def freeze(o, strict=True):
7 """
8 Recursively convert simple Python containers into pyrsistent versions
9 of those containers.
11 - list is converted to pvector, recursively
12 - dict is converted to pmap, recursively on values (but not keys)
13 - set is converted to pset, but not recursively
14 - tuple is converted to tuple, recursively.
16 If strict == True (default):
18 - freeze is called on elements of pvectors
19 - freeze is called on values of pmaps
21 Sets and dict keys are not recursively frozen because they do not contain
22 mutable data by convention. The main exception to this rule is that
23 dict keys and set elements are often instances of mutable objects that
24 support hash-by-id, which this function can't convert anyway.
26 >>> freeze(set([1, 2]))
27 pset([1, 2])
28 >>> freeze([1, {'a': 3}])
29 pvector([1, pmap({'a': 3})])
30 >>> freeze((1, []))
31 (1, pvector([]))
32 """
33 typ = type(o)
34 if typ is dict or (strict and isinstance(o, PMap)):
35 return pmap({k: freeze(v, strict) for k, v in o.items()})
36 if typ is list or (strict and isinstance(o, PVector)):
37 curried_freeze = lambda x: freeze(x, strict)
38 return pvector(map(curried_freeze, o))
39 if typ is tuple:
40 curried_freeze = lambda x: freeze(x, strict)
41 return tuple(map(curried_freeze, o))
42 if typ is set:
43 # impossible to have anything that needs freezing inside a set or pset
44 return pset(o)
45 return o
48def thaw(o, strict=True):
49 """
50 Recursively convert pyrsistent containers into simple Python containers.
52 - pvector is converted to list, recursively
53 - pmap is converted to dict, recursively on values (but not keys)
54 - pset is converted to set, but not recursively
55 - tuple is converted to tuple, recursively.
57 If strict == True (the default):
59 - thaw is called on elements of lists
60 - thaw is called on values in dicts
62 >>> from pyrsistent import s, m, v
63 >>> thaw(s(1, 2))
64 {1, 2}
65 >>> thaw(v(1, m(a=3)))
66 [1, {'a': 3}]
67 >>> thaw((1, v()))
68 (1, [])
69 """
70 typ = type(o)
71 if isinstance(o, PVector) or (strict and typ is list):
72 curried_thaw = lambda x: thaw(x, strict)
73 return list(map(curried_thaw, o))
74 if isinstance(o, PMap) or (strict and typ is dict):
75 return {k: thaw(v, strict) for k, v in o.items()}
76 if typ is tuple:
77 curried_thaw = lambda x: thaw(x, strict)
78 return tuple(map(curried_thaw, o))
79 if isinstance(o, PSet):
80 # impossible to thaw inside psets or sets
81 return set(o)
82 return o
85def mutant(fn):
86 """
87 Convenience decorator to isolate mutation to within the decorated function (with respect
88 to the input arguments).
90 All arguments to the decorated function will be frozen so that they are guaranteed not to change.
91 The return value is also frozen.
92 """
93 @wraps(fn)
94 def inner_f(*args, **kwargs):
95 return freeze(fn(*[freeze(e) for e in args], **dict(freeze(item) for item in kwargs.items())))
97 return inner_f