private-attribute-cpp 1.3.6__tar.gz → 1.3.8__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.
- {private_attribute_cpp-1.3.6/private_attribute_cpp.egg-info → private_attribute_cpp-1.3.8}/PKG-INFO +1 -1
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/private_attribute.cpp +438 -47
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/setup.py +1 -1
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/LICENSE +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/MANIFEST.in +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/README.md +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/picosha2.h +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/private_attribute.pyi +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/private_attribute_cpp.egg-info/top_level.txt +0 -0
- {private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8}/setup.cfg +0 -0
{private_attribute_cpp-1.3.6/private_attribute_cpp.egg-info → private_attribute_cpp-1.3.8}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: private_attribute_cpp
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.8
|
|
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,6 +143,12 @@ namespace {
|
|
|
128
143
|
};
|
|
129
144
|
};
|
|
130
145
|
|
|
146
|
+
namespace AllSlots {
|
|
147
|
+
static getattrofunc original_getattro = nullptr;
|
|
148
|
+
static setattrofunc original_setattro = nullptr;
|
|
149
|
+
static destructor original_finalize = nullptr;
|
|
150
|
+
}
|
|
151
|
+
|
|
131
152
|
struct FinalObject
|
|
132
153
|
{
|
|
133
154
|
PyObject* result = NULL;
|
|
@@ -1191,6 +1212,8 @@ typedef struct {
|
|
|
1191
1212
|
static void PrivateAttr_object_init_private_dict(uintptr_t obj_id, uintptr_t type_id);
|
|
1192
1213
|
static void ensure_tp(PyTypeObject* type_instance);
|
|
1193
1214
|
static void ensure_subclass_tp(PyTypeObject* type_instance);
|
|
1215
|
+
static int PrivateAttr_tp_setattro(PyObject* self, PyObject* name, PyObject* value);
|
|
1216
|
+
static void PrivateAttr_tp_finalize(PyObject* self);
|
|
1194
1217
|
|
|
1195
1218
|
static PyObject*
|
|
1196
1219
|
PrivateAttr_tp_getattro(PyObject* self, PyObject* name)
|
|
@@ -1212,8 +1235,11 @@ PrivateAttr_tp_getattro(PyObject* self, PyObject* name)
|
|
|
1212
1235
|
}
|
|
1213
1236
|
Py_XDECREF(code);
|
|
1214
1237
|
if (::AllData::all_type_getattro.find(type_id) != ::AllData::all_type_getattro.end()){
|
|
1215
|
-
|
|
1216
|
-
|
|
1238
|
+
if (::AllData::all_type_getattro[type_id]) {
|
|
1239
|
+
PyObject* result = ::AllData::all_type_getattro[type_id](self, name);
|
|
1240
|
+
ensure_tp(typ);
|
|
1241
|
+
return result;
|
|
1242
|
+
}
|
|
1217
1243
|
}
|
|
1218
1244
|
return PyObject_GenericGetAttr(self, name);
|
|
1219
1245
|
}
|
|
@@ -1245,6 +1271,7 @@ PrivateAttr_tp_setattro(PyObject* self, PyObject* name, PyObject* value)
|
|
|
1245
1271
|
Py_XDECREF(code);
|
|
1246
1272
|
if (::AllData::all_type_setattro.find(typ_id) != ::AllData::all_type_setattro.end()){
|
|
1247
1273
|
int result = ::AllData::all_type_setattro[typ_id](self, name, value);
|
|
1274
|
+
ensure_tp(typ);
|
|
1248
1275
|
return result;
|
|
1249
1276
|
}
|
|
1250
1277
|
return PyObject_GenericSetAttr(self, name, value);
|
|
@@ -1258,7 +1285,10 @@ PrivateAttr_tp_finalize(PyObject* self)
|
|
|
1258
1285
|
uintptr_t typ_id = (uintptr_t)typ;
|
|
1259
1286
|
Py_ssize_t original_ref = Py_REFCNT(self);
|
|
1260
1287
|
if (::AllData::all_type_finalize.find(typ_id) != ::AllData::all_type_finalize.end()){
|
|
1261
|
-
::AllData::all_type_finalize[typ_id]
|
|
1288
|
+
if (::AllData::all_type_finalize[typ_id]) {
|
|
1289
|
+
::AllData::all_type_finalize[typ_id](self);
|
|
1290
|
+
ensure_tp(typ);
|
|
1291
|
+
}
|
|
1262
1292
|
}
|
|
1263
1293
|
if (original_ref != Py_REFCNT(self)) {
|
|
1264
1294
|
return;
|
|
@@ -1743,6 +1773,157 @@ need_analyse_type(PyObject* type)
|
|
|
1743
1773
|
return false;
|
|
1744
1774
|
}
|
|
1745
1775
|
|
|
1776
|
+
static void
|
|
1777
|
+
get_getattribute_and_getattr(PyTypeObject* cls, PyObject** getattribute, PyObject** getattr)
|
|
1778
|
+
{
|
|
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);
|
|
1872
|
+
}
|
|
1873
|
+
return res;
|
|
1874
|
+
}
|
|
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
|
+
}
|
|
1926
|
+
|
|
1746
1927
|
static bool
|
|
1747
1928
|
PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationData& data)
|
|
1748
1929
|
{
|
|
@@ -1809,7 +1990,7 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
|
|
|
1809
1990
|
}
|
|
1810
1991
|
|
|
1811
1992
|
if (!PyUnicode_Check(attr)) {
|
|
1812
|
-
|
|
1993
|
+
PyErr_Format(PyExc_TypeError, "all items in '__private_attrs__' must be 'str', not '%.200s'", Py_TYPE(attr)->tp_name);
|
|
1813
1994
|
return false;
|
|
1814
1995
|
}
|
|
1815
1996
|
|
|
@@ -1821,7 +2002,7 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
|
|
|
1821
2002
|
std::string attr_str = real_class_name(attr_cstr, data.class_name);
|
|
1822
2003
|
|
|
1823
2004
|
for (const char** p = invalid_name; *p != NULL; p++) {
|
|
1824
|
-
if (attr_str
|
|
2005
|
+
if (strcmp(attr_str.c_str(), *p) == 0) {
|
|
1825
2006
|
std::string error_msg = "invalid attribute name: '" + std::string(*p) + "'";
|
|
1826
2007
|
PyErr_SetString(PyExc_TypeError, error_msg.c_str());
|
|
1827
2008
|
return false;
|
|
@@ -1842,10 +2023,10 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
|
|
|
1842
2023
|
return false;
|
|
1843
2024
|
}
|
|
1844
2025
|
|
|
1845
|
-
|
|
1846
|
-
bool has_slots = (all_slots != NULL);
|
|
2026
|
+
int has_slots = PyDict_ContainsString(data.attrs_copy, "__slots__");
|
|
1847
2027
|
|
|
1848
2028
|
if (has_slots) {
|
|
2029
|
+
PyObject* all_slots = PyDict_GetItemString(data.attrs_copy, "__slots__");
|
|
1849
2030
|
PyObject* slot_seq = PySequence_Fast(all_slots, "__slots__ must be a sequence");
|
|
1850
2031
|
if (!slot_seq) {
|
|
1851
2032
|
return false;
|
|
@@ -1866,8 +2047,6 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
|
|
|
1866
2047
|
}
|
|
1867
2048
|
}
|
|
1868
2049
|
Py_DECREF(slot_seq);
|
|
1869
|
-
} else {
|
|
1870
|
-
PyErr_Clear();
|
|
1871
2050
|
}
|
|
1872
2051
|
|
|
1873
2052
|
Py_ssize_t bases_len = PyTuple_GET_SIZE(data.bases);
|
|
@@ -1927,16 +2106,16 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
|
|
|
1927
2106
|
|
|
1928
2107
|
// get "private_func" from kwds
|
|
1929
2108
|
if (kwds && PyDict_Check(kwds)) {
|
|
1930
|
-
|
|
1931
|
-
if (
|
|
2109
|
+
bool has_private_func = PyDict_ContainsString(kwds, "private_func");
|
|
2110
|
+
if (has_private_func) {
|
|
2111
|
+
data.private_func = PyDict_GetItemString(kwds, "private_func");
|
|
1932
2112
|
Py_INCREF(data.private_func);
|
|
1933
2113
|
}
|
|
1934
2114
|
data.base_kwds = PyDict_Copy(kwds);
|
|
1935
2115
|
if (!data.base_kwds) {
|
|
1936
2116
|
return false;
|
|
1937
2117
|
}
|
|
1938
|
-
PyDict_DelItemString(data.base_kwds, "private_func");
|
|
1939
|
-
PyErr_Clear();
|
|
2118
|
+
if (has_private_func) PyDict_DelItemString(data.base_kwds, "private_func");
|
|
1940
2119
|
}
|
|
1941
2120
|
|
|
1942
2121
|
return true;
|
|
@@ -1968,49 +2147,77 @@ PrivateAttrType_create(PyTypeObject* type, PrivateAttrCreationData& data)
|
|
|
1968
2147
|
return new_type;
|
|
1969
2148
|
}
|
|
1970
2149
|
|
|
2150
|
+
static getattrofunc get_need_tp_getattro(PyTypeObject* cls);
|
|
2151
|
+
static setattrofunc get_need_tp_setattro(PyTypeObject* cls);
|
|
2152
|
+
static destructor get_need_tp_finalize(PyTypeObject* cls);
|
|
2153
|
+
|
|
1971
2154
|
static void
|
|
1972
2155
|
ensure_tp(PyTypeObject* type_instance)
|
|
1973
2156
|
{
|
|
1974
2157
|
uintptr_t type_id = (uintptr_t)(type_instance);
|
|
1975
|
-
|
|
2158
|
+
{
|
|
1976
2159
|
if (type_instance->tp_getattro != PrivateAttr_tp_getattro) {
|
|
1977
|
-
|
|
2160
|
+
if (!type_instance->tp_getattro) {
|
|
2161
|
+
::AllData::all_type_getattro[type_id] = get_need_tp_getattro(type_instance);
|
|
2162
|
+
} else {
|
|
2163
|
+
::AllData::all_type_getattro[type_id] = type_instance->tp_getattro;
|
|
2164
|
+
}
|
|
1978
2165
|
type_instance->tp_getattro = PrivateAttr_tp_getattro;
|
|
1979
2166
|
} else {
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
::AllData::all_type_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
|
+
}
|
|
1986
2177
|
}
|
|
1987
2178
|
}
|
|
1988
2179
|
}
|
|
1989
|
-
|
|
2180
|
+
{
|
|
1990
2181
|
if (type_instance->tp_setattro != PrivateAttr_tp_setattro) {
|
|
1991
|
-
|
|
2182
|
+
if (!type_instance->tp_setattro) {
|
|
2183
|
+
::AllData::all_type_setattro[type_id] = get_need_tp_setattro(type_instance);
|
|
2184
|
+
} else {
|
|
2185
|
+
::AllData::all_type_setattro[type_id] = type_instance->tp_setattro;
|
|
2186
|
+
}
|
|
1992
2187
|
type_instance->tp_setattro = PrivateAttr_tp_setattro;
|
|
1993
2188
|
} else {
|
|
1994
|
-
|
|
1995
|
-
|
|
1996
|
-
|
|
1997
|
-
|
|
1998
|
-
|
|
1999
|
-
::AllData::all_type_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
|
+
}
|
|
2000
2199
|
}
|
|
2001
2200
|
}
|
|
2002
2201
|
}
|
|
2003
|
-
|
|
2202
|
+
{
|
|
2004
2203
|
if (type_instance->tp_finalize != PrivateAttr_tp_finalize) {
|
|
2005
|
-
|
|
2204
|
+
if (!type_instance->tp_finalize) {
|
|
2205
|
+
::AllData::all_type_finalize[type_id] = get_need_tp_finalize(type_instance);
|
|
2206
|
+
} else {
|
|
2207
|
+
::AllData::all_type_finalize[type_id] = type_instance->tp_finalize;
|
|
2208
|
+
}
|
|
2006
2209
|
type_instance->tp_finalize = PrivateAttr_tp_finalize;
|
|
2007
2210
|
} else {
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
::AllData::all_type_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
|
+
}
|
|
2014
2221
|
}
|
|
2015
2222
|
}
|
|
2016
2223
|
}
|
|
@@ -2022,23 +2229,37 @@ ensure_subclass_tp(PyTypeObject* type_instance)
|
|
|
2022
2229
|
// type.__subclasses__
|
|
2023
2230
|
PyObject* type_subclasses = (PyObject*)type_instance->tp_subclasses;
|
|
2024
2231
|
if (!type_subclasses) {
|
|
2025
|
-
PyErr_Clear();
|
|
2026
2232
|
return;
|
|
2027
2233
|
}
|
|
2028
|
-
if (!
|
|
2029
|
-
Py_DECREF(type_subclasses);
|
|
2234
|
+
if (!PyDict_Check(type_subclasses)) {
|
|
2030
2235
|
return;
|
|
2031
2236
|
}
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2237
|
+
// check all values in the dict. It should be a weakref to a type. If not, continue.
|
|
2238
|
+
PyObject* key, *value;
|
|
2239
|
+
Py_ssize_t pos = 0;
|
|
2240
|
+
while (PyDict_Next(type_subclasses, &pos, &key, &value)) {
|
|
2241
|
+
if (!value || !PyWeakref_CheckRef(value)) {
|
|
2242
|
+
continue;
|
|
2243
|
+
}
|
|
2244
|
+
// python<3.13 use PyWeakref_GetObject, python>=3.13 use PyWeakref_GetRef
|
|
2245
|
+
#if PY_VERSION_HEX < 0x030D0000
|
|
2246
|
+
PyObject* subclass = PyWeakref_GetObject(value);
|
|
2035
2247
|
if (!subclass || !PyType_Check(subclass)) {
|
|
2036
2248
|
continue;
|
|
2037
2249
|
}
|
|
2038
2250
|
ensure_tp((PyTypeObject*)subclass);
|
|
2039
|
-
|
|
2251
|
+
#else
|
|
2252
|
+
PyObject* subclass;
|
|
2253
|
+
if (PyWeakref_GetRef(value, (PyObject**)&subclass) != 0) {
|
|
2254
|
+
continue;
|
|
2255
|
+
}
|
|
2256
|
+
if (!subclass || !PyType_Check(subclass)) {
|
|
2257
|
+
continue;
|
|
2258
|
+
}
|
|
2259
|
+
ensure_tp((PyTypeObject*)subclass);
|
|
2260
|
+
Py_XDECREF(subclass);
|
|
2261
|
+
#endif
|
|
2040
2262
|
}
|
|
2041
|
-
Py_DECREF(type_subclasses);
|
|
2042
2263
|
}
|
|
2043
2264
|
|
|
2044
2265
|
static bool
|
|
@@ -2052,6 +2273,15 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data)
|
|
|
2052
2273
|
uintptr_t type_id = (uintptr_t)(type_instance);
|
|
2053
2274
|
|
|
2054
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
|
+
}
|
|
2055
2285
|
|
|
2056
2286
|
::AllData::type_attr_dict[type_id] = {};
|
|
2057
2287
|
::AllData::all_type_attr_set[type_id] = data.private_attrs_set;
|
|
@@ -2205,6 +2435,139 @@ PrivateAttrType_getattr(PyObject* cls, PyObject* name)
|
|
|
2205
2435
|
return result;
|
|
2206
2436
|
}
|
|
2207
2437
|
|
|
2438
|
+
static int
|
|
2439
|
+
init_all_slots()
|
|
2440
|
+
{
|
|
2441
|
+
AllSlots::original_getattro = python_original_tp_getattro;
|
|
2442
|
+
AllSlots::original_setattro = python_original_tp_setattro;
|
|
2443
|
+
AllSlots::original_finalize = python_original_tp_finalize;
|
|
2444
|
+
return 0;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
static getattrofunc
|
|
2448
|
+
get_need_tp_getattro(PyTypeObject* cls)
|
|
2449
|
+
{
|
|
2450
|
+
if (PyDict_ContainsString(cls->tp_dict, "__getattribute__") || PyDict_ContainsString(cls->tp_dict, "__getattr__")) {
|
|
2451
|
+
return AllSlots::original_getattro;
|
|
2452
|
+
}
|
|
2453
|
+
PyTypeObject* base = cls->tp_base;
|
|
2454
|
+
while (base) {
|
|
2455
|
+
if (base->tp_getattro != PrivateAttr_tp_getattro) {
|
|
2456
|
+
return base->tp_getattro;
|
|
2457
|
+
} else if (::AllData::all_type_getattro.find((uintptr_t)base) != ::AllData::all_type_getattro.end()) {
|
|
2458
|
+
if (::AllData::all_type_getattro[(uintptr_t)base]) {
|
|
2459
|
+
return ::AllData::all_type_getattro[(uintptr_t)base];
|
|
2460
|
+
}
|
|
2461
|
+
base = base->tp_base;
|
|
2462
|
+
} else {
|
|
2463
|
+
base = base->tp_base;
|
|
2464
|
+
}
|
|
2465
|
+
}
|
|
2466
|
+
return NULL;
|
|
2467
|
+
}
|
|
2468
|
+
|
|
2469
|
+
static setattrofunc
|
|
2470
|
+
get_need_tp_setattro(PyTypeObject* cls)
|
|
2471
|
+
{
|
|
2472
|
+
if (PyDict_ContainsString(cls->tp_dict, "__setattr__") || PyDict_ContainsString(cls->tp_dict, "__delattr__")) {
|
|
2473
|
+
return AllSlots::original_setattro;
|
|
2474
|
+
}
|
|
2475
|
+
PyTypeObject* base = cls->tp_base;
|
|
2476
|
+
while (base) {
|
|
2477
|
+
if (base->tp_setattro != PrivateAttr_tp_setattro) {
|
|
2478
|
+
return base->tp_setattro;
|
|
2479
|
+
} else if (::AllData::all_type_setattro.find((uintptr_t)base) != ::AllData::all_type_setattro.end()) {
|
|
2480
|
+
if (::AllData::all_type_setattro[(uintptr_t)base]) {
|
|
2481
|
+
return ::AllData::all_type_setattro[(uintptr_t)base];
|
|
2482
|
+
}
|
|
2483
|
+
base = base->tp_base;
|
|
2484
|
+
} else {
|
|
2485
|
+
base = base->tp_base;
|
|
2486
|
+
}
|
|
2487
|
+
}
|
|
2488
|
+
return NULL;
|
|
2489
|
+
}
|
|
2490
|
+
|
|
2491
|
+
static destructor
|
|
2492
|
+
get_need_tp_finalize(PyTypeObject* cls)
|
|
2493
|
+
{
|
|
2494
|
+
if (PyDict_ContainsString(cls->tp_dict, "__del__")) {
|
|
2495
|
+
return AllSlots::original_finalize;
|
|
2496
|
+
}
|
|
2497
|
+
PyTypeObject* base = cls->tp_base;
|
|
2498
|
+
while (base) {
|
|
2499
|
+
if (base->tp_finalize != PrivateAttr_tp_finalize) {
|
|
2500
|
+
return base->tp_finalize;
|
|
2501
|
+
} else if (::AllData::all_type_finalize.find((uintptr_t)base) != ::AllData::all_type_finalize.end()) {
|
|
2502
|
+
if (::AllData::all_type_finalize[(uintptr_t)base]) {
|
|
2503
|
+
return ::AllData::all_type_finalize[(uintptr_t)base];
|
|
2504
|
+
}
|
|
2505
|
+
base = base->tp_base;
|
|
2506
|
+
} else {
|
|
2507
|
+
base = base->tp_base;
|
|
2508
|
+
}
|
|
2509
|
+
}
|
|
2510
|
+
return NULL;
|
|
2511
|
+
}
|
|
2512
|
+
|
|
2513
|
+
static void
|
|
2514
|
+
type_change_all_slots(PyTypeObject* cls, const char* name)
|
|
2515
|
+
{
|
|
2516
|
+
if (strcmp(name, "__getattribute__") == 0 || strcmp(name, "__getattr__") == 0) {
|
|
2517
|
+
cls->tp_getattro = PrivateAttr_tp_getattro;
|
|
2518
|
+
::AllData::all_type_getattro[(uintptr_t)cls] = get_need_tp_getattro(cls);
|
|
2519
|
+
} else if (strcmp(name, "__setattr__") == 0 || strcmp(name, "__delattr__") == 0) {
|
|
2520
|
+
cls->tp_setattro = PrivateAttr_tp_setattro;
|
|
2521
|
+
::AllData::all_type_setattro[(uintptr_t)cls] = get_need_tp_setattro(cls);
|
|
2522
|
+
} else if (strcmp(name, "__del__") == 0) {
|
|
2523
|
+
cls->tp_finalize = PrivateAttr_tp_finalize;
|
|
2524
|
+
::AllData::all_type_finalize[(uintptr_t)cls] = get_need_tp_finalize(cls);
|
|
2525
|
+
}
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
static void
|
|
2529
|
+
subtype_change_all_slots(PyTypeObject* cls, const char* name)
|
|
2530
|
+
{
|
|
2531
|
+
// tp_subclasses: {id(type): weakref.ref(type)}
|
|
2532
|
+
PyObject* tp_subclasses = (PyObject*)cls->tp_subclasses;
|
|
2533
|
+
if (!tp_subclasses) {
|
|
2534
|
+
return;
|
|
2535
|
+
}
|
|
2536
|
+
if (!PyDict_Check(tp_subclasses)) {
|
|
2537
|
+
return;
|
|
2538
|
+
}
|
|
2539
|
+
PyObject* key;
|
|
2540
|
+
PyObject* value;
|
|
2541
|
+
Py_ssize_t pos = 0;
|
|
2542
|
+
while (PyDict_Next(tp_subclasses, &pos, &key, &value)) {
|
|
2543
|
+
if (!PyWeakref_Check(value)) {
|
|
2544
|
+
continue;
|
|
2545
|
+
}
|
|
2546
|
+
#if PY_VERSION_HEX < 0x030D0000
|
|
2547
|
+
PyObject* obj = PyWeakref_GET_OBJECT(value);
|
|
2548
|
+
if (!obj) {
|
|
2549
|
+
continue;
|
|
2550
|
+
}
|
|
2551
|
+
#else
|
|
2552
|
+
PyObject* obj;
|
|
2553
|
+
if (PyWeakref_GetRef(value, &obj) != 0) {
|
|
2554
|
+
continue;
|
|
2555
|
+
}
|
|
2556
|
+
if (!obj) {
|
|
2557
|
+
continue;
|
|
2558
|
+
}
|
|
2559
|
+
#endif
|
|
2560
|
+
if (!PyType_Check(obj)) {
|
|
2561
|
+
continue;
|
|
2562
|
+
}
|
|
2563
|
+
PyTypeObject* sub_cls = (PyTypeObject*)obj;
|
|
2564
|
+
type_change_all_slots(sub_cls, name);
|
|
2565
|
+
#if PY_VERSION_HEX >= 0x030D0000
|
|
2566
|
+
Py_XDECREF(obj);
|
|
2567
|
+
#endif
|
|
2568
|
+
}
|
|
2569
|
+
}
|
|
2570
|
+
|
|
2208
2571
|
static int
|
|
2209
2572
|
PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value)
|
|
2210
2573
|
{
|
|
@@ -2231,6 +2594,33 @@ PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value)
|
|
|
2231
2594
|
return type_setattr(cls, name_str, value);
|
|
2232
2595
|
}
|
|
2233
2596
|
Py_XDECREF(now_code);
|
|
2597
|
+
// if name in __getattribute__, __setattr__, __delattr__, __del__, just set to tp_dict
|
|
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) {
|
|
2603
|
+
PyObject* tp_dict = ((PyTypeObject*)cls)->tp_dict;
|
|
2604
|
+
if (!tp_dict) {
|
|
2605
|
+
PyErr_SetString(PyExc_TypeError, "type has no tp_dict");
|
|
2606
|
+
return -1;
|
|
2607
|
+
}
|
|
2608
|
+
if (!value) {
|
|
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);
|
|
2611
|
+
return -1;
|
|
2612
|
+
}
|
|
2613
|
+
type_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2614
|
+
subtype_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2615
|
+
return 0;
|
|
2616
|
+
}
|
|
2617
|
+
if (PyDict_SetItem(tp_dict, name, value) < 0) {
|
|
2618
|
+
return -1;
|
|
2619
|
+
}
|
|
2620
|
+
type_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2621
|
+
subtype_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2622
|
+
return 0;
|
|
2623
|
+
}
|
|
2234
2624
|
PyTypeObject* base = Py_TYPE(cls)->tp_base;
|
|
2235
2625
|
while (base && base->tp_base && base->tp_setattro == PrivateAttrType_setattr) {
|
|
2236
2626
|
base = base->tp_base;
|
|
@@ -2316,7 +2706,7 @@ static void
|
|
|
2316
2706
|
PrivateAttrType_del(PyObject* cls)
|
|
2317
2707
|
{
|
|
2318
2708
|
PrivateAttrType_finalize(cls);
|
|
2319
|
-
(
|
|
2709
|
+
PyType_Type.tp_dealloc(cls);
|
|
2320
2710
|
}
|
|
2321
2711
|
|
|
2322
2712
|
static const char* PrivateAttrBase_doc = "The class to help to create private attribute. It does not have any special behavior.";
|
|
@@ -2775,7 +3165,8 @@ static PyModuleDef def = {
|
|
|
2775
3165
|
PyMODINIT_FUNC
|
|
2776
3166
|
PyInit_private_attribute(void)
|
|
2777
3167
|
{
|
|
2778
|
-
if (
|
|
3168
|
+
if (init_all_slots() <0 ||
|
|
3169
|
+
PyType_Ready(&PrivateWrapType) < 0 ||
|
|
2779
3170
|
PyType_Ready(&PrivateWrapProxyType) < 0 ||
|
|
2780
3171
|
PyType_Ready(&PrivateAttrType) < 0 ||
|
|
2781
3172
|
PyType_Ready(&PrivateModuleType) < 0 ||
|
{private_attribute_cpp-1.3.6 → private_attribute_cpp-1.3.8/private_attribute_cpp.egg-info}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: private_attribute_cpp
|
|
3
|
-
Version: 1.3.
|
|
3
|
+
Version: 1.3.8
|
|
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.
|
|
22
|
+
version='1.3.8',
|
|
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.',
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|