private-attribute-cpp 2.1.22__tar.gz → 2.1.24__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 (24) hide show
  1. {private_attribute_cpp-2.1.22/private_attribute_cpp.egg-info → private_attribute_cpp-2.1.24}/PKG-INFO +1 -1
  2. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/private_attribute.cpp +190 -256
  3. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/private_attribute.pyi +1 -1
  4. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
  5. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/setup.py +1 -1
  6. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_private_wrap.py +10 -2
  7. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/LICENSE +0 -0
  8. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/MANIFEST.in +0 -0
  9. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/README.md +0 -0
  10. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/picosha2.h +0 -0
  11. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
  12. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  13. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  14. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  15. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/setup.cfg +0 -0
  16. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_attr_classify_owner.py +0 -0
  17. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_class_private_attrs.py +0 -0
  18. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_gc_collect.py +0 -0
  19. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_private_abc.py +0 -0
  20. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_private_attrs.py +0 -0
  21. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_private_func.py +0 -0
  22. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_private_inheritance.py +0 -0
  23. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_private_method.py +0 -0
  24. {private_attribute_cpp-2.1.22 → private_attribute_cpp-2.1.24}/tests/test_slots_cycle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.1.22
3
+ Version: 2.1.24
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
@@ -125,6 +125,18 @@ public:
125
125
  PyObjectStorage(PyObject* obj) noexcept : obj(obj) {
126
126
  Py_XINCREF(obj);
127
127
  }
128
+ // Construct a PyObjectStorage that takes ownership of a strong reference
129
+ // already held by the caller (a "new reference"). The reference count is
130
+ // NOT incremented; the stored object's ownership is simply transferred
131
+ // into the storage, and the destructor will release it exactly once.
132
+ static PyObjectStorage from_new_ref(PyObject* obj) noexcept {
133
+ PyObjectStorage storage;
134
+ storage.obj = obj;
135
+ return storage;
136
+ }
137
+ static PyObjectStorage from_new_ref(PyCodeObject* obj) noexcept {
138
+ return from_new_ref(reinterpret_cast<PyObject*>(obj));
139
+ }
128
140
  // support for PyCodeObject*
129
141
  PyObjectStorage(PyCodeObject* obj) noexcept : obj(reinterpret_cast<PyObject*>(obj)) {
130
142
  Py_XINCREF(obj);
@@ -176,9 +188,10 @@ public:
176
188
  return obj;
177
189
  }
178
190
 
179
- operator PyCodeObject*() const noexcept {
180
- return reinterpret_cast<PyCodeObject*>(obj);
191
+ explicit operator bool() const noexcept {
192
+ return obj != NULL;
181
193
  }
194
+
182
195
  PyObject* get() const noexcept {
183
196
  return obj;
184
197
  }
@@ -506,22 +519,22 @@ custom_random_string(uintptr_t obj_id, const std::string& attr_name, PyObject* f
506
519
  return result;
507
520
  } else {
508
521
  lock.unlock();
509
- PyObject* python_result = PyObject_CallFunction(
510
- func,
511
- "Ks",
512
- static_cast<unsigned long long>(obj_id),
513
- attr_name.c_str()
522
+ PyObjectStorage python_result = PyObjectStorage::from_new_ref(
523
+ PyObject_CallFunction(
524
+ func,
525
+ "Ks",
526
+ static_cast<unsigned long long>(obj_id),
527
+ attr_name.c_str()
528
+ )
514
529
  );
515
530
  if (python_result) {
516
531
  if (!PyUnicode_Check(python_result)) {
517
- Py_DECREF(python_result);
518
- PyErr_SetString(PyExc_TypeError, "private_func function must return a string");
532
+ PyErr_Format(PyExc_TypeError, "private_func function must return a string, not '%s'", Py_TYPE(python_result)->tp_name);
519
533
  result.ok = false;
520
534
  result.value = "private_func function must return a string";
521
535
  return result;
522
536
  }
523
537
  result.value = PyUnicode_AsUTF8(python_result);
524
- Py_DECREF(python_result);
525
538
  std::string original_result = result.value;
526
539
  unsigned long long i = 1;
527
540
  std::unique_lock<std::shared_mutex> lock2(::AllData::cache_mutex);
@@ -1462,6 +1475,10 @@ PrivateWrap_New(PyObject *decorator, PyObject *func, PyObject *list) noexcept
1462
1475
 
1463
1476
  PrivateWrapObject *self =
1464
1477
  PyObject_GC_New(PrivateWrapObject, &PrivateWrapType);
1478
+ if (!self) {
1479
+ Py_DECREF(wrapped);
1480
+ return NULL;
1481
+ }
1465
1482
  self->func_list = list;
1466
1483
  Py_INCREF(list);
1467
1484
 
@@ -1499,19 +1516,20 @@ PrivateWrapProxy_call(PrivateWrapProxyObject *self, PyObject *args, PyObject* /*
1499
1516
  PyObject *func;
1500
1517
  if (!PyArg_ParseTuple(args, "O:private_attribute.PrivateWrapProxy.__call__", &func)) return NULL;
1501
1518
  if(PyObject_TypeCheck(func, &PrivateWrapType)) {
1519
+ PyObjectStorage final_func_list = PyObjectStorage::from_new_ref(
1520
+ PySequence_Concat(((PrivateWrapObject*)func)->func_list, self->func_list));
1502
1521
  return (PyObject*)PrivateWrap_New(
1503
1522
  self->decorator,
1504
1523
  ((PrivateWrapObject*)func)->result,
1505
- PySequence_Concat(((PrivateWrapObject*)func)->func_list,
1506
- self->func_list)
1524
+ final_func_list
1507
1525
  );
1508
1526
  }
1509
1527
 
1510
1528
  PyObject *new_list = PyList_New(0);
1511
1529
  PyList_Append(new_list, func);
1512
1530
 
1513
- PyObject *combined =
1514
- PySequence_Concat(new_list, self->func_list);
1531
+ PyObjectStorage combined =
1532
+ PyObjectStorage::from_new_ref(PySequence_Concat(new_list, self->func_list));
1515
1533
 
1516
1534
  return (PyObject*)PrivateWrap_New(
1517
1535
  self->decorator,
@@ -1668,25 +1686,24 @@ PrivateAttr_tp_getattro(PyObject* self, PyObject* name) noexcept
1668
1686
  uintptr_t type_id = (uintptr_t)typ;
1669
1687
  PrivateAttr_object_init_private_dict((uintptr_t)self, type_id);
1670
1688
  std::string name_str = PyUnicode_AsUTF8(name);
1671
- auto code = get_now_code();
1672
- if (type_private_attr(type_id, name_str)) {
1673
- if (!code) {
1674
- Py_XDECREF(code);
1675
- PyErr_SetString(PyExc_AttributeError, "private attribute");
1676
- return NULL;
1677
- }
1678
- AttrClassifyResult classify = attr_classify(type_id, name_str, code);
1679
- Py_XDECREF(code);
1680
- if (!classify.allowed) {
1681
- PyErr_SetString(PyExc_AttributeError, "private attribute");
1682
- return NULL;
1683
- }
1684
- if (classify.type_id != 0) {
1685
- return id_getattr(classify.type_id, name_str, self, (PyObject*)typ);
1689
+ {
1690
+ PyObjectStorage code = PyObjectStorage::from_new_ref(get_now_code());
1691
+ if (type_private_attr(type_id, name_str)) {
1692
+ if (!code) {
1693
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
1694
+ return NULL;
1695
+ }
1696
+ AttrClassifyResult classify = attr_classify(type_id, name_str, (PyCodeObject*)(code.get()));
1697
+ if (!classify.allowed) {
1698
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
1699
+ return NULL;
1700
+ }
1701
+ if (classify.type_id != 0) {
1702
+ return id_getattr(classify.type_id, name_str, self, (PyObject*)typ);
1703
+ }
1704
+ // owner is 0: not private for this access context -> normal attribute
1686
1705
  }
1687
- // owner is 0: not private for this access context -> normal attribute
1688
1706
  }
1689
- Py_XDECREF(code);
1690
1707
  if (::AllData::all_type_getattro.find(type_id) != ::AllData::all_type_getattro.end()){
1691
1708
  if (::AllData::all_type_getattro[type_id]) {
1692
1709
  PyObject* result = ::AllData::all_type_getattro[type_id](self, name);
@@ -1707,28 +1724,27 @@ PrivateAttr_tp_setattro(PyObject* self, PyObject* name, PyObject* value) noexcep
1707
1724
  return -1;
1708
1725
  }
1709
1726
  std::string name_str(c_name);
1710
- auto code = get_now_code();
1711
- if (type_private_attr(typ_id, name_str)) {
1712
- if (!code) {
1713
- PyErr_SetString(PyExc_AttributeError, "private attribute");
1714
- Py_XDECREF(code);
1715
- return -1;
1716
- }
1717
- AttrClassifyResult classify = attr_classify(typ_id, name_str, code);
1718
- Py_XDECREF(code);
1719
- if (!classify.allowed) {
1720
- PyErr_SetString(PyExc_AttributeError, "private attribute");
1721
- return -1;
1722
- }
1723
- if (classify.type_id != 0) {
1724
- if (!value) {
1725
- return id_delattr(classify.type_id, name_str, self, (PyObject*)typ);
1727
+ {
1728
+ PyObjectStorage code = PyObjectStorage::from_new_ref(get_now_code());
1729
+ if (type_private_attr(typ_id, name_str)) {
1730
+ if (!code) {
1731
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
1732
+ return -1;
1733
+ }
1734
+ AttrClassifyResult classify = attr_classify(typ_id, name_str, (PyCodeObject*)(code.get()));
1735
+ if (!classify.allowed) {
1736
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
1737
+ return -1;
1726
1738
  }
1727
- return id_setattr(classify.type_id, name_str, self, (PyObject*)typ, value);
1739
+ if (classify.type_id != 0) {
1740
+ if (!value) {
1741
+ return id_delattr(classify.type_id, name_str, self, (PyObject*)typ);
1742
+ }
1743
+ return id_setattr(classify.type_id, name_str, self, (PyObject*)typ, value);
1744
+ }
1745
+ // owner is 0: not private for this access context -> normal attribute
1728
1746
  }
1729
- // owner is 0: not private for this access context -> normal attribute
1730
1747
  }
1731
- Py_XDECREF(code);
1732
1748
  if (::AllData::all_type_setattro.find(typ_id) != ::AllData::all_type_setattro.end()){
1733
1749
  int result = ::AllData::all_type_setattro[typ_id](self, name, value);
1734
1750
  ensure_tp(typ);
@@ -2636,10 +2652,9 @@ analyse_all_code(PyObject* obj, std::unordered_map<uintptr_t, PyObjectStorage>&
2636
2652
  Py_ssize_t len = PySequence_Length(co_contain);
2637
2653
  if (len >= 0) {
2638
2654
  for (Py_ssize_t i = 0; i < len; i++) {
2639
- PyObject* item = PySequence_GetItem(co_contain, i);
2655
+ PyObjectStorage item = PyObjectStorage::from_new_ref(PySequence_GetItem(co_contain, i));
2640
2656
  if (item) {
2641
2657
  analyse_all_code(item, map, _seen);
2642
- Py_DECREF(item);
2643
2658
  }
2644
2659
  }
2645
2660
  }
@@ -2653,10 +2668,9 @@ analyse_all_code(PyObject* obj, std::unordered_map<uintptr_t, PyObjectStorage>&
2653
2668
  Py_ssize_t len = PySequence_Length(func_list);
2654
2669
  if (len >= 0) {
2655
2670
  for (Py_ssize_t i = 0; i < len; i++) {
2656
- PyObject* func = PySequence_GetItem(func_list, i);
2671
+ PyObjectStorage func = PyObjectStorage::from_new_ref(PySequence_GetItem(func_list, i));
2657
2672
  if (func) {
2658
2673
  analyse_all_code(func, map, _seen);
2659
- Py_DECREF(func);
2660
2674
  }
2661
2675
  }
2662
2676
  }
@@ -2664,50 +2678,44 @@ analyse_all_code(PyObject* obj, std::unordered_map<uintptr_t, PyObjectStorage>&
2664
2678
  return;
2665
2679
  }
2666
2680
  if (PyObject_TypeCheck(obj, &PyProperty_Type)) {
2667
- PyObject* fget = try_get_attr_string(obj, "fget");
2681
+ PyObjectStorage fget = PyObjectStorage::from_new_ref(try_get_attr_string(obj, "fget"));
2668
2682
  if (fget) {
2669
2683
  analyse_all_code(fget, map, _seen);
2670
- Py_DECREF(fget);
2671
2684
  }
2672
- PyObject* fset = try_get_attr_string(obj, "fset");
2685
+ PyObjectStorage fset = PyObjectStorage::from_new_ref(try_get_attr_string(obj, "fset"));
2673
2686
  if (fset) {
2674
2687
  analyse_all_code(fset, map, _seen);
2675
- Py_DECREF(fset);
2676
2688
  }
2677
- PyObject* fdel = try_get_attr_string(obj, "fdel");
2689
+ PyObject* fdel = PyObjectStorage::from_new_ref(try_get_attr_string(obj, "fdel"));
2678
2690
  if (fdel) {
2679
2691
  analyse_all_code(fdel, map, _seen);
2680
- Py_DECREF(fdel);
2681
2692
  }
2682
2693
  return;
2683
2694
  }
2684
2695
  if (PyObject_TypeCheck(obj, &PyClassMethod_Type) || PyObject_TypeCheck(obj, &PyStaticMethod_Type)) {
2685
- PyObject* func = try_get_attr_string(obj, "__func__");
2696
+ PyObjectStorage func = PyObjectStorage::from_new_ref(try_get_attr_string(obj, "__func__"));
2686
2697
  if (func) {
2687
2698
  analyse_all_code(func, map, _seen);
2688
- Py_DECREF(func);
2689
2699
  }
2690
2700
  return;
2691
2701
  }
2692
- PyObject* wrap = try_get_attr_string(obj, "__wrapped__");
2693
- if (wrap) {
2694
- if (wrap == obj) {
2695
- PyObject* code = try_get_attr_string(obj, "__code__");
2696
- if (code) {
2697
- analyse_all_code(code, map, _seen);
2698
- Py_DECREF(code);
2702
+ {
2703
+ PyObjectStorage wrap = PyObjectStorage::from_new_ref(try_get_attr_string(obj, "__wrapped__"));
2704
+ if (wrap) {
2705
+ if (wrap == obj) {
2706
+ PyObjectStorage code = PyObjectStorage::from_new_ref(try_get_attr_string(obj, "__code__"));
2707
+ if (code) {
2708
+ analyse_all_code(code, map, _seen);
2709
+ }
2710
+ return;
2699
2711
  }
2700
- Py_DECREF(wrap);
2712
+ analyse_all_code(wrap, map, _seen);
2701
2713
  return;
2702
2714
  }
2703
- analyse_all_code(wrap, map, _seen);
2704
- Py_DECREF(wrap);
2705
- return;
2706
2715
  }
2707
- PyObject* code = try_get_attr_string(obj, "__code__");
2716
+ PyObjectStorage code = PyObjectStorage::from_new_ref(try_get_attr_string(obj, "__code__"));
2708
2717
  if (code) {
2709
2718
  analyse_all_code(code, map, _seen);
2710
- Py_DECREF(code);
2711
2719
  }
2712
2720
  }
2713
2721
 
@@ -2854,8 +2862,7 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
2854
2862
  __private_attrs__ = PyDict_GetItemString(data.attrs, "__private_attrs__");
2855
2863
  }
2856
2864
  else {
2857
- __private_attrs__ = PyTuple_New(0);
2858
- Py_DECREF(__private_attrs__);
2865
+ __private_attrs__ = PyObjectStorage::from_new_ref(PyTuple_New(0));
2859
2866
  }
2860
2867
 
2861
2868
  if (PyUnicode_Check(__private_attrs__)) {
@@ -2864,8 +2871,7 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
2864
2871
  return false;
2865
2872
  }
2866
2873
  PyTuple_SET_ITEM(new___private_attrs__, 0, __private_attrs__);
2867
- __private_attrs__ = new___private_attrs__;
2868
- Py_DECREF(__private_attrs__);
2874
+ __private_attrs__ = PyObjectStorage::from_new_ref(new___private_attrs__);
2869
2875
  }
2870
2876
 
2871
2877
  if (!PySequence_Check(__private_attrs__)) {
@@ -2935,41 +2941,38 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
2935
2941
  if (PyUnicode_Check(all_slots)) {
2936
2942
  const char* slot_cstr = PyUnicode_AsUTF8(all_slots);
2937
2943
  if (data.private_attrs_vector_string.find((std::string)slot_cstr) != data.private_attrs_vector_string.end()){
2938
- std::string error_msg = "'__slots__' and '__private_attrs__' cannot have the same attribute name: '" + std::string(slot_cstr) + "'";
2939
- PyErr_SetString(PyExc_TypeError, error_msg.c_str());
2944
+ PyErr_Format(PyExc_TypeError, "'__slots__' and '__private_attrs__' cannot have the same attribute name: '%s'", slot_cstr);
2940
2945
  return false;
2941
2946
  }
2942
2947
  } else {
2943
- PyObject* slot_seq;
2948
+ PyObjectStorage slot_seq;
2944
2949
  if (PyAnyDict_Check(all_slots)) {
2945
2950
  // use the key of the dict as the slot name
2946
2951
  PyObject* keys = PyDict_Keys(all_slots);
2947
2952
  if (!keys) {
2948
2953
  return false;
2949
2954
  }
2950
- slot_seq = keys;
2955
+ slot_seq = PyObjectStorage::from_new_ref(keys);
2951
2956
  } else {
2952
- slot_seq = PySequence_Fast(all_slots, "__slots__ must be a string, dict or sequence");
2957
+ slot_seq = PyObjectStorage::from_new_ref(PySequence_Fast(all_slots, "__slots__ must be a string, dict or sequence"));
2953
2958
  }
2954
- if (!slot_seq) {
2959
+ if (!slot_seq.get()) {
2955
2960
  return false;
2956
2961
  }
2957
2962
 
2958
- Py_ssize_t slot_len = PySequence_Fast_GET_SIZE(slot_seq);
2963
+ Py_ssize_t slot_len = PySequence_Fast_GET_SIZE(slot_seq.get());
2959
2964
 
2960
2965
  for (Py_ssize_t j = 0; j < slot_len; j++) {
2961
- PyObject* slot = PySequence_Fast_GET_ITEM(slot_seq, j);
2966
+ PyObject* slot = PySequence_Fast_GET_ITEM(slot_seq.get(), j);
2962
2967
  if (PyUnicode_Check(slot)) {
2963
2968
  const char* slot_cstr = PyUnicode_AsUTF8(slot);
2964
2969
  std::string final_name = real_class_name(slot_cstr, data.class_name);
2965
2970
  if (data.private_attrs_vector_string.find(final_name) != data.private_attrs_vector_string.end()){
2966
2971
  PyErr_Format(PyExc_TypeError, "'__slots__' and '__private_attrs__' cannot have the same attribute name: '%s'", final_name.c_str());
2967
- Py_DECREF(slot_seq);
2968
2972
  return false;
2969
2973
  }
2970
2974
  }
2971
2975
  }
2972
- Py_DECREF(slot_seq);
2973
2976
  }
2974
2977
  }
2975
2978
 
@@ -2999,7 +3002,7 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
2999
3002
  {
3000
3003
  Py_ssize_t pos = 0;
3001
3004
  PyObject* key, *value;
3002
- PyObject* forward_analyse = PyDict_Copy(data.attrs_copy);
3005
+ PyObjectStorage forward_analyse = PyObjectStorage::from_new_ref(PyDict_Copy(data.attrs_copy));
3003
3006
  while (PyDict_Next(forward_analyse, &pos, &key, &value)) {
3004
3007
  if (!key || !PyUnicode_Check(key)) {
3005
3008
  PyErr_SetString(PyExc_TypeError, "all keys in 'attrs' must be strings");
@@ -3038,7 +3041,6 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
3038
3041
  if (PyDict_SetItem(data.attrs_copy, key, need_value) < 0) return false;
3039
3042
  }
3040
3043
  }
3041
- Py_DECREF(forward_analyse);
3042
3044
  }
3043
3045
 
3044
3046
  // get "private_func" from kwds
@@ -3314,7 +3316,8 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
3314
3316
  }
3315
3317
 
3316
3318
  if (data.private_func) {
3317
- Py_INCREF(data.private_func);
3319
+ // The PyObjectStorage assignment already INCREFs (RAII); the manual
3320
+ // INCREF was removed to avoid a +1 leak.
3318
3321
  ::AllData::type_need_call[type_id] = data.private_func;
3319
3322
  }
3320
3323
 
@@ -3402,25 +3405,23 @@ PrivateAttrType_getattr(PyObject* cls, PyObject* name) noexcept
3402
3405
  }
3403
3406
  uintptr_t typ_id = (uintptr_t)(cls);
3404
3407
  std::string name_str = PyUnicode_AsUTF8(name);
3405
- PyCodeObject* now_code = get_now_code();
3406
- if (type_private_attr(typ_id, name_str)) {
3407
- if (!now_code) {
3408
- PyErr_SetString(PyExc_AttributeError, "private attribute");
3409
- Py_XDECREF(now_code);
3410
- return NULL;
3411
- }
3412
- AttrClassifyResult classify = attr_classify(typ_id, name_str, now_code);
3413
- Py_XDECREF(now_code);
3414
- if (!classify.allowed) {
3415
- PyErr_SetString(PyExc_AttributeError, "private attribute");
3416
- return NULL;
3417
- }
3418
- if (classify.type_id != 0) {
3419
- return type_getattr(cls, name_str);
3408
+ {
3409
+ PyObjectStorage now_code = PyObjectStorage::from_new_ref(get_now_code());
3410
+ if (type_private_attr(typ_id, name_str)) {
3411
+ if (!now_code) {
3412
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
3413
+ return NULL;
3414
+ }
3415
+ AttrClassifyResult classify = attr_classify(typ_id, name_str, (PyCodeObject*)(now_code.get()));
3416
+ if (!classify.allowed) {
3417
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
3418
+ return NULL;
3419
+ }
3420
+ if (classify.type_id != 0) {
3421
+ return type_getattr(cls, name_str);
3422
+ }
3420
3423
  }
3421
- // owner is 0: not private for this access context -> normal attribute
3422
3424
  }
3423
- Py_XDECREF(now_code);
3424
3425
  PyTypeObject* base = Py_TYPE(cls)->tp_base;
3425
3426
  while (base && base->tp_base && base->tp_getattro == PrivateAttrType_getattr) {
3426
3427
  base = base->tp_base;
@@ -3493,35 +3494,31 @@ init_all_slots() noexcept
3493
3494
  return 0;
3494
3495
  }
3495
3496
  original_type_tp_setattro = PyType_Type.tp_setattro;
3496
- PyObject* original_setattr = PyObject_GetAttrString((PyObject*)&PyType_Type, "__setattr__");
3497
+ PyObjectStorage original_setattr = PyObjectStorage::from_new_ref(PyObject_GetAttrString((PyObject*)&PyType_Type, "__setattr__"));
3497
3498
  if (!original_setattr) {return -1;}
3498
3499
  if (original_setattr && PyObject_IsInstance(original_setattr, (PyObject*)&PyWrapperDescr_Type)) {
3499
- ((PyWrapperDescrObject*)original_setattr)->d_wrapped = (void*)new_type_tp_setattro;
3500
+ ((PyWrapperDescrObject*)(original_setattr.get()))->d_wrapped = (void*)new_type_tp_setattro;
3500
3501
  }
3501
- Py_DECREF(original_setattr);
3502
- PyObject* original_delattr = PyObject_GetAttrString((PyObject*)&PyType_Type, "__delattr__");
3502
+ PyObjectStorage original_delattr = PyObjectStorage::from_new_ref(PyObject_GetAttrString((PyObject*)&PyType_Type, "__delattr__"));
3503
3503
  if (!original_delattr) {return -1;}
3504
3504
  if (original_delattr && PyObject_IsInstance(original_delattr, (PyObject*)&PyWrapperDescr_Type)) {
3505
- ((PyWrapperDescrObject*)original_delattr)->d_wrapped = (void*)new_type_tp_setattro;
3505
+ ((PyWrapperDescrObject*)(original_delattr.get()))->d_wrapped = (void*)new_type_tp_setattro;
3506
3506
  }
3507
- Py_DECREF(original_delattr);
3508
3507
  PyType_Type.tp_setattro = new_type_tp_setattro;
3509
- PyObject* all_metaclasses = PyObject_CallMethod((PyObject*)&PyType_Type, "__subclasses__", "O", (PyObject*)&PyType_Type);
3508
+ PyObjectStorage all_metaclasses = PyObjectStorage::from_new_ref(PyObject_CallMethod((PyObject*)&PyType_Type, "__subclasses__", "O", (PyObject*)&PyType_Type));
3510
3509
  if (!all_metaclasses) {return -1;}
3511
3510
  if (!PyList_Check(all_metaclasses)) {
3512
- Py_DECREF(all_metaclasses);
3513
- has_init_slots = true;
3514
- return 0;
3511
+ PyErr_SetString(PyExc_TypeError, "subclasses of type is not list");
3512
+ return -1;
3515
3513
  }
3516
- Py_ssize_t list_len = PyList_GET_SIZE(all_metaclasses);
3514
+ Py_ssize_t list_len = PyList_GET_SIZE(all_metaclasses.get());
3517
3515
  for (Py_ssize_t i = 0; i < list_len; i++) {
3518
- PyObject* metaclass = PyList_GET_ITEM(all_metaclasses, i);
3516
+ PyObject* metaclass = PyList_GET_ITEM(all_metaclasses.get(), i);
3519
3517
  if (!PyType_Check(metaclass)) {continue;}
3520
3518
  if (((PyTypeObject*)metaclass)->tp_setattro == original_type_tp_setattro) {
3521
3519
  ((PyTypeObject*)metaclass)->tp_setattro = new_type_tp_setattro;
3522
3520
  }
3523
3521
  }
3524
- Py_DECREF(all_metaclasses);
3525
3522
  has_init_slots = true;
3526
3523
  return 0;
3527
3524
  }
@@ -3756,25 +3753,24 @@ PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value) noexcept
3756
3753
  PyErr_SetString(PyExc_TypeError, error_message.c_str());
3757
3754
  return -1;
3758
3755
  }
3759
- PyCodeObject* now_code = get_now_code();
3760
- if (type_private_attr(typ_id, name_str)) {
3761
- if (!now_code) {
3762
- PyErr_SetString(PyExc_AttributeError, "private attribute");
3763
- Py_XDECREF(now_code);
3764
- return -1;
3765
- }
3766
- AttrClassifyResult classify = attr_classify(typ_id, name_str, now_code);
3767
- Py_XDECREF(now_code);
3768
- if (!classify.allowed) {
3769
- PyErr_SetString(PyExc_AttributeError, "private attribute");
3770
- return -1;
3771
- }
3772
- if (classify.type_id != 0) {
3773
- return type_setattr(cls, name_str, value);
3756
+ {
3757
+ PyObjectStorage now_code = PyObjectStorage::from_new_ref(get_now_code());
3758
+ if (type_private_attr(typ_id, name_str)) {
3759
+ if (!now_code) {
3760
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
3761
+ return -1;
3762
+ }
3763
+ AttrClassifyResult classify = attr_classify(typ_id, name_str, (PyCodeObject*)(now_code.get()));
3764
+ if (!classify.allowed) {
3765
+ PyErr_SetString(PyExc_AttributeError, "private attribute");
3766
+ return -1;
3767
+ }
3768
+ if (classify.type_id != 0) {
3769
+ return type_setattr(cls, name_str, value);
3770
+ }
3771
+ // owner is 0: not private for this access context -> normal attribute
3774
3772
  }
3775
- // owner is 0: not private for this access context -> normal attribute
3776
3773
  }
3777
- Py_XDECREF(now_code);
3778
3774
  PyTypeObject* base = Py_TYPE(cls)->tp_base;
3779
3775
  while (base && base->tp_base && base->tp_setattro == PrivateAttrType_setattr) {
3780
3776
  base = base->tp_base;
@@ -3854,86 +3850,55 @@ PrivateAttrType_del(PyObject* cls) noexcept
3854
3850
  PyType_Type.tp_dealloc(cls);
3855
3851
  }
3856
3852
 
3857
- static const char* PrivateAttrBase_doc = "The class to help to create private attribute. It does not have any special behavior.";
3853
+ static const char* PrivateAttrBase_doc = "The class to help creating private attribute. It does not have any special behavior.";
3858
3854
 
3859
3855
  // PrivateAttrBase
3860
3856
  static PyObject*
3861
3857
  create_private_attr_base_simple(void) noexcept
3862
3858
  {
3863
- PyObject* name = NULL;
3864
- PyObject* bases = NULL;
3865
- PyObject* dict = NULL;
3866
- PyObject* private_attrs = NULL;
3867
- PyObject* doc = NULL;
3868
- PyObject* module_name = NULL;
3869
- PyObject* args = NULL;
3870
- PyObject* base_type = NULL;
3871
-
3872
- name = PyUnicode_InternFromString("PrivateAttrBase");
3873
- if (!name) goto fail;
3874
-
3875
- bases = PyTuple_New(0);
3876
- if (!bases) goto fail;
3859
+ PyObjectStorage name = PyObjectStorage::from_new_ref(PyUnicode_InternFromString("PrivateAttrBase"));
3860
+ if (!name) return NULL;
3877
3861
 
3878
- dict = PyDict_New();
3879
- if (!dict) goto fail;
3862
+ PyObjectStorage bases = PyObjectStorage::from_new_ref(PyTuple_New(0));
3863
+ if (!bases) return NULL;
3880
3864
 
3881
- private_attrs = PyTuple_New(0);
3882
- if (!private_attrs) goto fail;
3865
+ PyObjectStorage dict = PyObjectStorage::from_new_ref(PyDict_New());
3866
+ if (!dict) return NULL;
3883
3867
 
3884
- doc = PyUnicode_InternFromString(PrivateAttrBase_doc);
3885
- if (!doc) goto fail;
3868
+ PyObjectStorage private_attrs = PyObjectStorage::from_new_ref(PyTuple_New(0));
3869
+ if (!private_attrs) return NULL;
3886
3870
 
3887
- module_name = PyUnicode_InternFromString("private_attribute");
3888
- if (!module_name) goto fail;
3871
+ PyObjectStorage doc = PyObjectStorage::from_new_ref(PyUnicode_InternFromString(PrivateAttrBase_doc));
3872
+ if (!doc) return NULL;
3889
3873
 
3890
- if (PyDict_SetItemString(dict, "__private_attrs__", private_attrs) < 0) goto fail;
3891
- if (PyDict_SetItemString(dict, "__slots__", private_attrs) < 0) goto fail;
3892
- if (PyDict_SetItemString(dict, "__doc__", doc) < 0) goto fail;
3893
- if (PyDict_SetItemString(dict, "__module__", module_name) < 0) goto fail;
3874
+ PyObjectStorage module_name = PyObjectStorage::from_new_ref(PyUnicode_InternFromString("private_attribute"));
3875
+ if (!module_name) return NULL;
3894
3876
 
3895
- Py_DECREF(doc);
3896
- doc = NULL;
3897
- Py_DECREF(module_name);
3898
- module_name = NULL;
3877
+ if (PyDict_SetItemString(dict, "__private_attrs__", private_attrs) < 0) return NULL;
3878
+ if (PyDict_SetItemString(dict, "__slots__", private_attrs) < 0) return NULL;
3879
+ if (PyDict_SetItemString(dict, "__doc__", doc) < 0) return NULL;
3880
+ if (PyDict_SetItemString(dict, "__module__", module_name) < 0) return NULL;
3899
3881
 
3900
- args = PyTuple_Pack(3, name, bases, dict);
3901
- if (!args) goto fail;
3882
+ PyObjectStorage args = PyObjectStorage::from_new_ref(PyTuple_Pack(3, name.get(), bases.get(), dict.get()));
3883
+ if (!args) return NULL;
3902
3884
 
3885
+ PyObject* base_type = NULL;
3903
3886
  {
3904
3887
  // RAII: the first heap type created through tp_new (PrivateAttrBase)
3905
3888
  // carries CPython's pristine subtype_traverse/subtype_clear in its
3906
3889
  // tp_traverse/tp_clear; PrivateAttrType_new captures those pointers
3907
3890
  // while this guard is active.
3908
3891
  PrivateAttrCaptureGuard capture_guard;
3909
- base_type = PrivateAttrType_new((PyTypeObject*)&PrivateAttrType, args, NULL);
3892
+ base_type = PrivateAttrType_new((PyTypeObject*)&PrivateAttrType, args.get(), NULL);
3910
3893
  }
3911
- Py_DECREF(args);
3912
- args = NULL;
3913
-
3914
- Py_DECREF(name);
3915
- name = NULL;
3916
- Py_DECREF(bases);
3917
- bases = NULL;
3918
- Py_DECREF(dict);
3919
- dict = NULL;
3920
3894
 
3921
- if (!base_type) goto fail;
3895
+ if (!base_type) return NULL;
3922
3896
 
3923
3897
  ((PyTypeObject*)base_type)->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
3924
3898
  return base_type;
3925
-
3926
- fail:
3927
- Py_XDECREF(name);
3928
- Py_XDECREF(bases);
3929
- Py_XDECREF(dict);
3930
- Py_XDECREF(private_attrs);
3931
- Py_XDECREF(doc);
3932
- Py_XDECREF(module_name);
3933
- Py_XDECREF(args);
3934
- return NULL;
3935
3899
  }
3936
3900
 
3901
+
3937
3902
  typedef struct {
3938
3903
  PyObject_HEAD
3939
3904
  PrivateAttrCreationData* tmp;
@@ -4132,7 +4097,8 @@ metaclass_weakref_callback(PyObject* self, PyObject* /*weakref*/) noexcept
4132
4097
 
4133
4098
  auto it = ::AllData::all_register_type_weak_ref.find(id);
4134
4099
  if (it != ::AllData::all_register_type_weak_ref.end()) {
4135
- Py_DECREF(it->second);
4100
+ // The PyObjectStorage destructor releases the stored reference on
4101
+ // erase; do not DECREF here (double-DECREF).
4136
4102
  ::AllData::all_register_type_weak_ref.erase(it);
4137
4103
  }
4138
4104
  METACLASS_WEAKREF_CALLBACK_REMOVE_ITEM(getattro);
@@ -4229,7 +4195,9 @@ register_metaclass_head(PyObject* metaclass) noexcept
4229
4195
  Py_DECREF(capsule);
4230
4196
  return NULL;
4231
4197
  }
4232
- ::AllData::all_register_type_weak_ref[id] = ref;
4198
+ // PyWeakref_NewRef returns a new reference; transfer it into the storage
4199
+ // without an extra INCREF (which the plain assignment operator would add).
4200
+ ::AllData::all_register_type_weak_ref[id] = PyObjectStorage::from_new_ref(ref);
4233
4201
  PyTypeObject* mt = (PyTypeObject*)metaclass;
4234
4202
  // Save the ORIGINAL slots before wrapping. Always resolve through the
4235
4203
  // get_type_need_tp_* walkers so a delegating default (CPython's
@@ -4374,50 +4342,33 @@ PrivateModule_get_PrivateAttrBase(PyObject* /*self*/, void* /*closure*/) noexcep
4374
4342
  return NULL;
4375
4343
  }
4376
4344
  AllData::store_module_self[AllData::kPrivateAttrBaseKey] = base;
4377
- Py_DECREF(base);
4378
- it = AllData::store_module_self.find(AllData::kPrivateAttrBaseKey);
4345
+ return base;
4379
4346
  }
4380
4347
  PyObject* PrivateAttrBase = it->second.get();
4381
4348
  Py_INCREF(PrivateAttrBase);
4382
4349
  return PrivateAttrBase;
4383
4350
  }
4384
4351
 
4385
- static int
4386
- PyList_AppendString(PyObject* list, const char* str) noexcept
4387
- {
4388
- PyObject* obj = PyUnicode_InternFromString(str);
4389
- if (!obj) return -1;
4390
- if (PyList_Append(list, obj) < 0) {
4391
- Py_DECREF(obj);
4392
- return -1;
4393
- }
4394
- Py_DECREF(obj);
4395
- return 0;
4396
- }
4397
-
4398
- #define DIR_CHECK(command) do {if (command < 0) goto finally;} while (0)
4399
-
4400
4352
  static PyObject*
4401
4353
  PrivateModule_dir(PyObject* self, PyObject* /*args*/) noexcept
4402
4354
  {
4403
4355
  PyObject* parent_dir = PyObject_CallMethod((PyObject*)&PyModule_Type, "__dir__", "O", self);
4404
4356
  if (!parent_dir) return NULL;
4405
- PyObject* attr_list = PyList_New(0);
4357
+ PyObject* attr_list = Py_BuildValue("[ssssssss]",
4358
+ "PrivateWrapProxy",
4359
+ "PrivateAttrType",
4360
+ "PrivateAttrBase",
4361
+ "prepare",
4362
+ "postprocess",
4363
+ "register_metaclass",
4364
+ "ensure_type",
4365
+ "ensure_metaclass"
4366
+ );
4406
4367
  if (!attr_list) {
4407
4368
  Py_DECREF(parent_dir);
4408
4369
  return NULL;
4409
4370
  }
4410
- PyObject* result = NULL;
4411
- DIR_CHECK(PyList_AppendString(attr_list, "PrivateWrapProxy"));
4412
- DIR_CHECK(PyList_AppendString(attr_list, "PrivateAttrType"));
4413
- DIR_CHECK(PyList_AppendString(attr_list, "PrivateAttrBase"));
4414
- DIR_CHECK(PyList_AppendString(attr_list, "prepare"));
4415
- DIR_CHECK(PyList_AppendString(attr_list, "postprocess"));
4416
- DIR_CHECK(PyList_AppendString(attr_list, "register_metaclass"));
4417
- DIR_CHECK(PyList_AppendString(attr_list, "ensure_type"));
4418
- DIR_CHECK(PyList_AppendString(attr_list, "ensure_metaclass"));
4419
- result = PySequence_Concat(parent_dir, attr_list);
4420
- finally:
4371
+ PyObject* result = PySequence_Concat(parent_dir, attr_list);
4421
4372
  Py_DECREF(parent_dir);
4422
4373
  Py_DECREF(attr_list);
4423
4374
  return result;
@@ -4676,25 +4627,21 @@ atexit_register_clean_func(void) noexcept
4676
4627
  if (resigtered_clean_func) {
4677
4628
  return 0;
4678
4629
  }
4679
- PyObject* atexit = PyImport_ImportModule("atexit");
4630
+ PyObjectStorage atexit = PyObjectStorage::from_new_ref(PyImport_ImportModule("atexit"));
4680
4631
  if (!atexit) {
4681
4632
  return -1;
4682
4633
  }
4683
4634
 
4684
- PyObject* func = PyCFunction_New(&clean_storage, NULL);
4635
+ PyObjectStorage func = PyObjectStorage::from_new_ref(PyCFunction_New(&clean_storage, NULL));
4685
4636
  if (!func) {
4686
- Py_DECREF(atexit);
4687
4637
  return -1;
4688
4638
  }
4689
4639
 
4690
- PyObject* result = PyObject_CallMethod(atexit, "register", "O", func);
4691
- Py_DECREF(func);
4692
- Py_DECREF(atexit);
4640
+ PyObjectStorage result = PyObjectStorage::from_new_ref(PyObject_CallMethod(atexit, "register", "O", func.get()));
4693
4641
 
4694
4642
  if (!result) {
4695
4643
  return -1;
4696
4644
  }
4697
- Py_DECREF(result);
4698
4645
  resigtered_clean_func = true;
4699
4646
  return 0;
4700
4647
  }
@@ -4702,7 +4649,7 @@ atexit_register_clean_func(void) noexcept
4702
4649
  static PyObject*
4703
4650
  PrivateModule_create(PyObject* spec, PyModuleDef* /*def*/) noexcept
4704
4651
  {
4705
- PyObject* name = PyObject_GetAttrString(spec, "name");
4652
+ PyObjectStorage name = PyObjectStorage::from_new_ref(PyObject_GetAttrString(spec, "name"));
4706
4653
  if (!name) {
4707
4654
  return NULL;
4708
4655
  }
@@ -4711,13 +4658,9 @@ PrivateModule_create(PyObject* spec, PyModuleDef* /*def*/) noexcept
4711
4658
  // PyInit_private_attribute is genuinely a
4712
4659
  // `private_attribute.private_attribute_module` instance from the start,
4713
4660
  // rather than a plain module re-typed with Py_SET_TYPE afterwards.
4714
- PyObject* m = PyObject_CallFunction((PyObject*)&PrivateModuleType, "O", name);
4715
- Py_DECREF(name);
4716
- return m;
4661
+ return PyObject_CallFunction((PyObject*)&PrivateModuleType, "O", name.get());
4717
4662
  }
4718
4663
 
4719
- #define MODULE_EXEC_CHECK(command) do {if (command < 0) {return -1;}} while(0)
4720
-
4721
4664
  static int
4722
4665
  PrivateModule_exec(PyObject* m) noexcept
4723
4666
  {
@@ -4730,7 +4673,16 @@ PrivateModule_exec(PyObject* m) noexcept
4730
4673
  return -1;
4731
4674
  }
4732
4675
  Py_DECREF(private_attr_base);
4733
- PyObject* all = PyList_New(0);
4676
+ PyObject* all = Py_BuildValue("[ssssssss]",
4677
+ "PrivateWrapProxy",
4678
+ "PrivateAttrType",
4679
+ "PrivateAttrBase",
4680
+ "prepare",
4681
+ "postprocess",
4682
+ "register_metaclass",
4683
+ "ensure_type",
4684
+ "ensure_metaclass"
4685
+ );
4734
4686
  if (!all) {
4735
4687
  return -1;
4736
4688
  }
@@ -4738,24 +4690,6 @@ PrivateModule_exec(PyObject* m) noexcept
4738
4690
  Py_DECREF(all);
4739
4691
  return -1;
4740
4692
  }
4741
- /* all contains:
4742
- * PrivateWrapProxy
4743
- * PrivateAttrType
4744
- * PrivateAttrBase
4745
- * prepare
4746
- * postprocess
4747
- * register_metaclass
4748
- * ensure_type
4749
- * ensure_metaclass
4750
- */
4751
- MODULE_EXEC_CHECK(PyList_AppendString(all, "PrivateWrapProxy"));
4752
- MODULE_EXEC_CHECK(PyList_AppendString(all, "PrivateAttrType"));
4753
- MODULE_EXEC_CHECK(PyList_AppendString(all, "PrivateAttrBase"));
4754
- MODULE_EXEC_CHECK(PyList_AppendString(all, "prepare"));
4755
- MODULE_EXEC_CHECK(PyList_AppendString(all, "postprocess"));
4756
- MODULE_EXEC_CHECK(PyList_AppendString(all, "register_metaclass"));
4757
- MODULE_EXEC_CHECK(PyList_AppendString(all, "ensure_type"));
4758
- MODULE_EXEC_CHECK(PyList_AppendString(all, "ensure_metaclass"));
4759
4693
 
4760
4694
  AllData::store_module_self[AllData::kModuleSelfKey] = m; // store module self
4761
4695
 
@@ -102,7 +102,7 @@ class PrivateAttrType(type):
102
102
  private_func: Callable[[int, str], str]|None = None) -> PrivateAttrType: ...
103
103
 
104
104
  class PrivateAttrBase(metaclass=PrivateAttrType):
105
- "The class to help to create private attribute. It does not have any special behavior."
105
+ "The class to help creating private attribute. It does not have any special behavior."
106
106
  __slots__ = ()
107
107
  __private_attrs__ = ()
108
108
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.1.22
3
+ Version: 2.1.24
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
@@ -24,7 +24,7 @@ readme = open('README.md').read()
24
24
 
25
25
  setup(
26
26
  name='private_attribute_cpp',
27
- version='2.1.22',
27
+ version='2.1.24',
28
28
  author="HuangHaoHua",
29
29
  author_email="13140752715@example.com",
30
30
  description='A Python package that provides a way to define private attributes in C++ implementation.',
@@ -1,6 +1,7 @@
1
1
  import private_attribute
2
2
  import unittest
3
3
 
4
+ # test whether the PrivateWrapProxy can find the original function if the decorator is a custom type
4
5
  class MyWrap:
5
6
  def __init__(self, func):
6
7
  self.func1 = func
@@ -19,6 +20,12 @@ class MyWrap:
19
20
  return func.__get__(instance, owner)(*args, **kwargs)
20
21
  return wrapper
21
22
 
23
+ # test whether the PrivateWrapProxy can find the original function if the decorator forgets to use functools.wrap
24
+ def ill_decorator(func):
25
+ def wrapper(*args, **kwargs):
26
+ return func(*args, **kwargs)
27
+ return wrapper
28
+
22
29
  class MyClass(private_attribute.PrivateAttrBase):
23
30
  __private_attrs__ = ["_secret1", "_secret2", "_secret3"]
24
31
  def __init__(self, secret1, secret2, secret3):
@@ -27,11 +34,12 @@ class MyClass(private_attribute.PrivateAttrBase):
27
34
  self._secret3 = secret3
28
35
 
29
36
  @private_attribute.PrivateWrapProxy(MyWrap)
30
- def get_secret(self):
37
+ def get_secret(self): # type: ignore
31
38
  return self._secret1
32
39
 
33
40
  @private_attribute.PrivateWrapProxy(get_secret.result.add, get_secret)
34
- def get_secret(self):
41
+ @private_attribute.PrivateWrapProxy(ill_decorator, get_secret)
42
+ def get_secret(self): # type: ignore
35
43
  return self._secret2
36
44
 
37
45
  @private_attribute.PrivateWrapProxy(get_secret.result.add, get_secret)