private-attribute-cpp 1.4.3__tar.gz → 1.4.5__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {private_attribute_cpp-1.4.3/private_attribute_cpp.egg-info → private_attribute_cpp-1.4.5}/PKG-INFO +1 -1
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute.cpp +35 -5
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute.pyi +9 -9
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/SOURCES.txt +8 -1
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/setup.py +1 -2
- private_attribute_cpp-1.4.5/tests/test_class_private_attrs.py +22 -0
- private_attribute_cpp-1.4.5/tests/test_private_abc.py +53 -0
- private_attribute_cpp-1.4.5/tests/test_private_attrs.py +50 -0
- private_attribute_cpp-1.4.5/tests/test_private_func.py +27 -0
- private_attribute_cpp-1.4.5/tests/test_private_inheritance.py +40 -0
- private_attribute_cpp-1.4.5/tests/test_private_method.py +30 -0
- private_attribute_cpp-1.4.5/tests/test_private_wrap.py +51 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/LICENSE +0 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/MANIFEST.in +0 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/README.md +0 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/picosha2.h +0 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/top_level.txt +0 -0
- {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/setup.cfg +0 -0
{private_attribute_cpp-1.4.3/private_attribute_cpp.egg-info → private_attribute_cpp-1.4.5}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: private_attribute_cpp
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.5
|
|
4
4
|
Summary: A Python package that provides a way to define private attributes in C++ implementation.
|
|
5
5
|
Home-page: https://github.com/Locked-chess-official/private_attribute_cpp
|
|
6
6
|
Author: HuangHaoHua
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
#include <memory>
|
|
22
22
|
#include <algorithm>
|
|
23
23
|
|
|
24
|
-
// python under 3.13 doesn't
|
|
24
|
+
// python under 3.13 doesn't have PyDict_ContainsString, so we implement it ourselves
|
|
25
25
|
#if PY_VERSION_HEX < 0x030D0000
|
|
26
26
|
static int
|
|
27
27
|
PyDict_ContainsString(PyObject *op, const char *key)
|
|
@@ -231,7 +231,7 @@ generate_private_attr_name(uintptr_t obj_id, const std::string& attr_name)
|
|
|
231
231
|
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
|
|
232
232
|
|
|
233
233
|
std::uniform_int_distribution<long long> dist(0, printable_chars.size() - 1);
|
|
234
|
-
|
|
234
|
+
|
|
235
235
|
auto generate_random_ascii = [&](int length) {
|
|
236
236
|
std::string result;
|
|
237
237
|
for(int i = 0; i < length; i++) {
|
|
@@ -2440,7 +2440,13 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data)
|
|
|
2440
2440
|
analyse_all_code(original_value, ::AllData::type_allowed_code_map[type_id], set);
|
|
2441
2441
|
}
|
|
2442
2442
|
}
|
|
2443
|
-
|
|
2443
|
+
|
|
2444
|
+
// Python >= 3.13, delete the attr "__static_attributes__"
|
|
2445
|
+
#if PY_VERSION_HEX >= 0x030D0000
|
|
2446
|
+
PyDict_DelItemString(type_instance->tp_dict, "__static_attributes__");
|
|
2447
|
+
PyErr_Clear();
|
|
2448
|
+
#endif
|
|
2449
|
+
|
|
2444
2450
|
return true;
|
|
2445
2451
|
}
|
|
2446
2452
|
|
|
@@ -3206,7 +3212,7 @@ static PyMethodDef PrivateModule_methods[] = {
|
|
|
3206
3212
|
static PyTypeObject PrivateModuleType = {
|
|
3207
3213
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
3208
3214
|
"private_attribute_module", //tp_name
|
|
3209
|
-
PyModule_Type.tp_basicsize + 8, //tp_basicsize size of module object + 8 bytes for
|
|
3215
|
+
PyModule_Type.tp_basicsize + 8, //tp_basicsize size of module object + 8 bytes for basicsize to avoid changing attribute '__class__'
|
|
3210
3216
|
0, //tp_itemsize
|
|
3211
3217
|
0, //tp_dealloc
|
|
3212
3218
|
0, //tp_print
|
|
@@ -3279,14 +3285,38 @@ PyInit_private_attribute(void)
|
|
|
3279
3285
|
PyType_Ready(&PrivateTempType) < 0) {
|
|
3280
3286
|
return NULL;
|
|
3281
3287
|
}
|
|
3282
|
-
|
|
3288
|
+
PyObject* all = PyList_New(0);
|
|
3289
|
+
if (!all) {
|
|
3290
|
+
return NULL;
|
|
3291
|
+
}
|
|
3283
3292
|
PyObject* m = PyModule_Create(&def);
|
|
3284
3293
|
if (!m) {
|
|
3294
|
+
Py_DECREF(all);
|
|
3285
3295
|
return NULL;
|
|
3286
3296
|
}
|
|
3287
3297
|
#ifdef Py_GIL_DISABLED
|
|
3288
3298
|
PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
|
|
3289
3299
|
#endif
|
|
3300
|
+
|
|
3301
|
+
PyModule_AddObject(m, "__all__", all);
|
|
3302
|
+
/* all contains:
|
|
3303
|
+
* PrivateWrapProxy
|
|
3304
|
+
* PrivateAttrType
|
|
3305
|
+
* PrivateAttrBase
|
|
3306
|
+
* prepare
|
|
3307
|
+
* postprocess
|
|
3308
|
+
* register_metaclass
|
|
3309
|
+
* ensure_type
|
|
3310
|
+
* ensure_metaclass
|
|
3311
|
+
*/
|
|
3312
|
+
PyList_Append(all, PyUnicode_FromString("PrivateWrapProxy"));
|
|
3313
|
+
PyList_Append(all, PyUnicode_FromString("PrivateAttrType"));
|
|
3314
|
+
PyList_Append(all, PyUnicode_FromString("PrivateAttrBase"));
|
|
3315
|
+
PyList_Append(all, PyUnicode_FromString("prepare"));
|
|
3316
|
+
PyList_Append(all, PyUnicode_FromString("postprocess"));
|
|
3317
|
+
PyList_Append(all, PyUnicode_FromString("register_metaclass"));
|
|
3318
|
+
PyList_Append(all, PyUnicode_FromString("ensure_type"));
|
|
3319
|
+
PyList_Append(all, PyUnicode_FromString("ensure_metaclass"));
|
|
3290
3320
|
Py_SET_TYPE(m, &PrivateModuleType);
|
|
3291
3321
|
return m;
|
|
3292
3322
|
}
|
|
@@ -19,14 +19,14 @@ from typing import Any, TypeVar, Callable, TypedDict, Sequence, Generic
|
|
|
19
19
|
from types import FunctionType
|
|
20
20
|
|
|
21
21
|
# define the dict that must have a key "__private_attrs__" and value must be the sequence of strings
|
|
22
|
-
class
|
|
22
|
+
class _PrivateAttrDict(TypedDict):
|
|
23
23
|
__private_attrs__: Sequence[str]
|
|
24
24
|
|
|
25
|
-
|
|
25
|
+
_T = TypeVar('T')
|
|
26
26
|
|
|
27
|
-
class _PrivateWrap(Generic[
|
|
27
|
+
class _PrivateWrap(Generic[_T]):
|
|
28
28
|
@property
|
|
29
|
-
def result(self) ->
|
|
29
|
+
def result(self) -> _T:
|
|
30
30
|
"the final result of decorating"
|
|
31
31
|
...
|
|
32
32
|
|
|
@@ -38,7 +38,7 @@ class _PrivateWrap(Generic[T]):
|
|
|
38
38
|
def __getattr__(self, name: str) -> Any:
|
|
39
39
|
return getattr(self.result, name)
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
_TVar = TypeVar('TVar')
|
|
42
42
|
|
|
43
43
|
class PrivateWrapProxy:
|
|
44
44
|
"""
|
|
@@ -70,13 +70,13 @@ class PrivateWrapProxy:
|
|
|
70
70
|
def my_method(self): ...
|
|
71
71
|
```
|
|
72
72
|
"""
|
|
73
|
-
def __init__(self, decorator: Callable[[
|
|
74
|
-
def __call__(self, func:
|
|
73
|
+
def __init__(self, decorator: Callable[[_TVar], _T], orig: _PrivateWrap[Any]|None = None, /) -> None: ...
|
|
74
|
+
def __call__(self, func: _TVar, /) -> _PrivateWrap[_T]: ...
|
|
75
75
|
|
|
76
76
|
class PrivateAttrType(type):
|
|
77
77
|
"metaclass for private attributes"
|
|
78
78
|
def __new__(cls, name: str, bases: tuple,
|
|
79
|
-
attrs:
|
|
79
|
+
attrs: _PrivateAttrDict, /,
|
|
80
80
|
private_func: Callable[[int, str], str]|None = None) -> PrivateAttrType: ...
|
|
81
81
|
|
|
82
82
|
class PrivateAttrBase(metaclass=PrivateAttrType):
|
|
@@ -95,7 +95,7 @@ class _PrivateTemp:
|
|
|
95
95
|
@property
|
|
96
96
|
def kwds(self) -> dict[str, Any]: ...
|
|
97
97
|
|
|
98
|
-
def prepare(name: str, bases: tuple, attrs:
|
|
98
|
+
def prepare(name: str, bases: tuple, attrs: _PrivateAttrDict, /, **kwds) -> _PrivateTemp:
|
|
99
99
|
"""
|
|
100
100
|
function for custom metaclass to create private attributes class.
|
|
101
101
|
|
{private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5/private_attribute_cpp.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: private_attribute_cpp
|
|
3
|
-
Version: 1.4.
|
|
3
|
+
Version: 1.4.5
|
|
4
4
|
Summary: A Python package that provides a way to define private attributes in C++ implementation.
|
|
5
5
|
Home-page: https://github.com/Locked-chess-official/private_attribute_cpp
|
|
6
6
|
Author: HuangHaoHua
|
|
@@ -9,4 +9,11 @@ private_attribute_cpp.egg-info/PKG-INFO
|
|
|
9
9
|
private_attribute_cpp.egg-info/SOURCES.txt
|
|
10
10
|
private_attribute_cpp.egg-info/dependency_links.txt
|
|
11
11
|
private_attribute_cpp.egg-info/not-zip-safe
|
|
12
|
-
private_attribute_cpp.egg-info/top_level.txt
|
|
12
|
+
private_attribute_cpp.egg-info/top_level.txt
|
|
13
|
+
tests/test_class_private_attrs.py
|
|
14
|
+
tests/test_private_abc.py
|
|
15
|
+
tests/test_private_attrs.py
|
|
16
|
+
tests/test_private_func.py
|
|
17
|
+
tests/test_private_inheritance.py
|
|
18
|
+
tests/test_private_method.py
|
|
19
|
+
tests/test_private_wrap.py
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
from setuptools import setup, Extension
|
|
2
2
|
import sys
|
|
3
|
-
import sysconfig
|
|
4
3
|
|
|
5
4
|
if sys.platform == "win32":
|
|
6
5
|
extra_compile_args = ['/std:c++17']
|
|
@@ -19,7 +18,7 @@ readme = open('README.md').read()
|
|
|
19
18
|
|
|
20
19
|
setup(
|
|
21
20
|
name='private_attribute_cpp',
|
|
22
|
-
version='1.4.
|
|
21
|
+
version='1.4.5',
|
|
23
22
|
author="HuangHaoHua",
|
|
24
23
|
author_email="13140752715@example.com",
|
|
25
24
|
description='A Python package that provides a way to define private attributes in C++ implementation.',
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import private_attribute
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
class MyClass(private_attribute.PrivateAttrBase):
|
|
5
|
+
__private_attrs__ = ["_secret"]
|
|
6
|
+
_secret = 1
|
|
7
|
+
@classmethod
|
|
8
|
+
def get_secret(cls):
|
|
9
|
+
return cls._secret
|
|
10
|
+
|
|
11
|
+
class TestClassPrivateAttrs(unittest.TestCase):
|
|
12
|
+
def test_class_private_attrs(self):
|
|
13
|
+
self.assertEqual(MyClass.get_secret(), 1)
|
|
14
|
+
with self.assertRaises(AttributeError):
|
|
15
|
+
MyClass._secret = 2
|
|
16
|
+
a = MyClass()
|
|
17
|
+
with self.assertRaises(AttributeError):
|
|
18
|
+
a._secret = 2
|
|
19
|
+
self.assertEqual(a.get_secret(), 1)
|
|
20
|
+
|
|
21
|
+
if __name__ == "__main__":
|
|
22
|
+
unittest.main()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
from abc import ABCMeta, abstractmethod, ABC
|
|
2
|
+
import private_attribute
|
|
3
|
+
import unittest
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class PrivateAbcMeta(ABCMeta):
|
|
7
|
+
def __new__(cls, *args, **kwargs):
|
|
8
|
+
temp = private_attribute.prepare(*args, **kwargs)
|
|
9
|
+
typ = super().__new__(cls, temp.name, temp.bases, temp.attrs, **temp.kwds)
|
|
10
|
+
private_attribute.postprocess(typ, temp)
|
|
11
|
+
return typ
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
private_attribute.register_metaclass(PrivateAbcMeta)
|
|
15
|
+
|
|
16
|
+
class MyClass(ABC, metaclass=PrivateAbcMeta):
|
|
17
|
+
__private_attrs__ = ["_secret1"]
|
|
18
|
+
_secret1 = 10
|
|
19
|
+
@classmethod
|
|
20
|
+
def get_secret1(cls):
|
|
21
|
+
return cls._secret1
|
|
22
|
+
|
|
23
|
+
@abstractmethod
|
|
24
|
+
def public_method(self):
|
|
25
|
+
pass
|
|
26
|
+
|
|
27
|
+
class ConcreteClass(MyClass):
|
|
28
|
+
__private_attrs__ = ["_secret2"]
|
|
29
|
+
def __init__(self, secret1, secret2):
|
|
30
|
+
self._secret1 = secret1
|
|
31
|
+
self._secret2 = secret2
|
|
32
|
+
|
|
33
|
+
def public_method(self):
|
|
34
|
+
return self._secret1, self._secret2
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class TestPrivateAbc(unittest.TestCase):
|
|
38
|
+
def test_private_abc(self):
|
|
39
|
+
c = ConcreteClass("secret1", "secret2")
|
|
40
|
+
self.assertEqual(c.public_method(), ("secret1", "secret2"))
|
|
41
|
+
with self.assertRaises(AttributeError):
|
|
42
|
+
c._secret1
|
|
43
|
+
with self.assertRaises(AttributeError):
|
|
44
|
+
c._secret2
|
|
45
|
+
with self.assertRaises(TypeError):
|
|
46
|
+
MyClass()
|
|
47
|
+
with self.assertRaises(AttributeError):
|
|
48
|
+
MyClass._secret1
|
|
49
|
+
self.assertEqual(MyClass.get_secret1(), 10)
|
|
50
|
+
self.assertEqual(ConcreteClass.get_secret1(), 10)
|
|
51
|
+
|
|
52
|
+
if __name__ == '__main__':
|
|
53
|
+
unittest.main()
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import private_attribute
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
class BaseClass(private_attribute.PrivateAttrBase):
|
|
5
|
+
__private_attrs__ = ["_a", "_b"]
|
|
6
|
+
__slots__ = ["c", "d"]
|
|
7
|
+
def __init__(self, a, b, c, d):
|
|
8
|
+
self._a = a
|
|
9
|
+
self._b = b
|
|
10
|
+
self.c = c
|
|
11
|
+
self.d = d
|
|
12
|
+
|
|
13
|
+
@property
|
|
14
|
+
def a(self):
|
|
15
|
+
return self._a
|
|
16
|
+
|
|
17
|
+
@property
|
|
18
|
+
def b(self):
|
|
19
|
+
return self._b
|
|
20
|
+
|
|
21
|
+
def public_has_a(self):
|
|
22
|
+
return hasattr(self, "_a")
|
|
23
|
+
|
|
24
|
+
def public_has_b(self):
|
|
25
|
+
return hasattr(self, "_b")
|
|
26
|
+
|
|
27
|
+
class TestPrivateAttributes(unittest.TestCase):
|
|
28
|
+
def __init__(self, *args, **kwargs):
|
|
29
|
+
super().__init__(*args, **kwargs)
|
|
30
|
+
self.base_obj = BaseClass(1, 2, 3, 4)
|
|
31
|
+
|
|
32
|
+
def test_private_attrs(self):
|
|
33
|
+
self.assertTrue(self.base_obj.public_has_a())
|
|
34
|
+
self.assertTrue(self.base_obj.public_has_b())
|
|
35
|
+
self.assertEqual(self.base_obj.a, 1)
|
|
36
|
+
self.assertEqual(self.base_obj.b, 2)
|
|
37
|
+
self.assertEqual(self.base_obj.c, 3)
|
|
38
|
+
self.assertEqual(self.base_obj.d, 4)
|
|
39
|
+
self.assertFalse(hasattr(self.base_obj, "_a"))
|
|
40
|
+
self.assertFalse(hasattr(self.base_obj, "_b"))
|
|
41
|
+
with self.assertRaises(AttributeError):
|
|
42
|
+
self.base_obj._a
|
|
43
|
+
with self.assertRaises(AttributeError):
|
|
44
|
+
self.base_obj._b
|
|
45
|
+
self.assertTrue(isinstance(self.base_obj.__private_attrs__, tuple))
|
|
46
|
+
for i in self.base_obj.__private_attrs__:
|
|
47
|
+
self.assertTrue(isinstance(i, tuple))
|
|
48
|
+
|
|
49
|
+
if __name__ == "__main__":
|
|
50
|
+
unittest.main()
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import private_attribute
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
def my_func(obj_id, attr):
|
|
5
|
+
return f"Object ID: {obj_id}, String: {attr}"
|
|
6
|
+
|
|
7
|
+
class MyClass(private_attribute.PrivateAttrBase, private_func=my_func):
|
|
8
|
+
__private_attrs__ = ["_secret"]
|
|
9
|
+
__slots__ = ["public_attr"]
|
|
10
|
+
|
|
11
|
+
def __init__(self, secret, public_attr):
|
|
12
|
+
self._secret = secret
|
|
13
|
+
self.public_attr = public_attr
|
|
14
|
+
|
|
15
|
+
def get_secret(self):
|
|
16
|
+
return self._secret
|
|
17
|
+
|
|
18
|
+
class TestPrivateFunc(unittest.TestCase):
|
|
19
|
+
def test_private_func(self):
|
|
20
|
+
obj = MyClass("12345", "public_value")
|
|
21
|
+
self.assertEqual(obj.get_secret(), "12345")
|
|
22
|
+
self.assertEqual(obj.public_attr, "public_value")
|
|
23
|
+
with self.assertRaises(AttributeError):
|
|
24
|
+
obj._secret
|
|
25
|
+
|
|
26
|
+
if __name__ == "__main__":
|
|
27
|
+
unittest.main()
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import private_attribute
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
class BaseClass(private_attribute.PrivateAttrBase):
|
|
5
|
+
__private_attrs__ = ["_value"]
|
|
6
|
+
__slots__ = []
|
|
7
|
+
|
|
8
|
+
def __init__(self, value):
|
|
9
|
+
super().__init__()
|
|
10
|
+
self._value = value
|
|
11
|
+
|
|
12
|
+
class SubClass(BaseClass):
|
|
13
|
+
__private_attrs__ = ["_other_value"]
|
|
14
|
+
__slots__ = []
|
|
15
|
+
|
|
16
|
+
def __init__(self, value, other_value):
|
|
17
|
+
super().__init__(value)
|
|
18
|
+
self._other_value = other_value
|
|
19
|
+
|
|
20
|
+
@property
|
|
21
|
+
def value(self):
|
|
22
|
+
return self._value
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def other_value(self):
|
|
26
|
+
return self._other_value
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class TestPrivateInheritance(unittest.TestCase):
|
|
30
|
+
def test_private_inheritance(self):
|
|
31
|
+
obj = SubClass(1, 2)
|
|
32
|
+
self.assertEqual(obj.value, 1)
|
|
33
|
+
self.assertEqual(obj.other_value, 2)
|
|
34
|
+
with self.assertRaises(AttributeError):
|
|
35
|
+
obj._value
|
|
36
|
+
with self.assertRaises(AttributeError):
|
|
37
|
+
obj._other_value
|
|
38
|
+
|
|
39
|
+
if __name__ == "__main__":
|
|
40
|
+
unittest.main()
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import private_attribute
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
class PrivateMethodClass(private_attribute.PrivateAttrBase):
|
|
5
|
+
__private_attrs__ = ["_secret_method", "_a"]
|
|
6
|
+
__slots__ = ["public_attr"]
|
|
7
|
+
|
|
8
|
+
def __init__(self, a):
|
|
9
|
+
self._a = a
|
|
10
|
+
self.public_attr = "public_value"
|
|
11
|
+
|
|
12
|
+
def _secret_method(self):
|
|
13
|
+
return self._a
|
|
14
|
+
|
|
15
|
+
def public_method(self):
|
|
16
|
+
return self._secret_method()
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class TestPrivateMethod(unittest.TestCase):
|
|
20
|
+
def test_private_method(self):
|
|
21
|
+
obj = PrivateMethodClass(1)
|
|
22
|
+
self.assertEqual(obj.public_method(), 1)
|
|
23
|
+
with self.assertRaises(AttributeError):
|
|
24
|
+
obj._secret_method()
|
|
25
|
+
|
|
26
|
+
with self.assertRaises(AttributeError):
|
|
27
|
+
obj._a
|
|
28
|
+
|
|
29
|
+
if __name__ == "__main__":
|
|
30
|
+
unittest.main()
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import private_attribute
|
|
2
|
+
import unittest
|
|
3
|
+
|
|
4
|
+
class MyWrap:
|
|
5
|
+
def __init__(self, func):
|
|
6
|
+
self.func1 = func
|
|
7
|
+
self.index = 1
|
|
8
|
+
|
|
9
|
+
def add(self, func):
|
|
10
|
+
self.index += 1
|
|
11
|
+
setattr(self, f"func{self.index}", func)
|
|
12
|
+
return self
|
|
13
|
+
|
|
14
|
+
def get(self, index, instance, owner):
|
|
15
|
+
func = getattr(self, f"func{index}")
|
|
16
|
+
return func.__get__(instance, owner)
|
|
17
|
+
|
|
18
|
+
class MyClass(private_attribute.PrivateAttrBase):
|
|
19
|
+
__private_attrs__ = ["_secret1", "_secret2", "_secret3"]
|
|
20
|
+
def __init__(self, secret1, secret2, secret3):
|
|
21
|
+
self._secret1 = secret1
|
|
22
|
+
self._secret2 = secret2
|
|
23
|
+
self._secret3 = secret3
|
|
24
|
+
|
|
25
|
+
@private_attribute.PrivateWrapProxy(MyWrap)
|
|
26
|
+
def get_secret(self):
|
|
27
|
+
return self._secret1
|
|
28
|
+
|
|
29
|
+
@private_attribute.PrivateWrapProxy(get_secret.result.add, get_secret)
|
|
30
|
+
def get_secret(self):
|
|
31
|
+
return self._secret2
|
|
32
|
+
|
|
33
|
+
@private_attribute.PrivateWrapProxy(get_secret.result.add, get_secret)
|
|
34
|
+
def get_secret(self):
|
|
35
|
+
return self._secret3
|
|
36
|
+
|
|
37
|
+
class TestPrivateWrap(unittest.TestCase):
|
|
38
|
+
def test_private_wrap(self):
|
|
39
|
+
a = MyClass(1, 2, 3)
|
|
40
|
+
self.assertEqual(a.get_secret.get(1, a, MyClass)(), 1)
|
|
41
|
+
self.assertEqual(a.get_secret.get(2, a, MyClass)(), 2)
|
|
42
|
+
self.assertEqual(a.get_secret.get(3, a, MyClass)(), 3)
|
|
43
|
+
with self.assertRaises(AttributeError):
|
|
44
|
+
a._secret1
|
|
45
|
+
with self.assertRaises(AttributeError):
|
|
46
|
+
a._secret2
|
|
47
|
+
with self.assertRaises(AttributeError):
|
|
48
|
+
a._secret3
|
|
49
|
+
|
|
50
|
+
if __name__ == "__main__":
|
|
51
|
+
unittest.main()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|