-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathprivate.py
More file actions
69 lines (54 loc) · 1.7 KB
/
private.py
File metadata and controls
69 lines (54 loc) · 1.7 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
import contextvars
import functools
import inspect
import weakref
import types
class Private:
def __init__(self):
self._var = contextvars.ContextVar('_var')
def __set_name__(self, owner, name):
self.name = name
context = contextvars.copy_context()
old_getattribute = owner.__getattribute__
def get_patched(method):
@functools.wraps(method)
def patched(*args, **kwargs):
def wrapper():
self._var.set(self._var.get(weakref.WeakKeyDictionary()))
return method(*args, **kwargs)
return context.run(wrapper)
return patched
def getattribute(self, name):
attr = old_getattribute(self, name)
if not isinstance(attr, types.MethodType):
return attr
return get_patched(attr)
owner.__getattribute__ = getattribute
old_init = owner.__init__
owner.__init__ = get_patched(old_init)
def __get__(self, instance, owner):
if instance is None:
return self
try:
return self._var.get()[instance]
except (LookupError, KeyError):
raise AttributeError(self.name) from None
def __set__(self, instance, value):
try:
self._var.get()[instance] = value
except LookupError:
raise AttributeError(self.name) from None
class Class:
x = Private()
def __init__(self, x):
self.x = x
def get_x(self):
return self.x
obj = Class(5)
obj2 = Class(1)
print(obj.get_x())
print(obj2.get_x())
#print(Class.__dict__['x']._values[obj])
#obj.x = 0
#print(obj.x)
#print(dict(Class.x._var.get()))