private-attribute-cpp 2.0.3__tar.gz → 2.0.4__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-2.0.3/private_attribute_cpp.egg-info → private_attribute_cpp-2.0.4}/PKG-INFO +1 -1
  2. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/private_attribute.cpp +105 -94
  3. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
  4. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/setup.py +1 -1
  5. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/LICENSE +0 -0
  6. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/MANIFEST.in +0 -0
  7. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/README.md +0 -0
  8. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/picosha2.h +0 -0
  9. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/private_attribute.pyi +0 -0
  10. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
  11. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  12. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  13. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  14. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/setup.cfg +0 -0
  15. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/tests/test_class_private_attrs.py +0 -0
  16. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/tests/test_private_abc.py +0 -0
  17. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/tests/test_private_attrs.py +0 -0
  18. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/tests/test_private_func.py +0 -0
  19. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/tests/test_private_inheritance.py +0 -0
  20. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/tests/test_private_method.py +0 -0
  21. {private_attribute_cpp-2.0.3 → private_attribute_cpp-2.0.4}/tests/test_private_wrap.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.0.3
3
+ Version: 2.0.4
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
@@ -115,6 +115,56 @@ namespace std {
115
115
  };
116
116
  }
117
117
 
118
+ struct PyObjectStorage
119
+ {
120
+ PyObject* obj = NULL;
121
+
122
+ PyObjectStorage() noexcept = default;
123
+ PyObjectStorage(PyObject* obj) noexcept : obj(obj) {
124
+ Py_XINCREF(obj);
125
+ }
126
+ PyObjectStorage(const PyObjectStorage& other) noexcept : obj(other.obj) {
127
+ Py_XINCREF(obj);
128
+ }
129
+ PyObjectStorage(PyObjectStorage&& other) noexcept : obj(other.obj) {
130
+ other.obj = NULL;
131
+ }
132
+ PyObjectStorage& operator=(const PyObjectStorage& other) noexcept {
133
+ if (this == &other) {
134
+ return *this;
135
+ }
136
+ PyObject* new_obj = other.obj;
137
+ Py_XINCREF(new_obj);
138
+ Py_XDECREF(obj);
139
+ obj = new_obj;
140
+ return *this;
141
+ }
142
+ PyObjectStorage& operator=(PyObjectStorage&& other) noexcept {
143
+ if (this != &other) {
144
+ Py_XDECREF(obj);
145
+ obj = other.obj;
146
+ other.obj = NULL;
147
+ }
148
+ return *this;
149
+ }
150
+ PyObjectStorage& operator=(PyObject* new_obj) noexcept {
151
+ Py_XINCREF(new_obj);
152
+ Py_XDECREF(obj);
153
+ obj = new_obj;
154
+ return *this;
155
+ }
156
+ ~PyObjectStorage() noexcept {
157
+ Py_XDECREF(obj);
158
+ }
159
+
160
+ operator PyObject*() const noexcept {
161
+ return obj;
162
+ }
163
+ PyObject* get() const noexcept {
164
+ return obj;
165
+ }
166
+ };
167
+
118
168
  namespace {
119
169
  namespace AllData {
120
170
  static std::unordered_map<AllPyobjectAttrCacheKey, std::string> cache;
@@ -122,7 +172,7 @@ namespace {
122
172
  static std::unordered_map<uintptr_t, std::vector<AllPyobjectAttrCacheKey>> obj_attr_keys;
123
173
  static std::shared_mutex cache_mutex;
124
174
  namespace {
125
- static std::unordered_map<uintptr_t, std::unordered_map<std::string, PyObject*>> type_attr_dict;
175
+ static std::unordered_map<uintptr_t, std::unordered_map<std::string, PyObjectStorage>> type_attr_dict;
126
176
  };
127
177
  static std::unordered_map<uintptr_t, std::unordered_map<uintptr_t, PyCodeObject*>> type_allowed_code_map;
128
178
  static std::unordered_map<uintptr_t, std::shared_ptr<std::shared_mutex>> all_type_mutex;
@@ -130,7 +180,7 @@ namespace {
130
180
  static std::unordered_map<uintptr_t, std::unordered_set<TwoStringTuple>> all_type_attr_set;
131
181
  namespace {
132
182
  static std::unordered_map<uintptr_t, std::unordered_map<uintptr_t,
133
- std::unordered_map<std::string, PyObject*>>> all_object_attr, all_type_subclass_attr;
183
+ std::unordered_map<std::string, PyObjectStorage>>> all_object_attr, all_type_subclass_attr;
134
184
  };
135
185
  static std::unordered_map<uintptr_t, std::unordered_map<uintptr_t, std::shared_ptr<std::shared_mutex>>>
136
186
  all_object_mutex, all_type_subclass_mutex;
@@ -149,16 +199,12 @@ namespace {
149
199
 
150
200
  struct FinalObject
151
201
  {
152
- PyObject* result = NULL;
202
+ PyObjectStorage result;
153
203
  int status = 0;
154
- FinalObject(PyObject* result) noexcept
155
- : result(result) {
156
- Py_XINCREF(result);
157
- }
158
- FinalObject(int status) noexcept: status(status) {}
159
- ~FinalObject() noexcept {
160
- Py_XDECREF(result);
161
- }
204
+ FinalObject() noexcept = default;
205
+ FinalObject(PyObject* result) noexcept : result(result) {}
206
+ FinalObject(PyObjectStorage result) noexcept : result(std::move(result)) {}
207
+ FinalObject(int status) noexcept : status(status) {}
162
208
  };
163
209
 
164
210
  static TwoStringTuple get_string_hash_tuple2(const std::string& name) noexcept;
@@ -570,12 +616,8 @@ id_setattr(const std::string& attr_name, PyObject* obj, PyObject* typ, PyObject*
570
616
  }
571
617
 
572
618
  // second: set attribute on obj
573
- Py_INCREF(value);
574
619
  {
575
620
  std::unique_lock<std::shared_mutex> lock(*::AllData::all_object_mutex[final_id][obj_id]);
576
- if (::AllData::all_object_attr[final_id][obj_id].find(obj_private_name) != ::AllData::all_object_attr[final_id][obj_id].end()) {
577
- Py_XDECREF(::AllData::all_object_attr[final_id][obj_id][obj_private_name]);
578
- }
579
621
  ::AllData::all_object_attr[final_id][obj_id][obj_private_name] = value;
580
622
  }
581
623
  return 0;
@@ -621,11 +663,7 @@ type_setattr(PyObject* typ, const std::string& attr_name, PyObject* value) noexc
621
663
  }
622
664
  {
623
665
  std::unique_lock<std::shared_mutex> lock(*::AllData::all_type_mutex[typ_id]);
624
- if (::AllData::type_attr_dict[typ_id].find(final_key) != ::AllData::type_attr_dict[typ_id].end()) {
625
- Py_XDECREF(::AllData::type_attr_dict[typ_id][final_key]);
626
- }
627
666
  ::AllData::type_attr_dict[typ_id][final_key] = value;
628
- Py_INCREF(value);
629
667
  }
630
668
  return 0;
631
669
  } else {
@@ -644,11 +682,7 @@ type_setattr(PyObject* typ, const std::string& attr_name, PyObject* value) noexc
644
682
  }
645
683
  {
646
684
  std::unique_lock<std::shared_mutex> lock(*::AllData::all_type_subclass_mutex[final_id][typ_id]);
647
- if (::AllData::all_type_subclass_attr[final_id][typ_id].find(final_key) != ::AllData::all_type_subclass_attr[final_id][typ_id].end()) {
648
- Py_XDECREF(::AllData::all_type_subclass_attr[final_id][typ_id][final_key]);
649
- }
650
685
  ::AllData::all_type_subclass_attr[final_id][typ_id][final_key] = value;
651
- Py_INCREF(value);
652
686
  return 0;
653
687
  }
654
688
  }
@@ -721,9 +755,7 @@ id_delattr(const std::string& attr_name, PyObject* obj, PyObject* typ) noexcept
721
755
  }
722
756
  PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type_name, attr_name.c_str());
723
757
  }
724
- PyObject* delete_obj = ::AllData::all_object_attr[final_id][obj_id][obj_private_name];
725
758
  ::AllData::all_object_attr[final_id][obj_id].erase(obj_private_name);
726
- Py_XDECREF(delete_obj);
727
759
  }
728
760
  return 0;
729
761
  }
@@ -770,9 +802,7 @@ type_delattr(PyObject* typ, const std::string& attr_name) noexcept
770
802
  PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '%s'", type_name, attr_name.c_str());
771
803
  return -1;
772
804
  }
773
- PyObject* delete_obj = ::AllData::type_attr_dict[typ_id][final_key];
774
805
  ::AllData::type_attr_dict[typ_id].erase(final_key);
775
- Py_XDECREF(delete_obj);
776
806
  } else {
777
807
  if (::AllData::all_type_subclass_attr.find(final_id) == ::AllData::all_type_subclass_attr.end()) {
778
808
  ::AllData::all_type_subclass_attr[final_id] = {};
@@ -796,9 +826,7 @@ type_delattr(PyObject* typ, const std::string& attr_name) noexcept
796
826
  PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '%s'", type_name, attr_name.c_str());
797
827
  return -1;
798
828
  }
799
- PyObject* delete_obj = ::AllData::all_type_subclass_attr[final_id][typ_id][final_key];
800
829
  ::AllData::all_type_subclass_attr[final_id][typ_id].erase(final_key);
801
- Py_XDECREF(delete_obj);
802
830
  }
803
831
  return 0;
804
832
  }
@@ -1312,10 +1340,6 @@ PrivateAttr_tp_finalize(PyObject* self) noexcept
1312
1340
  if (::AllData::all_object_attr.find(typ_id) != ::AllData::all_object_attr.end()){
1313
1341
  auto& all_object_attr = ::AllData::all_object_attr[typ_id];
1314
1342
  if (all_object_attr.find(id_self) != all_object_attr.end()){
1315
- auto& all_object_attr_self = all_object_attr[id_self];
1316
- for (auto& attr : all_object_attr_self){
1317
- Py_XDECREF(attr.second);
1318
- }
1319
1343
  all_object_attr.erase(id_self);
1320
1344
  }
1321
1345
  }
@@ -1330,10 +1354,6 @@ PrivateAttr_tp_finalize(PyObject* self) noexcept
1330
1354
  if (::AllData::all_object_attr.find(parent_id) != ::AllData::all_object_attr.end()){
1331
1355
  auto& all_object_attr = ::AllData::all_object_attr[parent_id];
1332
1356
  if (all_object_attr.find(id_self) != all_object_attr.end()){
1333
- auto& all_object_attr_self = all_object_attr[id_self];
1334
- for (auto& attr : all_object_attr_self){
1335
- Py_XDECREF(attr.second);
1336
- }
1337
1357
  all_object_attr.erase(id_self);
1338
1358
  }
1339
1359
  }
@@ -1610,6 +1630,21 @@ get_now_code() noexcept
1610
1630
  return code;
1611
1631
  }
1612
1632
 
1633
+ static PyObject*
1634
+ try_get_attr_string(PyObject* obj, const char* name) noexcept
1635
+ {
1636
+ if (obj == NULL || name == NULL) {
1637
+ return NULL;
1638
+ }
1639
+ if (PyObject_HasAttrString(obj, name) <= 0) {
1640
+ if (PyErr_Occurred()) {
1641
+ PyErr_Clear();
1642
+ }
1643
+ return NULL;
1644
+ }
1645
+ return PyObject_GetAttrString(obj, name);
1646
+ }
1647
+
1613
1648
  static void
1614
1649
  analyse_all_code(PyObject* obj, std::unordered_map<uintptr_t, PyCodeObject*>& map, std::unordered_set<uintptr_t>& _seen) noexcept
1615
1650
  {
@@ -1621,88 +1656,83 @@ analyse_all_code(PyObject* obj, std::unordered_map<uintptr_t, PyCodeObject*>& ma
1621
1656
  if (PyObject_TypeCheck(obj, &PyCode_Type)) {
1622
1657
  Py_INCREF(obj);
1623
1658
  map[(uintptr_t)obj] = (PyCodeObject*)obj;
1624
- PyObject* co_contain = PyObject_GetAttrString(obj, "co_consts");
1659
+ PyObject* co_contain = try_get_attr_string(obj, "co_consts");
1625
1660
  if (co_contain && PySequence_Check(co_contain)) {
1626
1661
  Py_ssize_t len = PySequence_Length(co_contain);
1627
- for (Py_ssize_t i = 0; i < len; i++) {
1628
- PyObject* item = PySequence_GetItem(co_contain, i);
1629
- if (item) {
1630
- analyse_all_code(item, map, _seen);
1631
- } else {
1632
- PyErr_Clear();
1662
+ if (len >= 0) {
1663
+ for (Py_ssize_t i = 0; i < len; i++) {
1664
+ PyObject* item = PySequence_GetItem(co_contain, i);
1665
+ if (item) {
1666
+ analyse_all_code(item, map, _seen);
1667
+ Py_DECREF(item);
1668
+ }
1633
1669
  }
1634
1670
  }
1635
1671
  }
1672
+ Py_XDECREF(co_contain);
1636
1673
  return;
1637
1674
  }
1638
1675
  if (PyObject_TypeCheck(obj, &PrivateWrapType)) {
1639
1676
  PyObject* func_list = ((PrivateWrapObject*)obj)->func_list;
1640
1677
  if (func_list && PySequence_Check(func_list)) {
1641
1678
  Py_ssize_t len = PySequence_Length(func_list);
1642
- for (Py_ssize_t i = 0; i < len; i++) {
1643
- PyObject* func = PySequence_GetItem(func_list, i);
1644
- if (func) {
1645
- analyse_all_code(func, map, _seen);
1646
- } else {
1647
- PyErr_Clear();
1679
+ if (len >= 0) {
1680
+ for (Py_ssize_t i = 0; i < len; i++) {
1681
+ PyObject* func = PySequence_GetItem(func_list, i);
1682
+ if (func) {
1683
+ analyse_all_code(func, map, _seen);
1684
+ Py_DECREF(func);
1685
+ }
1648
1686
  }
1649
1687
  }
1650
1688
  }
1651
1689
  return;
1652
1690
  }
1653
1691
  if (PyObject_TypeCheck(obj, &PyProperty_Type)) {
1654
- PyObject* fget = PyObject_GetAttrString(obj, "fget");
1692
+ PyObject* fget = try_get_attr_string(obj, "fget");
1655
1693
  if (fget) {
1656
1694
  analyse_all_code(fget, map, _seen);
1657
- } else {
1658
- PyErr_Clear();
1695
+ Py_DECREF(fget);
1659
1696
  }
1660
- PyObject* fset = PyObject_GetAttrString(obj, "fset");
1697
+ PyObject* fset = try_get_attr_string(obj, "fset");
1661
1698
  if (fset) {
1662
1699
  analyse_all_code(fset, map, _seen);
1700
+ Py_DECREF(fset);
1663
1701
  }
1664
- else {
1665
- PyErr_Clear();
1666
- }
1667
- PyObject* fdel = PyObject_GetAttrString(obj, "fdel");
1702
+ PyObject* fdel = try_get_attr_string(obj, "fdel");
1668
1703
  if (fdel) {
1669
1704
  analyse_all_code(fdel, map, _seen);
1670
- } else {
1671
- PyErr_Clear();
1705
+ Py_DECREF(fdel);
1672
1706
  }
1673
1707
  return;
1674
1708
  }
1675
1709
  if (PyObject_TypeCheck(obj, &PyClassMethod_Type) || PyObject_TypeCheck(obj, &PyStaticMethod_Type)) {
1676
- PyObject* func = PyObject_GetAttrString(obj, "__func__");
1710
+ PyObject* func = try_get_attr_string(obj, "__func__");
1677
1711
  if (func) {
1678
1712
  analyse_all_code(func, map, _seen);
1679
- } else {
1680
- PyErr_Clear();
1713
+ Py_DECREF(func);
1681
1714
  }
1682
1715
  return;
1683
1716
  }
1684
- PyObject* wrap = PyObject_GetAttrString(obj, "__wrapped__");
1717
+ PyObject* wrap = try_get_attr_string(obj, "__wrapped__");
1685
1718
  if (wrap) {
1686
1719
  if (wrap == obj) {
1687
- PyObject* code = PyObject_GetAttrString(obj, "__code__");
1720
+ PyObject* code = try_get_attr_string(obj, "__code__");
1688
1721
  if (code) {
1689
1722
  analyse_all_code(code, map, _seen);
1690
- } else {
1691
- PyErr_Clear();
1723
+ Py_DECREF(code);
1692
1724
  }
1725
+ Py_DECREF(wrap);
1693
1726
  return;
1694
1727
  }
1695
1728
  analyse_all_code(wrap, map, _seen);
1729
+ Py_DECREF(wrap);
1696
1730
  return;
1697
1731
  }
1698
- else {
1699
- PyErr_Clear();
1700
- }
1701
- PyObject* code = PyObject_GetAttrString(obj, "__code__");
1732
+ PyObject* code = try_get_attr_string(obj, "__code__");
1702
1733
  if (code) {
1703
1734
  analyse_all_code(code, map, _seen);
1704
- } else {
1705
- PyErr_Clear();
1735
+ Py_DECREF(code);
1706
1736
  }
1707
1737
  }
1708
1738
 
@@ -1724,8 +1754,8 @@ struct PrivateAttrCreationData
1724
1754
  std::unordered_set<TwoStringTuple> private_attrs_set;
1725
1755
  std::unordered_set<std::string> private_attrs_vector_string;
1726
1756
  std::vector<uintptr_t> all_need_analyse_base;
1727
- std::unordered_map<std::string, PyObject*> need_remove_itself;
1728
- std::unordered_map<uintptr_t, std::unordered_map<std::string, PyObject*>> need_remove_subclass;
1757
+ std::unordered_map<std::string, PyObjectStorage> need_remove_itself;
1758
+ std::unordered_map<uintptr_t, std::unordered_map<std::string, PyObjectStorage>> need_remove_subclass;
1729
1759
  PyObject* private_func = nullptr;
1730
1760
  PyObject* base_kwds = nullptr;
1731
1761
  PyObject* name = nullptr;
@@ -1766,16 +1796,7 @@ struct PrivateAttrCreationData
1766
1796
  base_kwds = nullptr;
1767
1797
  }
1768
1798
 
1769
- for (auto& pair : need_remove_itself) {
1770
- Py_XDECREF(pair.second);
1771
- }
1772
1799
  need_remove_itself.clear();
1773
-
1774
- for (auto& outer_pair : need_remove_subclass) {
1775
- for (auto& inner_pair : outer_pair.second) {
1776
- Py_XDECREF(inner_pair.second);
1777
- }
1778
- }
1779
1800
  need_remove_subclass.clear();
1780
1801
  cleared = true;
1781
1802
  }
@@ -2216,7 +2237,6 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2216
2237
  } else {
2217
2238
  final_key = default_random_string(type_id, key);
2218
2239
  }
2219
- Py_INCREF(value);
2220
2240
  ::AllData::type_attr_dict[type_id][final_key] = value;
2221
2241
  }
2222
2242
 
@@ -2244,7 +2264,6 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2244
2264
  } else {
2245
2265
  final_key = default_random_string(type_id, key);
2246
2266
  }
2247
- Py_INCREF(value);
2248
2267
  ::AllData::all_type_subclass_attr[i][type_id][final_key] = value;
2249
2268
  }
2250
2269
  }
@@ -2522,10 +2541,6 @@ PrivateAttrType_finalize(PyObject* cls) noexcept
2522
2541
  ::AllData::type_need_call.erase(typ_id);
2523
2542
  }
2524
2543
  if (::AllData::type_attr_dict.find(typ_id) != ::AllData::type_attr_dict.end()) {
2525
- auto& private_attrs = ::AllData::type_attr_dict[typ_id];
2526
- for (auto& attr : private_attrs) {
2527
- Py_XDECREF(attr.second);
2528
- }
2529
2544
  ::AllData::type_attr_dict.erase(typ_id);
2530
2545
  }
2531
2546
  if (::AllData::all_type_subclass_attr.find(typ_id) != ::AllData::all_type_subclass_attr.end()) {
@@ -2542,10 +2557,6 @@ PrivateAttrType_finalize(PyObject* cls) noexcept
2542
2557
  for (auto& parent_id : parent_ids) {
2543
2558
  if (::AllData::all_type_subclass_attr.find(parent_id) != ::AllData::all_type_subclass_attr.end()) {
2544
2559
  if (::AllData::all_type_subclass_attr[parent_id].find(typ_id) != ::AllData::all_type_subclass_attr[parent_id].end()) {
2545
- auto& private_attrs = ::AllData::all_type_subclass_attr[parent_id][typ_id];
2546
- for (auto& attr : private_attrs) {
2547
- Py_XDECREF(attr.second);
2548
- }
2549
2560
  ::AllData::all_type_subclass_attr[parent_id].erase(typ_id);
2550
2561
  }
2551
2562
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.0.3
3
+ Version: 2.0.4
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
@@ -18,7 +18,7 @@ readme = open('README.md').read()
18
18
 
19
19
  setup(
20
20
  name='private_attribute_cpp',
21
- version='2.0.3',
21
+ version='2.0.4',
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.',