private-attribute-cpp 1.3.7__tar.gz → 1.3.9__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.3.7
3
+ Version: 1.3.9
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,6 +21,21 @@
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
25
+ #if PY_VERSION_HEX < 0x030D0000
26
+ static int
27
+ PyDict_ContainsString(PyObject *op, const char *key)
28
+ {
29
+ PyObject *key_obj = PyUnicode_FromString(key);
30
+ if (key_obj == NULL) {
31
+ return -1;
32
+ }
33
+ int res = PyDict_Contains(op, key_obj);
34
+ Py_DECREF(key_obj);
35
+ return res;
36
+ }
37
+ #endif
38
+
24
39
  static const auto module_running_time = std::chrono::system_clock::now();
25
40
 
26
41
  static std::string
@@ -128,7 +143,7 @@ namespace {
128
143
  };
129
144
  };
130
145
 
131
- namespace AllSlots {
146
+ namespace AllSlots {
132
147
  static getattrofunc original_getattro = nullptr;
133
148
  static setattrofunc original_setattro = nullptr;
134
149
  static destructor original_finalize = nullptr;
@@ -1758,20 +1773,156 @@ need_analyse_type(PyObject* type)
1758
1773
  return false;
1759
1774
  }
1760
1775
 
1761
- // python under 3.13 doesn't has PyDict_ContainsString, so we implement it ourselves
1762
- #if PY_VERSION_HEX < 0x030D0000
1763
- static int
1764
- PyDict_ContainsString(PyObject *op, const char *key)
1776
+ static void
1777
+ get_getattribute_and_getattr(PyTypeObject* cls, PyObject** getattribute, PyObject** getattr)
1765
1778
  {
1766
- PyObject *key_obj = PyUnicode_FromString(key);
1767
- if (key_obj == NULL) {
1768
- return -1;
1779
+ bool has_getattribute = false;
1780
+ bool has_getattr = false;
1781
+ if (PyDict_ContainsString(cls->tp_dict, "__getattribute__")) {
1782
+ *getattribute = PyDict_GetItemString(cls->tp_dict, "__getattribute__");
1783
+ has_getattribute = true;
1784
+ }
1785
+ if (PyDict_ContainsString(cls->tp_dict, "__getattr__")) {
1786
+ *getattr = PyDict_GetItemString(cls->tp_dict, "__getattr__");
1787
+ has_getattr = true;
1788
+ }
1789
+ if (has_getattribute && has_getattr) {
1790
+ return;
1791
+ }
1792
+ for (PyTypeObject* base = cls->tp_base; base != NULL && base != &PyBaseObject_Type; base = base->tp_base) {
1793
+ if (!has_getattribute && PyDict_ContainsString(base->tp_dict, "__getattribute__")) {
1794
+ *getattribute = PyDict_GetItemString(base->tp_dict, "__getattribute__");
1795
+ has_getattribute = true;
1796
+ }
1797
+ if (!has_getattr && PyDict_ContainsString(base->tp_dict, "__getattr__")) {
1798
+ *getattr = PyDict_GetItemString(base->tp_dict, "__getattr__");
1799
+ has_getattr = true;
1800
+ }
1801
+ if (has_getattribute && has_getattr) {
1802
+ return;
1803
+ }
1804
+ }
1805
+ }
1806
+
1807
+ static void
1808
+ get_setattr_and_delattr(PyTypeObject* cls, PyObject** setattr, PyObject** delattr)
1809
+ {
1810
+ bool has_setattr = false;
1811
+ bool has_delattr = false;
1812
+ if (PyDict_ContainsString(cls->tp_dict, "__setattr__")) {
1813
+ *setattr = PyDict_GetItemString(cls->tp_dict, "__setattr__");
1814
+ has_setattr = true;
1815
+ }
1816
+ if (PyDict_ContainsString(cls->tp_dict, "__delattr__")) {
1817
+ *delattr = PyDict_GetItemString(cls->tp_dict, "__delattr__");
1818
+ has_delattr = true;
1819
+ }
1820
+ if (has_setattr && has_delattr) {
1821
+ return;
1822
+ }
1823
+ for (PyTypeObject* base = cls->tp_base; base != NULL && base != &PyBaseObject_Type; base = base->tp_base) {
1824
+ if (!has_setattr && PyDict_ContainsString(base->tp_dict, "__setattr__")) {
1825
+ *setattr = PyDict_GetItemString(base->tp_dict, "__setattr__");
1826
+ has_setattr = true;
1827
+ }
1828
+ if (!has_delattr && PyDict_ContainsString(base->tp_dict, "__delattr__")) {
1829
+ *delattr = PyDict_GetItemString(base->tp_dict, "__delattr__");
1830
+ has_delattr = true;
1831
+ }
1832
+ if (has_setattr && has_delattr) {
1833
+ return;
1834
+ }
1835
+ }
1836
+ }
1837
+
1838
+ static void
1839
+ get_del(PyTypeObject* cls, PyObject** del)
1840
+ {
1841
+ if (PyDict_ContainsString(cls->tp_dict, "__del__")) {
1842
+ *del = PyDict_GetItemString(cls->tp_dict, "__del__");
1843
+ return;
1844
+ }
1845
+ for (PyTypeObject* base = cls->tp_base; base != NULL && base != &PyBaseObject_Type; base = base->tp_base) {
1846
+ if (PyDict_ContainsString(base->tp_dict, "__del__")) {
1847
+ *del = PyDict_GetItemString(base->tp_dict, "__del__");
1848
+ return;
1849
+ }
1850
+ }
1851
+ }
1852
+
1853
+ static PyObject*
1854
+ python_original_tp_getattro(PyObject* self, PyObject* name)
1855
+ {
1856
+ PyObject* getattriute = NULL;
1857
+ PyObject* getattr = NULL;
1858
+ get_getattribute_and_getattr((PyTypeObject*)self->ob_type, &getattriute, &getattr);
1859
+ PyObject* res = NULL;
1860
+ if (getattriute) {
1861
+ res = PyObject_CallFunctionObjArgs(getattriute, self, name, NULL);
1862
+ } else {
1863
+ res = PyObject_GenericGetAttr(self, name);
1864
+ }
1865
+ if (!res && getattr) {
1866
+ // check if the exception is AttributeError
1867
+ if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
1868
+ return NULL;
1869
+ }
1870
+ PyErr_Clear();
1871
+ res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL);
1769
1872
  }
1770
- int res = PyDict_Contains(op, key_obj);
1771
- Py_DECREF(key_obj);
1772
1873
  return res;
1773
1874
  }
1774
- #endif
1875
+
1876
+ static int
1877
+ python_original_tp_setattro(PyObject* self, PyObject* name, PyObject* value)
1878
+ {
1879
+ PyObject* setattr = NULL;
1880
+ PyObject* delattr = NULL;
1881
+ get_setattr_and_delattr((PyTypeObject*)self->ob_type, &setattr, &delattr);
1882
+ if (value && setattr) {
1883
+ PyObject* res = PyObject_CallFunctionObjArgs(setattr, self, name, value, NULL);
1884
+ if (!res) {
1885
+ return -1;
1886
+ }
1887
+ Py_DECREF(res);
1888
+ return 0;
1889
+ } else if (!value && delattr) {
1890
+ PyObject* res = PyObject_CallFunctionObjArgs(delattr, self, name, NULL);
1891
+ if (!res) {
1892
+ return -1;
1893
+ }
1894
+ Py_DECREF(res);
1895
+ return 0;
1896
+ }
1897
+ return PyObject_GenericSetAttr(self, name, value);
1898
+ }
1899
+
1900
+ static void
1901
+ python_original_tp_finalize(PyObject* self)
1902
+ {
1903
+ PyObject* del = NULL;
1904
+ get_del((PyTypeObject*)self->ob_type, &del);
1905
+ if (del) {
1906
+ PyObject *exc_type = NULL, *exc_value = NULL, *exc_tb = NULL;
1907
+ PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
1908
+ PyObject *result = PyObject_CallFunctionObjArgs(del, self, NULL);
1909
+ if (result == NULL) {
1910
+ // python < 3.13 use PyErr_WriteUnraisable, python >= 3.13 use PyErr_FormatUnraisable
1911
+ # if PY_VERSION_HEX >= 0x030D0000
1912
+ PyErr_FormatUnraisable("Exception ignored while "
1913
+ "calling deallocator %R", del);
1914
+ # else
1915
+ PyErr_WriteUnraisable(del);
1916
+ # endif
1917
+ }
1918
+ else {
1919
+ Py_DECREF(result);
1920
+ }
1921
+ if (exc_type != NULL) {
1922
+ PyErr_Restore(exc_type, exc_value, exc_tb);
1923
+ }
1924
+ }
1925
+ }
1775
1926
 
1776
1927
  static bool
1777
1928
  PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationData& data)
@@ -2013,12 +2164,16 @@ ensure_tp(PyTypeObject* type_instance)
2013
2164
  }
2014
2165
  type_instance->tp_getattro = PrivateAttr_tp_getattro;
2015
2166
  } else {
2016
- PyTypeObject* base = type_instance->tp_base;
2017
- uintptr_t base_id = (uintptr_t)(base);
2018
- if (::AllData::all_type_getattro.find(base_id) != ::AllData::all_type_getattro.end()) {
2019
- ::AllData::all_type_getattro[type_id] = ::AllData::all_type_getattro[base_id];
2020
- } else if (base && base->tp_getattro && base->tp_getattro != PrivateAttr_tp_getattro) {
2021
- ::AllData::all_type_getattro[type_id] = base->tp_getattro;
2167
+ if (PyDict_ContainsString(type_instance->tp_dict, "__getattribute__") || PyDict_ContainsString(type_instance->tp_dict, "__getattr__")) {
2168
+ ::AllData::all_type_getattro[type_id] = AllSlots::original_getattro;
2169
+ } else {
2170
+ PyTypeObject* base = type_instance->tp_base;
2171
+ uintptr_t base_id = (uintptr_t)(base);
2172
+ if (::AllData::all_type_getattro.find(base_id) != ::AllData::all_type_getattro.end()) {
2173
+ ::AllData::all_type_getattro[type_id] = ::AllData::all_type_getattro[base_id];
2174
+ } else if (base && base->tp_getattro && base->tp_getattro != PrivateAttr_tp_getattro) {
2175
+ ::AllData::all_type_getattro[type_id] = base->tp_getattro;
2176
+ }
2022
2177
  }
2023
2178
  }
2024
2179
  }
@@ -2031,12 +2186,16 @@ ensure_tp(PyTypeObject* type_instance)
2031
2186
  }
2032
2187
  type_instance->tp_setattro = PrivateAttr_tp_setattro;
2033
2188
  } else {
2034
- PyTypeObject* base = type_instance->tp_base;
2035
- uintptr_t base_id = (uintptr_t)(base);
2036
- if (::AllData::all_type_setattro.find(base_id) != ::AllData::all_type_setattro.end()) {
2037
- ::AllData::all_type_setattro[type_id] = ::AllData::all_type_setattro[base_id];
2038
- } else if (base && base->tp_setattro && base->tp_setattro != PrivateAttr_tp_setattro) {
2039
- ::AllData::all_type_setattro[type_id] = base->tp_setattro;
2189
+ if (PyDict_ContainsString(type_instance->tp_dict, "__setattr__") || PyDict_ContainsString(type_instance->tp_dict, "__delattr__")) {
2190
+ ::AllData::all_type_setattro[type_id] = AllSlots::original_setattro;
2191
+ } else {
2192
+ PyTypeObject* base = type_instance->tp_base;
2193
+ uintptr_t base_id = (uintptr_t)(base);
2194
+ if (::AllData::all_type_setattro.find(base_id) != ::AllData::all_type_setattro.end()) {
2195
+ ::AllData::all_type_setattro[type_id] = ::AllData::all_type_setattro[base_id];
2196
+ } else if (base && base->tp_setattro && base->tp_setattro != PrivateAttr_tp_setattro) {
2197
+ ::AllData::all_type_setattro[type_id] = base->tp_setattro;
2198
+ }
2040
2199
  }
2041
2200
  }
2042
2201
  }
@@ -2049,12 +2208,16 @@ ensure_tp(PyTypeObject* type_instance)
2049
2208
  }
2050
2209
  type_instance->tp_finalize = PrivateAttr_tp_finalize;
2051
2210
  } else {
2052
- PyTypeObject* base = type_instance->tp_base;
2053
- uintptr_t base_id = (uintptr_t)(base);
2054
- if (::AllData::all_type_finalize.find(base_id) != ::AllData::all_type_finalize.end()) {
2055
- ::AllData::all_type_finalize[type_id] = ::AllData::all_type_finalize[base_id];
2056
- } else if (base && base->tp_finalize && base->tp_finalize != PrivateAttr_tp_finalize) {
2057
- ::AllData::all_type_finalize[type_id] = base->tp_finalize;
2211
+ if (PyDict_ContainsString(type_instance->tp_dict, "__del__")) {
2212
+ ::AllData::all_type_finalize[type_id] = AllSlots::original_finalize;
2213
+ } else {
2214
+ PyTypeObject* base = type_instance->tp_base;
2215
+ uintptr_t base_id = (uintptr_t)(base);
2216
+ if (::AllData::all_type_finalize.find(base_id) != ::AllData::all_type_finalize.end()) {
2217
+ ::AllData::all_type_finalize[type_id] = ::AllData::all_type_finalize[base_id];
2218
+ } else if (base && base->tp_finalize && base->tp_finalize != PrivateAttr_tp_finalize) {
2219
+ ::AllData::all_type_finalize[type_id] = base->tp_finalize;
2220
+ }
2058
2221
  }
2059
2222
  }
2060
2223
  }
@@ -2110,6 +2273,15 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data)
2110
2273
  uintptr_t type_id = (uintptr_t)(type_instance);
2111
2274
 
2112
2275
  ensure_tp(type_instance);
2276
+ if (PyDict_ContainsString(type_instance->tp_dict, "__getattribute__") || PyDict_ContainsString(type_instance->tp_dict, "__getattr__")) {
2277
+ ::AllData::all_type_getattro[type_id] = AllSlots::original_getattro;
2278
+ }
2279
+ if (PyDict_ContainsString(type_instance->tp_dict, "__setattr__") || PyDict_ContainsString(type_instance->tp_dict, "__delattr__")) {
2280
+ ::AllData::all_type_setattro[type_id] = AllSlots::original_setattro;
2281
+ }
2282
+ if (PyDict_ContainsString(type_instance->tp_dict, "__del__")) {
2283
+ ::AllData::all_type_finalize[type_id] = AllSlots::original_finalize;
2284
+ }
2113
2285
 
2114
2286
  ::AllData::type_attr_dict[type_id] = {};
2115
2287
  ::AllData::all_type_attr_set[type_id] = data.private_attrs_set;
@@ -2266,48 +2438,9 @@ PrivateAttrType_getattr(PyObject* cls, PyObject* name)
2266
2438
  static int
2267
2439
  init_all_slots()
2268
2440
  {
2269
- PyObject* class_locals = PyDict_New();
2270
- if (!class_locals) {
2271
- return -1;
2272
- }
2273
- // set "__getattribute__", "__setattr__", "__delattr__", "__del__" to class_locals
2274
- if (PyDict_SetItemString(class_locals, "__getattribute__", Py_None) < 0) {
2275
- Py_DECREF(class_locals);
2276
- return -1;
2277
- }
2278
- if (PyDict_SetItemString(class_locals, "__setattr__", Py_None) < 0) {
2279
- Py_DECREF(class_locals);
2280
- return -1;
2281
- }
2282
- if (PyDict_SetItemString(class_locals, "__delattr__", Py_None) < 0) {
2283
- Py_DECREF(class_locals);
2284
- return -1;
2285
- }
2286
- if (PyDict_SetItemString(class_locals, "__del__", Py_None) < 0) {
2287
- Py_DECREF(class_locals);
2288
- return -1;
2289
- }
2290
- PyObject* class_name = PyUnicode_FromString("_TempClass");
2291
- if (!class_name) {
2292
- Py_DECREF(class_locals);
2293
- return -1;
2294
- }
2295
- PyObject* args = PyTuple_Pack(3, class_name, PyTuple_New(0), class_locals);
2296
- if (!args) {
2297
- Py_DECREF(class_name);
2298
- Py_DECREF(class_locals);
2299
- return -1;
2300
- }
2301
- PyObject* temp_class = PyType_Type.tp_new(&PyType_Type, args, NULL);
2302
- Py_DECREF(args);
2303
- if (!temp_class) {
2304
- return -1;
2305
- }
2306
- PyTypeObject* temp_type = (PyTypeObject*)temp_class;
2307
- AllSlots::original_getattro = temp_type->tp_getattro;
2308
- AllSlots::original_setattro = temp_type->tp_setattro;
2309
- AllSlots::original_finalize = temp_type->tp_finalize;
2310
- Py_DECREF(temp_class);
2441
+ AllSlots::original_getattro = python_original_tp_getattro;
2442
+ AllSlots::original_setattro = python_original_tp_setattro;
2443
+ AllSlots::original_finalize = python_original_tp_finalize;
2311
2444
  return 0;
2312
2445
  }
2313
2446
 
@@ -2462,7 +2595,11 @@ PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value)
2462
2595
  }
2463
2596
  Py_XDECREF(now_code);
2464
2597
  // if name in __getattribute__, __setattr__, __delattr__, __del__, just set to tp_dict
2465
- if (name_str == "__getattribute__" || name_str == "__getattr__" || name_str == "__setattr__" || name_str == "__delattr__" || name_str == "__del__") {
2598
+ if (strcmp(name_str.c_str(), "__getattribute__") == 0 ||
2599
+ strcmp(name_str.c_str(), "__getattr__") == 0 ||
2600
+ strcmp(name_str.c_str(), "__setattr__") == 0 ||
2601
+ strcmp(name_str.c_str(), "__delattr__") == 0 ||
2602
+ strcmp(name_str.c_str(), "__del__") == 0) {
2466
2603
  PyObject* tp_dict = ((PyTypeObject*)cls)->tp_dict;
2467
2604
  if (!tp_dict) {
2468
2605
  PyErr_SetString(PyExc_TypeError, "type has no tp_dict");
@@ -2470,6 +2607,7 @@ PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value)
2470
2607
  }
2471
2608
  if (!value) {
2472
2609
  if (PyDict_DelItem(tp_dict, name) < 0) {
2610
+ PyErr_Format(PyExc_AttributeError, "type object '%.100s' has no attribute '%U'", ((PyTypeObject*)cls)->tp_name, name);
2473
2611
  return -1;
2474
2612
  }
2475
2613
  type_change_all_slots((PyTypeObject*)cls, name_str.c_str());
@@ -2832,10 +2970,6 @@ ensure_metaclass_tp(PyObject* /*self*/, PyObject* metaclass)
2832
2970
  Py_RETURN_NONE;
2833
2971
  }
2834
2972
 
2835
- typedef struct PrivateModule {
2836
- PyObject_HEAD
2837
- }PrivateModule;
2838
-
2839
2973
  static PyObject*
2840
2974
  PrivateModule_get_PrivateWrapProxy(PyObject* /*self*/, void* /*closure*/)
2841
2975
  {
@@ -2962,7 +3096,7 @@ static PyMethodDef PrivateModule_methods[] = {
2962
3096
  static PyTypeObject PrivateModuleType = {
2963
3097
  PyVarObject_HEAD_INIT(NULL, 0)
2964
3098
  "private_attribute_module", //tp_name
2965
- sizeof(PrivateModule), //tp_basicsize
3099
+ PyModule_Type.tp_basicsize, //tp_basicsize
2966
3100
  0, //tp_itemsize
2967
3101
  0, //tp_dealloc
2968
3102
  0, //tp_print
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.3.7
3
+ Version: 1.3.9
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
@@ -19,7 +19,7 @@ readme = open('README.md').read()
19
19
 
20
20
  setup(
21
21
  name='private_attribute_cpp',
22
- version='1.3.7',
22
+ version='1.3.9',
23
23
  author="HuangHaoHua",
24
24
  author_email="13140752715@example.com",
25
25
  description='A Python package that provides a way to define private attributes in C++ implementation.',