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.
Files changed (21) hide show
  1. {private_attribute_cpp-1.4.3/private_attribute_cpp.egg-info → private_attribute_cpp-1.4.5}/PKG-INFO +1 -1
  2. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute.cpp +35 -5
  3. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute.pyi +9 -9
  4. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
  5. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/SOURCES.txt +8 -1
  6. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/setup.py +1 -2
  7. private_attribute_cpp-1.4.5/tests/test_class_private_attrs.py +22 -0
  8. private_attribute_cpp-1.4.5/tests/test_private_abc.py +53 -0
  9. private_attribute_cpp-1.4.5/tests/test_private_attrs.py +50 -0
  10. private_attribute_cpp-1.4.5/tests/test_private_func.py +27 -0
  11. private_attribute_cpp-1.4.5/tests/test_private_inheritance.py +40 -0
  12. private_attribute_cpp-1.4.5/tests/test_private_method.py +30 -0
  13. private_attribute_cpp-1.4.5/tests/test_private_wrap.py +51 -0
  14. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/LICENSE +0 -0
  15. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/MANIFEST.in +0 -0
  16. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/README.md +0 -0
  17. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/picosha2.h +0 -0
  18. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  19. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  20. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  21. {private_attribute_cpp-1.4.3 → private_attribute_cpp-1.4.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.4.3
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 has PyDict_ContainsString, so we implement it ourselves
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 flag to avoid change attribute '__class__'
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 PrivateAttrDict(TypedDict):
22
+ class _PrivateAttrDict(TypedDict):
23
23
  __private_attrs__: Sequence[str]
24
24
 
25
- T = TypeVar('T')
25
+ _T = TypeVar('T')
26
26
 
27
- class _PrivateWrap(Generic[T]):
27
+ class _PrivateWrap(Generic[_T]):
28
28
  @property
29
- def result(self) -> T:
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
- TVar = TypeVar('TVar')
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[[TVar], T], orig: _PrivateWrap[Any]|None = None, /) -> None: ...
74
- def __call__(self, func: TVar, /) -> _PrivateWrap[T]: ...
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: PrivateAttrDict, /,
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: PrivateAttrDict, /, **kwds) -> _PrivateTemp:
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
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.4.3
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.3',
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()