-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathfreezer_property.py
More file actions
111 lines (84 loc) · 3.84 KB
/
Copy pathfreezer_property.py
File metadata and controls
111 lines (84 loc) · 3.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
# Copyright 2009-2017 Ram Rachum.
# This program is distributed under the MIT license.
from python_toolbox import caching
from python_toolbox.misc_tools import do_nothing
from .freezer_property_freezer import FreezerPropertyFreezer
from .freezer import Freezer
class FreezerProperty(caching.CachedProperty):
'''
A property which lazy-creates a freezer.
A freezer is used as a context manager to "freeze" and "thaw" an object.
See documentation of `Freezer` in this package for more info.
The advantages of using a `FreezerProperty` instead of creating a freezer
attribute for each instance:
- The `.on_freeze` and `.on_thaw` decorators can be used on the class's
methods to define them as freeze/thaw handlers.
- The freezer is created lazily on access (using
`caching.CachedProperty`) which can save processing power.
'''
def __init__(self, on_freeze=do_nothing, on_thaw=do_nothing,
freezer_type=FreezerPropertyFreezer, doc=None, name=None):
'''
Create the `FreezerProperty`.
All arguments are optional: You may pass in freeze/thaw handlers as
`on_freeze` and `on_thaw`, but you don't have to. You may choose a
specific freezer type to use as `freezer_type`, in which case you can't
use either the `on_freeze`/`on_thaw` arguments nor the decorators.
'''
if freezer_type is not FreezerPropertyFreezer:
assert issubclass(freezer_type, Freezer)
if not (on_freeze is on_thaw is do_nothing):
raise Exception(
"You've passed a `freezer_type` argument, so you're not "
"allowed to pass `on_freeze` or `on_thaw` arguments. The "
"freeze/thaw handlers should be defined on the freezer "
"type."
)
self.__freezer_type = freezer_type
'''The type of the internal freezer. Always a subclass of `Freezer`.'''
self._freeze_handler = on_freeze
'''Internal freeze handler. May be a no-op.'''
self._thaw_handler = on_thaw
'''Internal thaw handler. May be a no-op.'''
caching.CachedProperty.__init__(self,
self.__make_freezer,
doc=doc,
name=name)
def __make_freezer(self, obj):
'''
Create our freezer.
This is used only on the first time we are accessed, and afterwards the
freezer will be cached.
'''
assert obj is not None
freezer = self.__freezer_type(obj)
freezer.freezer_property = self
return freezer
def on_freeze(self, function):
'''
Use `function` as the freeze handler.
Returns `function` unchanged, so it may be used as a decorator.
'''
if self.__freezer_type is not FreezerPropertyFreezer:
raise Exception(
"You've passed a `freezer_type` argument, so you're not "
"allowed to use the `on_freeze` or `on_thaw` decorators. The "
"freeze/thaw handlers should be defined on the freezer "
"type."
)
self._freeze_handler = function
return function
def on_thaw(self, function):
'''
Use `function` as the thaw handler.
Returns `function` unchanged, so it may be used as a decorator.
'''
if self.__freezer_type is not FreezerPropertyFreezer:
raise Exception(
"You've passed a `freezer_type` argument, so you're not "
"allowed to use the `on_freeze` or `on_thaw` decorators. The "
"freeze/thaw handlers should be defined on the freezer "
"type."
)
self._thaw_handler = function
return function