private-attribute-cpp 1.4.5__tar.gz → 1.4.7__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.5/private_attribute_cpp.egg-info → private_attribute_cpp-1.4.7}/PKG-INFO +3 -2
  2. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/README.md +2 -1
  3. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/private_attribute.cpp +35 -33
  4. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/private_attribute.pyi +1 -1
  5. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7/private_attribute_cpp.egg-info}/PKG-INFO +3 -2
  6. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/setup.py +1 -1
  7. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/tests/test_class_private_attrs.py +2 -1
  8. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/tests/test_private_abc.py +3 -1
  9. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/tests/test_private_attrs.py +2 -1
  10. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/tests/test_private_func.py +1 -1
  11. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/tests/test_private_inheritance.py +1 -1
  12. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/tests/test_private_method.py +1 -1
  13. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/tests/test_private_wrap.py +11 -7
  14. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/LICENSE +0 -0
  15. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/MANIFEST.in +0 -0
  16. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/picosha2.h +0 -0
  17. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
  18. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  19. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  20. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  21. {private_attribute_cpp-1.4.5 → private_attribute_cpp-1.4.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.4.5
3
+ Version: 1.4.7
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
@@ -250,7 +250,8 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
250
250
  - One class defined in another class cannot use another class's private attribute.
251
251
  - One parent class defined an attribute which not in `__private_attrs__` or not a `PrivateAttrType` instance, the child class shouldn't contain the attribute in its `__private_attrs__`.
252
252
  - CPython may change "tp_getattro", "tp_setattro" and so on when you change the attribute "\_\_getattribute\_\_", "\_\_setattr\_\_" and so on. If you are fear about it, you can use `ensure_type` to reset those tp slots. For the other metaclasses, you can use `ensure_metaclass` to reset those tp slots. Also, don't set those methods on these classes in your code.
253
- - `private_attribute.register_metaclass` must be called with the metaclass which support weakref.
253
+ - `private_attribute.register_metaclass` must be called with the metaclass which supports weakref.
254
+ - Don't set `__static_attributes__` in private attribute class, or it will be removed.
254
255
 
255
256
  ## License
256
257
 
@@ -231,7 +231,8 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
231
231
  - One class defined in another class cannot use another class's private attribute.
232
232
  - One parent class defined an attribute which not in `__private_attrs__` or not a `PrivateAttrType` instance, the child class shouldn't contain the attribute in its `__private_attrs__`.
233
233
  - CPython may change "tp_getattro", "tp_setattro" and so on when you change the attribute "\_\_getattribute\_\_", "\_\_setattr\_\_" and so on. If you are fear about it, you can use `ensure_type` to reset those tp slots. For the other metaclasses, you can use `ensure_metaclass` to reset those tp slots. Also, don't set those methods on these classes in your code.
234
- - `private_attribute.register_metaclass` must be called with the metaclass which support weakref.
234
+ - `private_attribute.register_metaclass` must be called with the metaclass which supports weakref.
235
+ - Don't set `__static_attributes__` in private attribute class, or it will be removed.
235
236
 
236
237
  ## License
237
238
 
@@ -57,7 +57,7 @@ private:
57
57
  std::string attr_onehash;
58
58
  std::string another_string_hash;
59
59
  public:
60
- AllPyobjectAttrCacheKey(uintptr_t obj_id, std::string attr_name) : obj_id(obj_id) {
60
+ AllPyobjectAttrCacheKey(uintptr_t obj_id, const std::string& attr_name) : obj_id(obj_id) {
61
61
  std::string one_name = "_" + std::to_string(obj_id) + "_" + attr_name;
62
62
  std::string another_name = "_" + module_running_time_string + attr_name;
63
63
  picosha2::hash256_hex_string(one_name, attr_onehash);
@@ -82,7 +82,7 @@ private:
82
82
  std::string first;
83
83
  std::string second;
84
84
  public:
85
- TwoStringTuple(std::string first, std::string second) : first(first), second(second) {}
85
+ TwoStringTuple(const std::string& first, const std::string& second) : first(first), second(second) {}
86
86
  bool operator==(const TwoStringTuple& other) const {
87
87
  return this->first == other.first && this->second == other.second;
88
88
  }
@@ -162,11 +162,11 @@ struct FinalObject
162
162
  }
163
163
  };
164
164
 
165
- static TwoStringTuple get_string_hash_tuple2(std::string name);
165
+ static TwoStringTuple get_string_hash_tuple2(const std::string& name);
166
166
  static PyCodeObject* get_now_code();
167
- static uintptr_t type_set_attr_long_long_guidance(uintptr_t type, std::string name);
168
- static bool type_private_attr(uintptr_t type, std::string name);
169
- static FinalObject type_get_final_attr(uintptr_t type_id, std::string name);
167
+ static uintptr_t type_set_attr_long_long_guidance(uintptr_t type, const std::string& name);
168
+ static bool type_private_attr(uintptr_t type, const std::string& name);
169
+ static FinalObject type_get_final_attr(uintptr_t type_id, const std::string& name);
170
170
 
171
171
  static bool
172
172
  is_class_code(uintptr_t typ_id, PyCodeObject* code)
@@ -182,7 +182,7 @@ is_class_code(uintptr_t typ_id, PyCodeObject* code)
182
182
  }
183
183
 
184
184
  static bool
185
- is_type_private(uintptr_t typ_id, std::string name)
185
+ is_type_private(uintptr_t typ_id, const std::string& name)
186
186
  {
187
187
  if (::AllData::all_type_attr_set.find(typ_id) != ::AllData::all_type_attr_set.end()){
188
188
  auto& attr_set = ::AllData::all_type_attr_set[typ_id];
@@ -195,7 +195,7 @@ is_type_private(uintptr_t typ_id, std::string name)
195
195
  }
196
196
 
197
197
  static bool
198
- attr_classify(uintptr_t typ_id, std::string name, PyCodeObject* code)
198
+ attr_classify(uintptr_t typ_id, const std::string& name, PyCodeObject* code)
199
199
  {
200
200
  if (is_class_code(typ_id, code)) {
201
201
  return true;
@@ -248,7 +248,7 @@ generate_private_attr_name(uintptr_t obj_id, const std::string& attr_name)
248
248
  }
249
249
 
250
250
  static std::string
251
- default_random_string(uintptr_t obj_id, std::string attr_name)
251
+ default_random_string(uintptr_t obj_id, const std::string& attr_name)
252
252
  {
253
253
  AllPyobjectAttrCacheKey key(obj_id, attr_name);
254
254
  std::string result;
@@ -262,7 +262,7 @@ default_random_string(uintptr_t obj_id, std::string attr_name)
262
262
  lock.unlock();
263
263
  result = generate_private_attr_name(obj_id, attr_name);
264
264
  std::string original_result = result;
265
- int i = 1;
265
+ unsigned long long i = 1;
266
266
  std::unique_lock<std::shared_mutex> lock2(::AllData::cache_mutex);
267
267
  auto it = ::AllData::cache.find(key); // twice check
268
268
  if (it != ::AllData::cache.end()) {
@@ -333,7 +333,7 @@ private:
333
333
  };
334
334
 
335
335
  static std::string
336
- custom_random_string(uintptr_t obj_id, std::string attr_name, PyObject* func)
336
+ custom_random_string(uintptr_t obj_id, const std::string& attr_name, PyObject* func)
337
337
  {
338
338
  AllPyobjectAttrCacheKey key(obj_id, attr_name);
339
339
  std::string result;
@@ -363,7 +363,7 @@ custom_random_string(uintptr_t obj_id, std::string attr_name, PyObject* func)
363
363
  result = PyUnicode_AsUTF8(python_result);
364
364
  Py_DECREF(python_result);
365
365
  std::string original_result = result;
366
- int i = 1;
366
+ unsigned long long i = 1;
367
367
  std::unique_lock<std::shared_mutex> lock2(::AllData::cache_mutex);
368
368
  auto it = ::AllData::cache.find(key); // twice check
369
369
  if (it != ::AllData::cache.end()) {
@@ -426,7 +426,7 @@ static void ensure_tp(PyTypeObject* type_instance);
426
426
  static void ensure_subclass_tp(PyTypeObject* type_instance);
427
427
 
428
428
  static PyObject*
429
- id_getattr(std::string attr_name, PyObject* obj, PyObject* typ)
429
+ id_getattr(const std::string& attr_name, PyObject* obj, PyObject* typ)
430
430
  {
431
431
  uintptr_t obj_id, typ_id, final_id;
432
432
  obj_id = (uintptr_t) obj;
@@ -533,7 +533,7 @@ id_getattr(std::string attr_name, PyObject* obj, PyObject* typ)
533
533
  }
534
534
 
535
535
  static PyObject*
536
- type_getattr(PyObject* typ, std::string attr_name)
536
+ type_getattr(PyObject* typ, const std::string& attr_name)
537
537
  {
538
538
  uintptr_t typ_id = (uintptr_t)typ;
539
539
  FinalObject final_object = type_get_final_attr(typ_id, attr_name);
@@ -567,7 +567,7 @@ type_getattr(PyObject* typ, std::string attr_name)
567
567
  }
568
568
 
569
569
  static int
570
- id_setattr(std::string attr_name, PyObject* obj, PyObject* typ, PyObject* value)
570
+ id_setattr(const std::string& attr_name, PyObject* obj, PyObject* typ, PyObject* value)
571
571
  {
572
572
  uintptr_t obj_id, typ_id, final_id;
573
573
  obj_id = (uintptr_t) obj;
@@ -636,10 +636,10 @@ id_setattr(std::string attr_name, PyObject* obj, PyObject* typ, PyObject* value)
636
636
  return 0;
637
637
  }
638
638
 
639
- static int type_delattr(PyObject* typ, std::string attr_name);
639
+ static int type_delattr(PyObject* typ, const std::string& attr_name);
640
640
 
641
641
  static int
642
- type_setattr(PyObject* typ, std::string attr_name, PyObject* value)
642
+ type_setattr(PyObject* typ, const std::string& attr_name, PyObject* value)
643
643
  {
644
644
  if (!value) {
645
645
  return type_delattr(typ, attr_name);
@@ -711,7 +711,7 @@ type_setattr(PyObject* typ, std::string attr_name, PyObject* value)
711
711
  }
712
712
 
713
713
  static int
714
- id_delattr(std::string attr_name, PyObject* obj, PyObject* typ)
714
+ id_delattr(const std::string& attr_name, PyObject* obj, PyObject* typ)
715
715
  {
716
716
  uintptr_t obj_id, typ_id, final_id;
717
717
  obj_id = (uintptr_t) obj;
@@ -789,7 +789,7 @@ id_delattr(std::string attr_name, PyObject* obj, PyObject* typ)
789
789
  }
790
790
 
791
791
  static int
792
- type_delattr(PyObject* typ, std::string attr_name)
792
+ type_delattr(PyObject* typ, const std::string& attr_name)
793
793
  {
794
794
  uintptr_t typ_id = (uintptr_t) typ;
795
795
  uintptr_t final_id = type_set_attr_long_long_guidance(typ_id, attr_name);
@@ -1438,7 +1438,7 @@ static PyTypeObject PrivateAttrType = {
1438
1438
  };
1439
1439
 
1440
1440
  static PyObject*
1441
- get_string_hash_tuple(std::string name)
1441
+ get_string_hash_tuple(const std::string& name)
1442
1442
  {
1443
1443
  std::string name1;
1444
1444
  std::string name2;
@@ -1452,7 +1452,7 @@ get_string_hash_tuple(std::string name)
1452
1452
  }
1453
1453
 
1454
1454
  static TwoStringTuple
1455
- get_string_hash_tuple2(std::string name)
1455
+ get_string_hash_tuple2(const std::string& name)
1456
1456
  {
1457
1457
  std::string name1;
1458
1458
  std::string name2;
@@ -1466,7 +1466,7 @@ get_string_hash_tuple2(std::string name)
1466
1466
  }
1467
1467
 
1468
1468
  static FinalObject
1469
- type_get_final_attr(uintptr_t type_id, std::string name)
1469
+ type_get_final_attr(uintptr_t type_id, const std::string& name)
1470
1470
  {
1471
1471
  TwoStringTuple hash_tuple = get_string_hash_tuple2(name);
1472
1472
  if (::AllData::all_type_attr_set.find(type_id) != ::AllData::all_type_attr_set.end()) {
@@ -1580,7 +1580,7 @@ type_get_final_attr(uintptr_t type_id, std::string name)
1580
1580
  }
1581
1581
 
1582
1582
  static uintptr_t
1583
- type_set_attr_long_long_guidance(uintptr_t type_id, std::string name)
1583
+ type_set_attr_long_long_guidance(uintptr_t type_id, const std::string& name)
1584
1584
  {
1585
1585
  TwoStringTuple hash_tuple = get_string_hash_tuple2(name);
1586
1586
  if (::AllData::all_type_attr_set.find(type_id) != ::AllData::all_type_attr_set.end()) {
@@ -1602,7 +1602,7 @@ type_set_attr_long_long_guidance(uintptr_t type_id, std::string name)
1602
1602
  }
1603
1603
 
1604
1604
  static bool
1605
- type_private_attr(uintptr_t type_id, std::string name)
1605
+ type_private_attr(uintptr_t type_id, const std::string& name)
1606
1606
  {
1607
1607
  TwoStringTuple hash_tuple = get_string_hash_tuple2(name);
1608
1608
  if (::AllData::all_type_attr_set.find(type_id) != ::AllData::all_type_attr_set.end()) {
@@ -1722,7 +1722,7 @@ analyse_all_code(PyObject* obj, std::unordered_map<uintptr_t, PyCodeObject*>& ma
1722
1722
  }
1723
1723
 
1724
1724
  static std::string
1725
- real_class_name(std::string name, std::string class_name)
1725
+ real_class_name(const std::string& name, const std::string& class_name)
1726
1726
  {
1727
1727
  // if the name starts with "__" but does not end with "__", change to _ClassName__name
1728
1728
  if (name.length() >= 2 && name.substr(0, 2) == "__" && name.substr(name.length() - 2) != "__") {
@@ -2127,6 +2127,11 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
2127
2127
  return (uintptr_t)0;
2128
2128
  };
2129
2129
 
2130
+ // forbidden to have "__static_attributes__" in attrs, because it exposes the private attributes name.
2131
+ if (PyDict_ContainsString(data.attrs_copy, "__static_attributes__")) {
2132
+ PyDict_DelItemString(data.attrs_copy, "__static_attributes__");
2133
+ }
2134
+
2130
2135
  {
2131
2136
  Py_ssize_t pos = 0;
2132
2137
  PyObject* key, *value;
@@ -2335,6 +2340,10 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data)
2335
2340
 
2336
2341
  PyTypeObject* type_instance = (PyTypeObject*)new_type;
2337
2342
  uintptr_t type_id = (uintptr_t)(type_instance);
2343
+ if (PyDict_ContainsString(type_instance->tp_dict, "__static_attributes__")) {
2344
+ PyErr_SetString(PyExc_SystemError, "'__static_attributes__' will expose private attribute names and cannot be used in private attribute types");
2345
+ return false;
2346
+ }
2338
2347
 
2339
2348
  ensure_tp(type_instance);
2340
2349
  if (PyDict_ContainsString(type_instance->tp_dict, "__getattribute__") || PyDict_ContainsString(type_instance->tp_dict, "__getattr__")) {
@@ -2441,12 +2450,6 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data)
2441
2450
  }
2442
2451
  }
2443
2452
 
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
-
2450
2453
  return true;
2451
2454
  }
2452
2455
 
@@ -2808,6 +2811,7 @@ create_private_attr_base_simple(void)
2808
2811
  PyDict_SetItemString(dict, "__private_attrs__", private_attrs);
2809
2812
  PyDict_SetItemString(dict, "__slots__", private_attrs);
2810
2813
  PyDict_SetItemString(dict, "__doc__", PyUnicode_FromString(PrivateAttrBase_doc));
2814
+ PyDict_SetItemString(dict, "__module__", PyUnicode_FromString("private_attribute"));
2811
2815
  PyObject *args = PyTuple_Pack(3, name, bases, dict);
2812
2816
  PyObject* base_type;
2813
2817
  if (args) {
@@ -2825,8 +2829,6 @@ create_private_attr_base_simple(void)
2825
2829
  if (!base_type) {
2826
2830
  return NULL;
2827
2831
  }
2828
- // set "__module__"
2829
- PyType_Type.tp_setattro(base_type, PyUnicode_FromString("__module__"), PyUnicode_FromString("private_attribute"));
2830
2832
  ((PyTypeObject*)base_type)->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
2831
2833
  return base_type;
2832
2834
  }
@@ -71,7 +71,7 @@ class PrivateWrapProxy:
71
71
  ```
72
72
  """
73
73
  def __init__(self, decorator: Callable[[_TVar], _T], orig: _PrivateWrap[Any]|None = None, /) -> None: ...
74
- def __call__(self, func: _TVar, /) -> _PrivateWrap[_T]: ...
74
+ def __call__(self, func: _TVar | _PrivateWrap[_TVar], /) -> _PrivateWrap[_T]: ...
75
75
 
76
76
  class PrivateAttrType(type):
77
77
  "metaclass for private attributes"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.4.5
3
+ Version: 1.4.7
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
@@ -250,7 +250,8 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
250
250
  - One class defined in another class cannot use another class's private attribute.
251
251
  - One parent class defined an attribute which not in `__private_attrs__` or not a `PrivateAttrType` instance, the child class shouldn't contain the attribute in its `__private_attrs__`.
252
252
  - CPython may change "tp_getattro", "tp_setattro" and so on when you change the attribute "\_\_getattribute\_\_", "\_\_setattr\_\_" and so on. If you are fear about it, you can use `ensure_type` to reset those tp slots. For the other metaclasses, you can use `ensure_metaclass` to reset those tp slots. Also, don't set those methods on these classes in your code.
253
- - `private_attribute.register_metaclass` must be called with the metaclass which support weakref.
253
+ - `private_attribute.register_metaclass` must be called with the metaclass which supports weakref.
254
+ - Don't set `__static_attributes__` in private attribute class, or it will be removed.
254
255
 
255
256
  ## License
256
257
 
@@ -18,7 +18,7 @@ readme = open('README.md').read()
18
18
 
19
19
  setup(
20
20
  name='private_attribute_cpp',
21
- version='1.4.5',
21
+ version='1.4.7',
22
22
  author="HuangHaoHua",
23
23
  author_email="13140752715@example.com",
24
24
  description='A Python package that provides a way to define private attributes in C++ implementation.',
@@ -4,6 +4,7 @@ import unittest
4
4
  class MyClass(private_attribute.PrivateAttrBase):
5
5
  __private_attrs__ = ["_secret"]
6
6
  _secret = 1
7
+
7
8
  @classmethod
8
9
  def get_secret(cls):
9
10
  return cls._secret
@@ -19,4 +20,4 @@ class TestClassPrivateAttrs(unittest.TestCase):
19
20
  self.assertEqual(a.get_secret(), 1)
20
21
 
21
22
  if __name__ == "__main__":
22
- unittest.main()
23
+ unittest.main()
@@ -16,6 +16,7 @@ private_attribute.register_metaclass(PrivateAbcMeta)
16
16
  class MyClass(ABC, metaclass=PrivateAbcMeta):
17
17
  __private_attrs__ = ["_secret1"]
18
18
  _secret1 = 10
19
+
19
20
  @classmethod
20
21
  def get_secret1(cls):
21
22
  return cls._secret1
@@ -26,6 +27,7 @@ class MyClass(ABC, metaclass=PrivateAbcMeta):
26
27
 
27
28
  class ConcreteClass(MyClass):
28
29
  __private_attrs__ = ["_secret2"]
30
+
29
31
  def __init__(self, secret1, secret2):
30
32
  self._secret1 = secret1
31
33
  self._secret2 = secret2
@@ -50,4 +52,4 @@ class TestPrivateAbc(unittest.TestCase):
50
52
  self.assertEqual(ConcreteClass.get_secret1(), 10)
51
53
 
52
54
  if __name__ == '__main__':
53
- unittest.main()
55
+ unittest.main()
@@ -4,6 +4,7 @@ import unittest
4
4
  class BaseClass(private_attribute.PrivateAttrBase):
5
5
  __private_attrs__ = ["_a", "_b"]
6
6
  __slots__ = ["c", "d"]
7
+
7
8
  def __init__(self, a, b, c, d):
8
9
  self._a = a
9
10
  self._b = b
@@ -47,4 +48,4 @@ class TestPrivateAttributes(unittest.TestCase):
47
48
  self.assertTrue(isinstance(i, tuple))
48
49
 
49
50
  if __name__ == "__main__":
50
- unittest.main()
51
+ unittest.main()
@@ -24,4 +24,4 @@ class TestPrivateFunc(unittest.TestCase):
24
24
  obj._secret
25
25
 
26
26
  if __name__ == "__main__":
27
- unittest.main()
27
+ unittest.main()
@@ -37,4 +37,4 @@ class TestPrivateInheritance(unittest.TestCase):
37
37
  obj._other_value
38
38
 
39
39
  if __name__ == "__main__":
40
- unittest.main()
40
+ unittest.main()
@@ -27,4 +27,4 @@ class TestPrivateMethod(unittest.TestCase):
27
27
  obj._a
28
28
 
29
29
  if __name__ == "__main__":
30
- unittest.main()
30
+ unittest.main()
@@ -11,9 +11,13 @@ class MyWrap:
11
11
  setattr(self, f"func{self.index}", func)
12
12
  return self
13
13
 
14
- def get(self, index, instance, owner):
15
- func = getattr(self, f"func{index}")
16
- return func.__get__(instance, owner)
14
+ def __get__(self, instance, owner):
15
+ if instance is None:
16
+ return self
17
+ def wrapper(index, *args, **kwargs):
18
+ func = getattr(self, f"func{index}")
19
+ return func.__get__(instance, owner)(*args, **kwargs)
20
+ return wrapper
17
21
 
18
22
  class MyClass(private_attribute.PrivateAttrBase):
19
23
  __private_attrs__ = ["_secret1", "_secret2", "_secret3"]
@@ -37,9 +41,9 @@ class MyClass(private_attribute.PrivateAttrBase):
37
41
  class TestPrivateWrap(unittest.TestCase):
38
42
  def test_private_wrap(self):
39
43
  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)
44
+ self.assertEqual(a.get_secret(1), 1)
45
+ self.assertEqual(a.get_secret(2), 2)
46
+ self.assertEqual(a.get_secret(3), 3)
43
47
  with self.assertRaises(AttributeError):
44
48
  a._secret1
45
49
  with self.assertRaises(AttributeError):
@@ -48,4 +52,4 @@ class TestPrivateWrap(unittest.TestCase):
48
52
  a._secret3
49
53
 
50
54
  if __name__ == "__main__":
51
- unittest.main()
55
+ unittest.main()