private-attribute-cpp 1.4.11__tar.gz → 2.0.0__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.4.11/private_attribute_cpp.egg-info → private_attribute_cpp-2.0.0}/PKG-INFO +1 -1
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/private_attribute.cpp +401 -394
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/setup.py +1 -1
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/LICENSE +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/MANIFEST.in +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/README.md +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/picosha2.h +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/private_attribute.pyi +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/private_attribute_cpp.egg-info/top_level.txt +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/setup.cfg +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_class_private_attrs.py +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_private_abc.py +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_private_attrs.py +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_private_func.py +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_private_inheritance.py +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_private_method.py +0 -0
- {private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_private_wrap.py +0 -0
{private_attribute_cpp-1.4.11/private_attribute_cpp.egg-info → private_attribute_cpp-2.0.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: private_attribute_cpp
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
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
|
|
@@ -12,14 +12,12 @@
|
|
|
12
12
|
#include <ctime>
|
|
13
13
|
#include <iomanip>
|
|
14
14
|
#include <sstream>
|
|
15
|
-
#include <vector>
|
|
16
15
|
#include <random>
|
|
17
16
|
#include <mutex>
|
|
18
17
|
#include <shared_mutex>
|
|
19
18
|
#include "picosha2.h"
|
|
20
19
|
#include <functional>
|
|
21
20
|
#include <memory>
|
|
22
|
-
#include <algorithm>
|
|
23
21
|
|
|
24
22
|
// python under 3.13 doesn't have PyDict_ContainsString, so we implement it ourselves
|
|
25
23
|
#if PY_VERSION_HEX < 0x030D0000
|
|
@@ -35,7 +33,6 @@ PyDict_ContainsString(PyObject *op, const char *key) noexcept
|
|
|
35
33
|
return res;
|
|
36
34
|
}
|
|
37
35
|
#endif
|
|
38
|
-
|
|
39
36
|
static const auto module_running_time = std::chrono::system_clock::now();
|
|
40
37
|
|
|
41
38
|
static std::string
|
|
@@ -110,7 +107,7 @@ namespace std {
|
|
|
110
107
|
return key.gethash();
|
|
111
108
|
}
|
|
112
109
|
};
|
|
113
|
-
}
|
|
110
|
+
}
|
|
114
111
|
|
|
115
112
|
namespace {
|
|
116
113
|
namespace AllData {
|
|
@@ -144,12 +141,6 @@ namespace {
|
|
|
144
141
|
};
|
|
145
142
|
};
|
|
146
143
|
|
|
147
|
-
namespace AllSlots {
|
|
148
|
-
static getattrofunc original_getattro = nullptr;
|
|
149
|
-
static setattrofunc original_setattro = nullptr;
|
|
150
|
-
static destructor original_finalize = nullptr;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
144
|
struct FinalObject
|
|
154
145
|
{
|
|
155
146
|
PyObject* result = NULL;
|
|
@@ -227,7 +218,7 @@ generate_private_attr_name(uintptr_t obj_id, const std::string& attr_name) noexc
|
|
|
227
218
|
|
|
228
219
|
unsigned long long seed = std::stoul(hash_str.substr(0, 8), nullptr, 16);
|
|
229
220
|
|
|
230
|
-
std::mt19937 rng(seed);
|
|
221
|
+
std::mt19937 rng(static_cast<std::mt19937::result_type>(seed));
|
|
231
222
|
|
|
232
223
|
static const std::string printable_chars =
|
|
233
224
|
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ ";
|
|
@@ -325,12 +316,77 @@ public:
|
|
|
325
316
|
type = value = traceback = nullptr;
|
|
326
317
|
}
|
|
327
318
|
|
|
319
|
+
const char* what() const noexcept override {
|
|
320
|
+
if (!msg_.empty())
|
|
321
|
+
return msg_.c_str();
|
|
322
|
+
|
|
323
|
+
if (!type || !value) {
|
|
324
|
+
msg_ = "cannot format this exception (missing type/value)";
|
|
325
|
+
return msg_.c_str();
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
PyObject* tb_mod = PyImport_ImportModule("traceback");
|
|
329
|
+
if (!tb_mod) {
|
|
330
|
+
msg_ = "cannot format this exception (import traceback failed)";
|
|
331
|
+
return msg_.c_str();
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
PyObject* format_exc = PyObject_GetAttrString(tb_mod, "format_exception");
|
|
335
|
+
Py_DECREF(tb_mod);
|
|
336
|
+
if (!format_exc) {
|
|
337
|
+
msg_ = "cannot format this exception (get format_exception failed)";
|
|
338
|
+
return msg_.c_str();
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
PyObject* result = PyObject_CallFunctionObjArgs(
|
|
342
|
+
format_exc, type, value, traceback ? traceback : Py_None, nullptr);
|
|
343
|
+
Py_DECREF(format_exc);
|
|
344
|
+
|
|
345
|
+
if (!result) {
|
|
346
|
+
msg_ = "cannot format this exception (format_exception failed)";
|
|
347
|
+
return msg_.c_str();
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
PyObject* empty = PyUnicode_FromString("");
|
|
351
|
+
if (!empty) {
|
|
352
|
+
Py_DECREF(result);
|
|
353
|
+
msg_ = "cannot format this exception (create empty string failed)";
|
|
354
|
+
return msg_.c_str();
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
PyObject* joined = PyUnicode_Join(empty, result);
|
|
358
|
+
Py_DECREF(empty);
|
|
359
|
+
Py_DECREF(result);
|
|
360
|
+
|
|
361
|
+
if (!joined) {
|
|
362
|
+
msg_ = "cannot format this exception (join failed)";
|
|
363
|
+
return msg_.c_str();
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
const char* utf8 = PyUnicode_AsUTF8(joined);
|
|
367
|
+
if (utf8)
|
|
368
|
+
msg_ = utf8;
|
|
369
|
+
else
|
|
370
|
+
msg_ = "cannot format this exception (AsUTF8 failed)";
|
|
371
|
+
|
|
372
|
+
Py_DECREF(joined);
|
|
373
|
+
return msg_.c_str();
|
|
374
|
+
}
|
|
375
|
+
|
|
328
376
|
private:
|
|
329
377
|
PyObject* type = nullptr;
|
|
330
378
|
PyObject* value = nullptr;
|
|
331
379
|
PyObject* traceback = nullptr;
|
|
380
|
+
mutable std::string msg_;
|
|
332
381
|
};
|
|
333
382
|
|
|
383
|
+
// In MSVC, disable warning C5272
|
|
384
|
+
// The custom_random_string will throw RestorePythonException, which cannot be copied and will be caught anyway.
|
|
385
|
+
#ifdef _MSC_VER
|
|
386
|
+
#pragma warning(push)
|
|
387
|
+
#pragma warning(disable: 5272)
|
|
388
|
+
#endif
|
|
389
|
+
|
|
334
390
|
static std::string
|
|
335
391
|
custom_random_string(uintptr_t obj_id, const std::string& attr_name, PyObject* func)
|
|
336
392
|
{
|
|
@@ -389,6 +445,10 @@ custom_random_string(uintptr_t obj_id, const std::string& attr_name, PyObject* f
|
|
|
389
445
|
return result;
|
|
390
446
|
}
|
|
391
447
|
|
|
448
|
+
#ifdef _MSC_VER
|
|
449
|
+
#pragma warning(pop)
|
|
450
|
+
#endif
|
|
451
|
+
|
|
392
452
|
static void
|
|
393
453
|
clear_obj(uintptr_t obj_id) noexcept
|
|
394
454
|
{
|
|
@@ -897,7 +957,7 @@ static PyObject*
|
|
|
897
957
|
PrivateWrap_doc(PyObject *obj, void* /*closure*/) noexcept
|
|
898
958
|
{
|
|
899
959
|
if (!obj) {
|
|
900
|
-
return
|
|
960
|
+
return PyUnicode_InternFromString("PrivateWrap");
|
|
901
961
|
}
|
|
902
962
|
PyObject* doc = PyObject_GetAttrString(((PrivateWrapObject*)obj)->result, "__doc__");
|
|
903
963
|
if (!doc) {
|
|
@@ -911,26 +971,26 @@ static PyObject*
|
|
|
911
971
|
PrivateWrap_module(PyObject *obj, void* /*closure*/) noexcept
|
|
912
972
|
{
|
|
913
973
|
if (!obj) {
|
|
914
|
-
return
|
|
974
|
+
return PyUnicode_InternFromString("private_attribute");
|
|
915
975
|
}
|
|
916
976
|
PyObject* module = PyObject_GetAttrString(((PrivateWrapObject*)obj)->result, "__module__");
|
|
917
977
|
if (!module){
|
|
918
978
|
PyErr_Clear();
|
|
919
|
-
return
|
|
979
|
+
return PyUnicode_InternFromString("private_attribute");
|
|
920
980
|
}
|
|
921
981
|
return module;
|
|
922
982
|
}
|
|
923
983
|
|
|
924
984
|
static PyObject*
|
|
925
|
-
|
|
985
|
+
PrivateWrap_name(PyObject* obj, void* /*closure*/) noexcept
|
|
926
986
|
{
|
|
927
987
|
if (!obj) {
|
|
928
|
-
return
|
|
988
|
+
return PyUnicode_InternFromString("_PrivateWrap");
|
|
929
989
|
}
|
|
930
990
|
PyObject* name = PyObject_GetAttrString(((PrivateWrapObject*)obj)->result, "__name__");
|
|
931
991
|
if (!name) {
|
|
932
992
|
PyErr_Clear();
|
|
933
|
-
return
|
|
993
|
+
return PyUnicode_InternFromString("_PrivateWrap");
|
|
934
994
|
}
|
|
935
995
|
return name;
|
|
936
996
|
}
|
|
@@ -939,12 +999,12 @@ static PyObject*
|
|
|
939
999
|
PrivateWrap_qualname(PyObject* obj, void* /*closure*/) noexcept
|
|
940
1000
|
{
|
|
941
1001
|
if (!obj) {
|
|
942
|
-
return
|
|
1002
|
+
return PyUnicode_InternFromString("_PrivateWrap");
|
|
943
1003
|
}
|
|
944
1004
|
PyObject* qualname = PyObject_GetAttrString(((PrivateWrapObject*)obj)->result, "__qualname__");
|
|
945
1005
|
if (!qualname) {
|
|
946
1006
|
PyErr_Clear();
|
|
947
|
-
return
|
|
1007
|
+
return PyUnicode_InternFromString("_PrivateWrap");
|
|
948
1008
|
}
|
|
949
1009
|
return qualname;
|
|
950
1010
|
}
|
|
@@ -979,32 +1039,76 @@ PrivateWrap_type_params(PyObject* obj, void* /*closure*/) noexcept
|
|
|
979
1039
|
return type_params;
|
|
980
1040
|
}
|
|
981
1041
|
|
|
982
|
-
static const char* PrivateWrap_result_doc = "the final result of decorating";
|
|
983
1042
|
static const char* PrivateWrap_funcs_doc = "the original functions";
|
|
984
1043
|
|
|
985
1044
|
static PyGetSetDef PrivateWrap_getset[] = {
|
|
986
1045
|
{"funcs", (getter)PrivateWrap_funcs, NULL, PrivateWrap_funcs_doc, NULL},
|
|
987
1046
|
{"__doc__", (getter)PrivateWrap_doc, NULL, NULL, NULL},
|
|
988
1047
|
{"__module__", (getter)PrivateWrap_module, NULL, NULL, NULL},
|
|
989
|
-
{"__name__", (getter)
|
|
1048
|
+
{"__name__", (getter)PrivateWrap_name, NULL, NULL, NULL},
|
|
990
1049
|
{"__qualname__", (getter)PrivateWrap_qualname, NULL, NULL, NULL},
|
|
991
1050
|
{"__annotate__", (getter)PrivateWrap_annotate, NULL, NULL, NULL},
|
|
992
1051
|
{"__type_params__", (getter)PrivateWrap_type_params, NULL, NULL, NULL},
|
|
993
1052
|
{NULL}
|
|
994
1053
|
};
|
|
995
1054
|
|
|
1055
|
+
#define PrivateWrap_getattro_dunder(name) do {\
|
|
1056
|
+
if (strcmp(name_str, "__" #name "__") == 0) {\
|
|
1057
|
+
return PrivateWrap_##name(obj, NULL);\
|
|
1058
|
+
}\
|
|
1059
|
+
} while(0)
|
|
1060
|
+
|
|
996
1061
|
static PyObject *
|
|
997
1062
|
PrivateWrap_getattro(PyObject *obj, PyObject *name) noexcept
|
|
998
1063
|
{
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1064
|
+
PrivateWrapObject *self = (PrivateWrapObject *)obj;
|
|
1065
|
+
const char *name_str = PyUnicode_AsUTF8(name);
|
|
1066
|
+
if (!name_str) {
|
|
1067
|
+
PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
|
|
1068
|
+
return NULL;
|
|
1002
1069
|
}
|
|
1070
|
+
if (strcmp(name_str, "__wrapped__") == 0 || strcmp(name_str, "result") == 0) {
|
|
1071
|
+
if (!self->result) {
|
|
1072
|
+
PyErr_SetString(PyExc_AttributeError, "attribute 'result' is invalid");
|
|
1073
|
+
return NULL;
|
|
1074
|
+
}
|
|
1075
|
+
Py_INCREF(self->result);
|
|
1076
|
+
return self->result;
|
|
1077
|
+
}
|
|
1078
|
+
if (strcmp(name_str, "funcs") == 0) {
|
|
1079
|
+
return PrivateWrap_funcs(obj, NULL);
|
|
1080
|
+
}
|
|
1081
|
+
PrivateWrap_getattro_dunder(doc);
|
|
1082
|
+
PrivateWrap_getattro_dunder(module);
|
|
1083
|
+
PrivateWrap_getattro_dunder(name);
|
|
1084
|
+
PrivateWrap_getattro_dunder(qualname);
|
|
1085
|
+
PrivateWrap_getattro_dunder(annotate);
|
|
1086
|
+
PrivateWrap_getattro_dunder(type_params);
|
|
1087
|
+
return PyObject_GetAttr(self->result, name);
|
|
1088
|
+
}
|
|
1003
1089
|
|
|
1004
|
-
|
|
1090
|
+
static PyObject*
|
|
1091
|
+
PrivateWrap_descrget(PyObject* obj, PyObject* name, PyObject* cls) noexcept
|
|
1092
|
+
{
|
|
1093
|
+
PyObject* result = ((PrivateWrapObject*)obj)->result;
|
|
1094
|
+
if (Py_TYPE(result)->tp_descr_get) {
|
|
1095
|
+
return Py_TYPE(result)->tp_descr_get(result, name, cls);
|
|
1096
|
+
} else {
|
|
1097
|
+
Py_INCREF(result);
|
|
1098
|
+
return result;
|
|
1099
|
+
}
|
|
1100
|
+
}
|
|
1005
1101
|
|
|
1006
|
-
|
|
1007
|
-
|
|
1102
|
+
static int
|
|
1103
|
+
PrivateWrap_descrset(PyObject* obj, PyObject* name, PyObject* value) noexcept
|
|
1104
|
+
{
|
|
1105
|
+
PyObject* result = ((PrivateWrapObject*)obj)->result;
|
|
1106
|
+
if (Py_TYPE(result)->tp_descr_set) {
|
|
1107
|
+
return Py_TYPE(result)->tp_descr_set(result, name, value);
|
|
1108
|
+
} else {
|
|
1109
|
+
PyErr_SetString(PyExc_AttributeError, "attribute is not settable");
|
|
1110
|
+
return -1;
|
|
1111
|
+
}
|
|
1008
1112
|
}
|
|
1009
1113
|
|
|
1010
1114
|
static PyTypeObject PrivateWrapType = {
|
|
@@ -1028,7 +1132,7 @@ static PyTypeObject PrivateWrapType = {
|
|
|
1028
1132
|
0, // tp_setattro
|
|
1029
1133
|
0, // tp_as_buffer
|
|
1030
1134
|
Py_TPFLAGS_DEFAULT, // tp_flags
|
|
1031
|
-
"_PrivateWrap",
|
|
1135
|
+
"private_attribute._PrivateWrap", // tp_doc
|
|
1032
1136
|
0, // tp_traverse
|
|
1033
1137
|
0, // tp_clear
|
|
1034
1138
|
0, // tp_richcompare
|
|
@@ -1038,6 +1142,10 @@ static PyTypeObject PrivateWrapType = {
|
|
|
1038
1142
|
0, // tp_methods
|
|
1039
1143
|
PrivateWrap_members, // tp_members
|
|
1040
1144
|
PrivateWrap_getset, // tp_getset
|
|
1145
|
+
0, // tp_base
|
|
1146
|
+
0, // tp_dict
|
|
1147
|
+
PrivateWrap_descrget, // tp_descr_get
|
|
1148
|
+
PrivateWrap_descrset, // tp_descr_set
|
|
1041
1149
|
};
|
|
1042
1150
|
|
|
1043
1151
|
static PrivateWrapObject*
|
|
@@ -1814,12 +1922,17 @@ need_analyse_type(PyObject* type) noexcept
|
|
|
1814
1922
|
}
|
|
1815
1923
|
#if PY_VERSION_HEX < 0x030D0000
|
|
1816
1924
|
PyObject* metaclass = PyWeakref_GET_OBJECT(metaclassref);
|
|
1925
|
+
if (type == metaclass) continue;
|
|
1817
1926
|
if (PyObject_IsInstance(type, metaclass)) {
|
|
1818
1927
|
return true;
|
|
1819
1928
|
}
|
|
1820
1929
|
#else
|
|
1821
1930
|
PyObject* metaclass;
|
|
1822
1931
|
if (PyWeakref_GetRef(metaclassref, &metaclass) == 1) {
|
|
1932
|
+
if (type == metaclass) {
|
|
1933
|
+
Py_DECREF(metaclass);
|
|
1934
|
+
continue;
|
|
1935
|
+
}
|
|
1823
1936
|
if (PyObject_IsInstance(type, metaclass)) {
|
|
1824
1937
|
Py_DECREF(metaclass);
|
|
1825
1938
|
return true;
|
|
@@ -1831,157 +1944,6 @@ need_analyse_type(PyObject* type) noexcept
|
|
|
1831
1944
|
return false;
|
|
1832
1945
|
}
|
|
1833
1946
|
|
|
1834
|
-
static void
|
|
1835
|
-
get_getattribute_and_getattr(PyTypeObject* cls, PyObject** getattribute, PyObject** getattr) noexcept
|
|
1836
|
-
{
|
|
1837
|
-
bool has_getattribute = false;
|
|
1838
|
-
bool has_getattr = false;
|
|
1839
|
-
if (PyDict_ContainsString(cls->tp_dict, "__getattribute__")) {
|
|
1840
|
-
*getattribute = PyDict_GetItemString(cls->tp_dict, "__getattribute__");
|
|
1841
|
-
has_getattribute = true;
|
|
1842
|
-
}
|
|
1843
|
-
if (PyDict_ContainsString(cls->tp_dict, "__getattr__")) {
|
|
1844
|
-
*getattr = PyDict_GetItemString(cls->tp_dict, "__getattr__");
|
|
1845
|
-
has_getattr = true;
|
|
1846
|
-
}
|
|
1847
|
-
if (has_getattribute && has_getattr) {
|
|
1848
|
-
return;
|
|
1849
|
-
}
|
|
1850
|
-
for (PyTypeObject* base = cls->tp_base; base != NULL && base != &PyBaseObject_Type; base = base->tp_base) {
|
|
1851
|
-
if (!has_getattribute && PyDict_ContainsString(base->tp_dict, "__getattribute__")) {
|
|
1852
|
-
*getattribute = PyDict_GetItemString(base->tp_dict, "__getattribute__");
|
|
1853
|
-
has_getattribute = true;
|
|
1854
|
-
}
|
|
1855
|
-
if (!has_getattr && PyDict_ContainsString(base->tp_dict, "__getattr__")) {
|
|
1856
|
-
*getattr = PyDict_GetItemString(base->tp_dict, "__getattr__");
|
|
1857
|
-
has_getattr = true;
|
|
1858
|
-
}
|
|
1859
|
-
if (has_getattribute && has_getattr) {
|
|
1860
|
-
return;
|
|
1861
|
-
}
|
|
1862
|
-
}
|
|
1863
|
-
}
|
|
1864
|
-
|
|
1865
|
-
static void
|
|
1866
|
-
get_setattr_and_delattr(PyTypeObject* cls, PyObject** setattr, PyObject** delattr) noexcept
|
|
1867
|
-
{
|
|
1868
|
-
bool has_setattr = false;
|
|
1869
|
-
bool has_delattr = false;
|
|
1870
|
-
if (PyDict_ContainsString(cls->tp_dict, "__setattr__")) {
|
|
1871
|
-
*setattr = PyDict_GetItemString(cls->tp_dict, "__setattr__");
|
|
1872
|
-
has_setattr = true;
|
|
1873
|
-
}
|
|
1874
|
-
if (PyDict_ContainsString(cls->tp_dict, "__delattr__")) {
|
|
1875
|
-
*delattr = PyDict_GetItemString(cls->tp_dict, "__delattr__");
|
|
1876
|
-
has_delattr = true;
|
|
1877
|
-
}
|
|
1878
|
-
if (has_setattr && has_delattr) {
|
|
1879
|
-
return;
|
|
1880
|
-
}
|
|
1881
|
-
for (PyTypeObject* base = cls->tp_base; base != NULL && base != &PyBaseObject_Type; base = base->tp_base) {
|
|
1882
|
-
if (!has_setattr && PyDict_ContainsString(base->tp_dict, "__setattr__")) {
|
|
1883
|
-
*setattr = PyDict_GetItemString(base->tp_dict, "__setattr__");
|
|
1884
|
-
has_setattr = true;
|
|
1885
|
-
}
|
|
1886
|
-
if (!has_delattr && PyDict_ContainsString(base->tp_dict, "__delattr__")) {
|
|
1887
|
-
*delattr = PyDict_GetItemString(base->tp_dict, "__delattr__");
|
|
1888
|
-
has_delattr = true;
|
|
1889
|
-
}
|
|
1890
|
-
if (has_setattr && has_delattr) {
|
|
1891
|
-
return;
|
|
1892
|
-
}
|
|
1893
|
-
}
|
|
1894
|
-
}
|
|
1895
|
-
|
|
1896
|
-
static void
|
|
1897
|
-
get_del(PyTypeObject* cls, PyObject** del) noexcept
|
|
1898
|
-
{
|
|
1899
|
-
if (PyDict_ContainsString(cls->tp_dict, "__del__")) {
|
|
1900
|
-
*del = PyDict_GetItemString(cls->tp_dict, "__del__");
|
|
1901
|
-
return;
|
|
1902
|
-
}
|
|
1903
|
-
for (PyTypeObject* base = cls->tp_base; base != NULL && base != &PyBaseObject_Type; base = base->tp_base) {
|
|
1904
|
-
if (PyDict_ContainsString(base->tp_dict, "__del__")) {
|
|
1905
|
-
*del = PyDict_GetItemString(base->tp_dict, "__del__");
|
|
1906
|
-
return;
|
|
1907
|
-
}
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
|
|
1911
|
-
static PyObject*
|
|
1912
|
-
python_original_tp_getattro(PyObject* self, PyObject* name) noexcept
|
|
1913
|
-
{
|
|
1914
|
-
PyObject* getattriute = NULL;
|
|
1915
|
-
PyObject* getattr = NULL;
|
|
1916
|
-
get_getattribute_and_getattr((PyTypeObject*)self->ob_type, &getattriute, &getattr);
|
|
1917
|
-
PyObject* res = NULL;
|
|
1918
|
-
if (getattriute) {
|
|
1919
|
-
res = PyObject_CallFunctionObjArgs(getattriute, self, name, NULL);
|
|
1920
|
-
} else {
|
|
1921
|
-
res = PyObject_GenericGetAttr(self, name);
|
|
1922
|
-
}
|
|
1923
|
-
if (!res && getattr) {
|
|
1924
|
-
// check if the exception is AttributeError
|
|
1925
|
-
if (!PyErr_ExceptionMatches(PyExc_AttributeError)) {
|
|
1926
|
-
return NULL;
|
|
1927
|
-
}
|
|
1928
|
-
PyErr_Clear();
|
|
1929
|
-
res = PyObject_CallFunctionObjArgs(getattr, self, name, NULL);
|
|
1930
|
-
}
|
|
1931
|
-
return res;
|
|
1932
|
-
}
|
|
1933
|
-
|
|
1934
|
-
static int
|
|
1935
|
-
python_original_tp_setattro(PyObject* self, PyObject* name, PyObject* value) noexcept
|
|
1936
|
-
{
|
|
1937
|
-
PyObject* setattr = NULL;
|
|
1938
|
-
PyObject* delattr = NULL;
|
|
1939
|
-
get_setattr_and_delattr((PyTypeObject*)self->ob_type, &setattr, &delattr);
|
|
1940
|
-
if (value && setattr) {
|
|
1941
|
-
PyObject* res = PyObject_CallFunctionObjArgs(setattr, self, name, value, NULL);
|
|
1942
|
-
if (!res) {
|
|
1943
|
-
return -1;
|
|
1944
|
-
}
|
|
1945
|
-
Py_DECREF(res);
|
|
1946
|
-
return 0;
|
|
1947
|
-
} else if (!value && delattr) {
|
|
1948
|
-
PyObject* res = PyObject_CallFunctionObjArgs(delattr, self, name, NULL);
|
|
1949
|
-
if (!res) {
|
|
1950
|
-
return -1;
|
|
1951
|
-
}
|
|
1952
|
-
Py_DECREF(res);
|
|
1953
|
-
return 0;
|
|
1954
|
-
}
|
|
1955
|
-
return PyObject_GenericSetAttr(self, name, value);
|
|
1956
|
-
}
|
|
1957
|
-
|
|
1958
|
-
static void
|
|
1959
|
-
python_original_tp_finalize(PyObject* self) noexcept
|
|
1960
|
-
{
|
|
1961
|
-
PyObject* del = NULL;
|
|
1962
|
-
get_del((PyTypeObject*)self->ob_type, &del);
|
|
1963
|
-
if (del) {
|
|
1964
|
-
PyObject *exc_type = NULL, *exc_value = NULL, *exc_tb = NULL;
|
|
1965
|
-
PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
|
|
1966
|
-
PyObject *result = PyObject_CallFunctionObjArgs(del, self, NULL);
|
|
1967
|
-
if (result == NULL) {
|
|
1968
|
-
// python < 3.13 use PyErr_WriteUnraisable, python >= 3.13 use PyErr_FormatUnraisable
|
|
1969
|
-
# if PY_VERSION_HEX >= 0x030D0000
|
|
1970
|
-
PyErr_FormatUnraisable("Exception ignored while "
|
|
1971
|
-
"calling deallocator %R", del);
|
|
1972
|
-
# else
|
|
1973
|
-
PyErr_WriteUnraisable(del);
|
|
1974
|
-
# endif
|
|
1975
|
-
}
|
|
1976
|
-
else {
|
|
1977
|
-
Py_DECREF(result);
|
|
1978
|
-
}
|
|
1979
|
-
if (exc_type != NULL) {
|
|
1980
|
-
PyErr_Restore(exc_type, exc_value, exc_tb);
|
|
1981
|
-
}
|
|
1982
|
-
}
|
|
1983
|
-
}
|
|
1984
|
-
|
|
1985
1947
|
static bool
|
|
1986
1948
|
PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationData& data) noexcept
|
|
1987
1949
|
{
|
|
@@ -2223,67 +2185,55 @@ ensure_tp(PyTypeObject* type_instance) noexcept
|
|
|
2223
2185
|
uintptr_t type_id = (uintptr_t)(type_instance);
|
|
2224
2186
|
{
|
|
2225
2187
|
if (type_instance->tp_getattro != PrivateAttr_tp_getattro) {
|
|
2226
|
-
if (!type_instance->tp_getattro) {
|
|
2188
|
+
if (!type_instance->tp_getattro && ::AllData::all_type_getattro.find(type_id) == ::AllData::all_type_getattro.end()) {
|
|
2227
2189
|
::AllData::all_type_getattro[type_id] = get_need_tp_getattro(type_instance);
|
|
2228
2190
|
} else {
|
|
2229
2191
|
::AllData::all_type_getattro[type_id] = type_instance->tp_getattro;
|
|
2230
2192
|
}
|
|
2231
2193
|
type_instance->tp_getattro = PrivateAttr_tp_getattro;
|
|
2232
|
-
} else {
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
::AllData::all_type_getattro[type_id] = ::AllData::all_type_getattro[base_id];
|
|
2240
|
-
} else if (base && base->tp_getattro && base->tp_getattro != PrivateAttr_tp_getattro) {
|
|
2241
|
-
::AllData::all_type_getattro[type_id] = base->tp_getattro;
|
|
2242
|
-
}
|
|
2194
|
+
} else if (::AllData::all_type_getattro.find(type_id) == ::AllData::all_type_getattro.end()) {
|
|
2195
|
+
PyTypeObject* base = type_instance->tp_base;
|
|
2196
|
+
uintptr_t base_id = (uintptr_t)(base);
|
|
2197
|
+
if (::AllData::all_type_getattro.find(base_id) != ::AllData::all_type_getattro.end()) {
|
|
2198
|
+
::AllData::all_type_getattro[type_id] = ::AllData::all_type_getattro[base_id];
|
|
2199
|
+
} else if (base && base->tp_getattro && base->tp_getattro != PrivateAttr_tp_getattro) {
|
|
2200
|
+
::AllData::all_type_getattro[type_id] = base->tp_getattro;
|
|
2243
2201
|
}
|
|
2244
2202
|
}
|
|
2245
2203
|
}
|
|
2246
2204
|
{
|
|
2247
2205
|
if (type_instance->tp_setattro != PrivateAttr_tp_setattro) {
|
|
2248
|
-
if (!type_instance->tp_setattro) {
|
|
2206
|
+
if (!type_instance->tp_setattro && ::AllData::all_type_setattro.find(type_id) == ::AllData::all_type_setattro.end()) {
|
|
2249
2207
|
::AllData::all_type_setattro[type_id] = get_need_tp_setattro(type_instance);
|
|
2250
2208
|
} else {
|
|
2251
2209
|
::AllData::all_type_setattro[type_id] = type_instance->tp_setattro;
|
|
2252
2210
|
}
|
|
2253
2211
|
type_instance->tp_setattro = PrivateAttr_tp_setattro;
|
|
2254
|
-
} else {
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
::AllData::all_type_setattro[type_id] = ::AllData::all_type_setattro[base_id];
|
|
2262
|
-
} else if (base && base->tp_setattro && base->tp_setattro != PrivateAttr_tp_setattro) {
|
|
2263
|
-
::AllData::all_type_setattro[type_id] = base->tp_setattro;
|
|
2264
|
-
}
|
|
2212
|
+
} else if (::AllData::all_type_setattro.find(type_id) == ::AllData::all_type_setattro.end()){
|
|
2213
|
+
PyTypeObject* base = type_instance->tp_base;
|
|
2214
|
+
uintptr_t base_id = (uintptr_t)(base);
|
|
2215
|
+
if (::AllData::all_type_setattro.find(base_id) != ::AllData::all_type_setattro.end()) {
|
|
2216
|
+
::AllData::all_type_setattro[type_id] = ::AllData::all_type_setattro[base_id];
|
|
2217
|
+
} else if (base && base->tp_setattro && base->tp_setattro != PrivateAttr_tp_setattro) {
|
|
2218
|
+
::AllData::all_type_setattro[type_id] = base->tp_setattro;
|
|
2265
2219
|
}
|
|
2266
2220
|
}
|
|
2267
2221
|
}
|
|
2268
2222
|
{
|
|
2269
2223
|
if (type_instance->tp_finalize != PrivateAttr_tp_finalize) {
|
|
2270
|
-
if (!type_instance->tp_finalize) {
|
|
2224
|
+
if (!type_instance->tp_finalize && ::AllData::all_type_finalize.find(type_id) == ::AllData::all_type_finalize.end()) {
|
|
2271
2225
|
::AllData::all_type_finalize[type_id] = get_need_tp_finalize(type_instance);
|
|
2272
2226
|
} else {
|
|
2273
2227
|
::AllData::all_type_finalize[type_id] = type_instance->tp_finalize;
|
|
2274
2228
|
}
|
|
2275
2229
|
type_instance->tp_finalize = PrivateAttr_tp_finalize;
|
|
2276
|
-
} else {
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
::AllData::all_type_finalize[type_id] = ::AllData::all_type_finalize[base_id];
|
|
2284
|
-
} else if (base && base->tp_finalize && base->tp_finalize != PrivateAttr_tp_finalize) {
|
|
2285
|
-
::AllData::all_type_finalize[type_id] = base->tp_finalize;
|
|
2286
|
-
}
|
|
2230
|
+
} else if (::AllData::all_type_finalize.find(type_id) == ::AllData::all_type_finalize.end()) {
|
|
2231
|
+
PyTypeObject* base = type_instance->tp_base;
|
|
2232
|
+
uintptr_t base_id = (uintptr_t)(base);
|
|
2233
|
+
if (::AllData::all_type_finalize.find(base_id) != ::AllData::all_type_finalize.end()) {
|
|
2234
|
+
::AllData::all_type_finalize[type_id] = ::AllData::all_type_finalize[base_id];
|
|
2235
|
+
} else if (base && base->tp_finalize && base->tp_finalize != PrivateAttr_tp_finalize) {
|
|
2236
|
+
::AllData::all_type_finalize[type_id] = base->tp_finalize;
|
|
2287
2237
|
}
|
|
2288
2238
|
}
|
|
2289
2239
|
}
|
|
@@ -2292,40 +2242,16 @@ ensure_tp(PyTypeObject* type_instance) noexcept
|
|
|
2292
2242
|
static void
|
|
2293
2243
|
ensure_subclass_tp(PyTypeObject* type_instance) noexcept
|
|
2294
2244
|
{
|
|
2295
|
-
|
|
2296
|
-
|
|
2297
|
-
|
|
2298
|
-
|
|
2299
|
-
|
|
2300
|
-
|
|
2301
|
-
|
|
2302
|
-
}
|
|
2303
|
-
// check all values in the dict. It should be a weakref to a type. If not, continue.
|
|
2304
|
-
PyObject* key, *value;
|
|
2305
|
-
Py_ssize_t pos = 0;
|
|
2306
|
-
while (PyDict_Next(type_subclasses, &pos, &key, &value)) {
|
|
2307
|
-
if (!value || !PyWeakref_CheckRef(value)) {
|
|
2308
|
-
continue;
|
|
2309
|
-
}
|
|
2310
|
-
// python<3.13 use PyWeakref_GetObject, python>=3.13 use PyWeakref_GetRef
|
|
2311
|
-
#if PY_VERSION_HEX < 0x030D0000
|
|
2312
|
-
PyObject* subclass = PyWeakref_GetObject(value);
|
|
2313
|
-
if (!subclass || !PyType_Check(subclass)) {
|
|
2314
|
-
continue;
|
|
2315
|
-
}
|
|
2316
|
-
ensure_tp((PyTypeObject*)subclass);
|
|
2317
|
-
#else
|
|
2318
|
-
PyObject* subclass;
|
|
2319
|
-
if (PyWeakref_GetRef(value, (PyObject**)&subclass) != 1) {
|
|
2320
|
-
continue;
|
|
2321
|
-
}
|
|
2322
|
-
if (!subclass || !PyType_Check(subclass)) {
|
|
2323
|
-
continue;
|
|
2324
|
-
}
|
|
2245
|
+
PyObject* subclasses = PyObject_CallMethod((PyObject*)&PyType_Type, "__subclasses__", "O", (PyObject*)type_instance);
|
|
2246
|
+
assert(subclasses);
|
|
2247
|
+
assert(PyList_Check(subclasses));
|
|
2248
|
+
Py_ssize_t list_len = PyList_GET_SIZE(subclasses);
|
|
2249
|
+
for (Py_ssize_t i = 0; i < list_len; i++) {
|
|
2250
|
+
PyObject* subclass = PyList_GetItem(subclasses, i);
|
|
2251
|
+
if (!PyType_Check(subclass)) continue;
|
|
2325
2252
|
ensure_tp((PyTypeObject*)subclass);
|
|
2326
|
-
Py_XDECREF(subclass);
|
|
2327
|
-
#endif
|
|
2328
2253
|
}
|
|
2254
|
+
Py_DECREF(subclasses);
|
|
2329
2255
|
}
|
|
2330
2256
|
|
|
2331
2257
|
static bool
|
|
@@ -2348,15 +2274,6 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
|
|
|
2348
2274
|
}
|
|
2349
2275
|
|
|
2350
2276
|
ensure_tp(type_instance);
|
|
2351
|
-
if (PyDict_ContainsString(type_instance->tp_dict, "__getattribute__") || PyDict_ContainsString(type_instance->tp_dict, "__getattr__")) {
|
|
2352
|
-
::AllData::all_type_getattro[type_id] = AllSlots::original_getattro;
|
|
2353
|
-
}
|
|
2354
|
-
if (PyDict_ContainsString(type_instance->tp_dict, "__setattr__") || PyDict_ContainsString(type_instance->tp_dict, "__delattr__")) {
|
|
2355
|
-
::AllData::all_type_setattro[type_id] = AllSlots::original_setattro;
|
|
2356
|
-
}
|
|
2357
|
-
if (PyDict_ContainsString(type_instance->tp_dict, "__del__")) {
|
|
2358
|
-
::AllData::all_type_finalize[type_id] = AllSlots::original_finalize;
|
|
2359
|
-
}
|
|
2360
2277
|
|
|
2361
2278
|
::AllData::type_attr_dict[type_id] = {};
|
|
2362
2279
|
::AllData::all_type_attr_set[type_id] = data.private_attrs_set;
|
|
@@ -2510,21 +2427,93 @@ PrivateAttrType_getattr(PyObject* cls, PyObject* name) noexcept
|
|
|
2510
2427
|
return result;
|
|
2511
2428
|
}
|
|
2512
2429
|
|
|
2430
|
+
static setattrofunc original_type_tp_setattro = 0;
|
|
2431
|
+
|
|
2432
|
+
static bool
|
|
2433
|
+
is_registed_type(PyObject* type) noexcept
|
|
2434
|
+
{
|
|
2435
|
+
uintptr_t typ_id = (uintptr_t)type;
|
|
2436
|
+
return (AllData::all_register_type_weak_ref.find(typ_id) != AllData::all_register_type_weak_ref.end());
|
|
2437
|
+
}
|
|
2438
|
+
|
|
2439
|
+
static PyObject* ensure_metaclass_tp(PyObject* /*self*/, PyObject* metaclass) noexcept;
|
|
2440
|
+
|
|
2441
|
+
static int
|
|
2442
|
+
new_type_tp_setattro(PyObject* self, PyObject* name, PyObject* value) noexcept
|
|
2443
|
+
{
|
|
2444
|
+
std::vector<PyObject*> need_analyse_types_and_metaclasses;
|
|
2445
|
+
std::vector<PyObject*> registered_types_and_metaclasses;
|
|
2446
|
+
std::vector<PyObject*> all_subclasses;
|
|
2447
|
+
PyObject* subclasses = PyObject_CallMethod((PyObject*)&PyType_Type, "__subclasses__", "O", self);
|
|
2448
|
+
if (!subclasses) return -1;
|
|
2449
|
+
if (!PyList_Check(subclasses)) {
|
|
2450
|
+
PyErr_SetString(PyExc_TypeError, "subclasses of this class is not list");
|
|
2451
|
+
Py_DECREF(subclasses);
|
|
2452
|
+
return -1;
|
|
2453
|
+
}
|
|
2454
|
+
Py_ssize_t list_len = PyList_GET_SIZE(subclasses);
|
|
2455
|
+
for (Py_ssize_t i = 0; i < list_len; i++) {
|
|
2456
|
+
all_subclasses.push_back(PyList_GET_ITEM(subclasses, i));
|
|
2457
|
+
}
|
|
2458
|
+
if (need_analyse_type(self)) {
|
|
2459
|
+
need_analyse_types_and_metaclasses.push_back(self);
|
|
2460
|
+
} else if (is_registed_type(self)) {
|
|
2461
|
+
registered_types_and_metaclasses.push_back(self);
|
|
2462
|
+
}
|
|
2463
|
+
for (auto& i: all_subclasses) {
|
|
2464
|
+
if (need_analyse_type(i)) {
|
|
2465
|
+
need_analyse_types_and_metaclasses.push_back(i);
|
|
2466
|
+
} else if (is_registed_type(i)) {
|
|
2467
|
+
registered_types_and_metaclasses.push_back(i);
|
|
2468
|
+
}
|
|
2469
|
+
}
|
|
2470
|
+
int result = original_type_tp_setattro(self, name, value);
|
|
2471
|
+
for (auto& i: need_analyse_types_and_metaclasses) {
|
|
2472
|
+
ensure_tp((PyTypeObject*)i);
|
|
2473
|
+
}
|
|
2474
|
+
for (auto& i: registered_types_and_metaclasses) {
|
|
2475
|
+
ensure_metaclass_tp(0, i);
|
|
2476
|
+
}
|
|
2477
|
+
Py_DECREF(subclasses);
|
|
2478
|
+
return result;
|
|
2479
|
+
}
|
|
2480
|
+
|
|
2513
2481
|
static int
|
|
2514
2482
|
init_all_slots() noexcept
|
|
2515
2483
|
{
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2484
|
+
original_type_tp_setattro = PyType_Type.tp_setattro;
|
|
2485
|
+
PyObject* original_setattr = PyObject_GetAttrString((PyObject*)&PyType_Type, "__setattr__");
|
|
2486
|
+
if (!original_setattr) {return -1;}
|
|
2487
|
+
if (original_setattr && PyObject_IsInstance(original_setattr, (PyObject*)&PyWrapperDescr_Type)) {
|
|
2488
|
+
((PyWrapperDescrObject*)original_setattr)->d_wrapped = (void*)new_type_tp_setattro;
|
|
2489
|
+
}
|
|
2490
|
+
Py_DECREF(original_setattr);
|
|
2491
|
+
PyObject* original_delattr = PyObject_GetAttrString((PyObject*)&PyType_Type, "__delattr__");
|
|
2492
|
+
if (!original_delattr) {return -1;}
|
|
2493
|
+
if (original_delattr && PyObject_IsInstance(original_delattr, (PyObject*)&PyWrapperDescr_Type)) {
|
|
2494
|
+
((PyWrapperDescrObject*)original_delattr)->d_wrapped = (void*)new_type_tp_setattro;
|
|
2495
|
+
}
|
|
2496
|
+
Py_DECREF(original_delattr);
|
|
2497
|
+
PyType_Type.tp_setattro = new_type_tp_setattro;
|
|
2498
|
+
PyObject* all_metaclasses = PyObject_CallMethod((PyObject*)&PyType_Type, "__subclasses__", "O", (PyObject*)&PyType_Type);
|
|
2499
|
+
if (!all_metaclasses) {return -1;}
|
|
2500
|
+
if (!PyList_Check(all_metaclasses)) {
|
|
2501
|
+
Py_DECREF(all_metaclasses);
|
|
2502
|
+
return 0;
|
|
2503
|
+
}
|
|
2504
|
+
Py_ssize_t list_len = PyList_GET_SIZE(all_metaclasses);
|
|
2505
|
+
for (Py_ssize_t i = 0; i < list_len; i++) {
|
|
2506
|
+
PyObject* metaclass = PyList_GET_ITEM(all_metaclasses, i);
|
|
2507
|
+
if (!PyType_Check(metaclass)) {continue;}
|
|
2508
|
+
((PyTypeObject*)metaclass)->tp_setattro = new_type_tp_setattro;
|
|
2509
|
+
}
|
|
2510
|
+
Py_DECREF(all_metaclasses);
|
|
2519
2511
|
return 0;
|
|
2520
2512
|
}
|
|
2521
2513
|
|
|
2522
2514
|
static getattrofunc
|
|
2523
2515
|
get_need_tp_getattro(PyTypeObject* cls) noexcept
|
|
2524
2516
|
{
|
|
2525
|
-
if (PyDict_ContainsString(cls->tp_dict, "__getattribute__") || PyDict_ContainsString(cls->tp_dict, "__getattr__")) {
|
|
2526
|
-
return AllSlots::original_getattro;
|
|
2527
|
-
}
|
|
2528
2517
|
PyTypeObject* base = cls->tp_base;
|
|
2529
2518
|
while (base) {
|
|
2530
2519
|
if (base->tp_getattro != PrivateAttr_tp_getattro) {
|
|
@@ -2544,9 +2533,6 @@ get_need_tp_getattro(PyTypeObject* cls) noexcept
|
|
|
2544
2533
|
static setattrofunc
|
|
2545
2534
|
get_need_tp_setattro(PyTypeObject* cls) noexcept
|
|
2546
2535
|
{
|
|
2547
|
-
if (PyDict_ContainsString(cls->tp_dict, "__setattr__") || PyDict_ContainsString(cls->tp_dict, "__delattr__")) {
|
|
2548
|
-
return AllSlots::original_setattro;
|
|
2549
|
-
}
|
|
2550
2536
|
PyTypeObject* base = cls->tp_base;
|
|
2551
2537
|
while (base) {
|
|
2552
2538
|
if (base->tp_setattro != PrivateAttr_tp_setattro) {
|
|
@@ -2566,9 +2552,6 @@ get_need_tp_setattro(PyTypeObject* cls) noexcept
|
|
|
2566
2552
|
static destructor
|
|
2567
2553
|
get_need_tp_finalize(PyTypeObject* cls) noexcept
|
|
2568
2554
|
{
|
|
2569
|
-
if (PyDict_ContainsString(cls->tp_dict, "__del__")) {
|
|
2570
|
-
return AllSlots::original_finalize;
|
|
2571
|
-
}
|
|
2572
2555
|
PyTypeObject* base = cls->tp_base;
|
|
2573
2556
|
while (base) {
|
|
2574
2557
|
if (base->tp_finalize != PrivateAttr_tp_finalize) {
|
|
@@ -2585,64 +2568,6 @@ get_need_tp_finalize(PyTypeObject* cls) noexcept
|
|
|
2585
2568
|
return NULL;
|
|
2586
2569
|
}
|
|
2587
2570
|
|
|
2588
|
-
static void
|
|
2589
|
-
type_change_all_slots(PyTypeObject* cls, const char* name) noexcept
|
|
2590
|
-
{
|
|
2591
|
-
if (strcmp(name, "__getattribute__") == 0 || strcmp(name, "__getattr__") == 0) {
|
|
2592
|
-
cls->tp_getattro = PrivateAttr_tp_getattro;
|
|
2593
|
-
::AllData::all_type_getattro[(uintptr_t)cls] = get_need_tp_getattro(cls);
|
|
2594
|
-
} else if (strcmp(name, "__setattr__") == 0 || strcmp(name, "__delattr__") == 0) {
|
|
2595
|
-
cls->tp_setattro = PrivateAttr_tp_setattro;
|
|
2596
|
-
::AllData::all_type_setattro[(uintptr_t)cls] = get_need_tp_setattro(cls);
|
|
2597
|
-
} else if (strcmp(name, "__del__") == 0) {
|
|
2598
|
-
cls->tp_finalize = PrivateAttr_tp_finalize;
|
|
2599
|
-
::AllData::all_type_finalize[(uintptr_t)cls] = get_need_tp_finalize(cls);
|
|
2600
|
-
}
|
|
2601
|
-
}
|
|
2602
|
-
|
|
2603
|
-
static void
|
|
2604
|
-
subtype_change_all_slots(PyTypeObject* cls, const char* name) noexcept
|
|
2605
|
-
{
|
|
2606
|
-
// tp_subclasses: {id(type): weakref.ref(type)}
|
|
2607
|
-
PyObject* tp_subclasses = (PyObject*)cls->tp_subclasses;
|
|
2608
|
-
if (!tp_subclasses) {
|
|
2609
|
-
return;
|
|
2610
|
-
}
|
|
2611
|
-
if (!PyDict_Check(tp_subclasses)) {
|
|
2612
|
-
return;
|
|
2613
|
-
}
|
|
2614
|
-
PyObject* key;
|
|
2615
|
-
PyObject* value;
|
|
2616
|
-
Py_ssize_t pos = 0;
|
|
2617
|
-
while (PyDict_Next(tp_subclasses, &pos, &key, &value)) {
|
|
2618
|
-
if (!PyWeakref_Check(value)) {
|
|
2619
|
-
continue;
|
|
2620
|
-
}
|
|
2621
|
-
#if PY_VERSION_HEX < 0x030D0000
|
|
2622
|
-
PyObject* obj = PyWeakref_GET_OBJECT(value);
|
|
2623
|
-
if (!obj) {
|
|
2624
|
-
continue;
|
|
2625
|
-
}
|
|
2626
|
-
#else
|
|
2627
|
-
PyObject* obj;
|
|
2628
|
-
if (PyWeakref_GetRef(value, &obj) != 1) {
|
|
2629
|
-
continue;
|
|
2630
|
-
}
|
|
2631
|
-
if (!obj) {
|
|
2632
|
-
continue;
|
|
2633
|
-
}
|
|
2634
|
-
#endif
|
|
2635
|
-
if (!PyType_Check(obj)) {
|
|
2636
|
-
continue;
|
|
2637
|
-
}
|
|
2638
|
-
PyTypeObject* sub_cls = (PyTypeObject*)obj;
|
|
2639
|
-
type_change_all_slots(sub_cls, name);
|
|
2640
|
-
#if PY_VERSION_HEX >= 0x030D0000
|
|
2641
|
-
Py_XDECREF(obj);
|
|
2642
|
-
#endif
|
|
2643
|
-
}
|
|
2644
|
-
}
|
|
2645
|
-
|
|
2646
2571
|
static int
|
|
2647
2572
|
PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value) noexcept
|
|
2648
2573
|
{
|
|
@@ -2669,42 +2594,12 @@ PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value) noexcept
|
|
|
2669
2594
|
return type_setattr(cls, name_str, value);
|
|
2670
2595
|
}
|
|
2671
2596
|
Py_XDECREF(now_code);
|
|
2672
|
-
// if name in __getattribute__, __setattr__, __delattr__, __del__, just set to tp_dict
|
|
2673
|
-
if (strcmp(name_str.c_str(), "__getattribute__") == 0 ||
|
|
2674
|
-
strcmp(name_str.c_str(), "__getattr__") == 0 ||
|
|
2675
|
-
strcmp(name_str.c_str(), "__setattr__") == 0 ||
|
|
2676
|
-
strcmp(name_str.c_str(), "__delattr__") == 0 ||
|
|
2677
|
-
strcmp(name_str.c_str(), "__del__") == 0) {
|
|
2678
|
-
PyObject* tp_dict = ((PyTypeObject*)cls)->tp_dict;
|
|
2679
|
-
if (!tp_dict) {
|
|
2680
|
-
PyErr_SetString(PyExc_TypeError, "type has no tp_dict");
|
|
2681
|
-
return -1;
|
|
2682
|
-
}
|
|
2683
|
-
if (!value) {
|
|
2684
|
-
if (PyDict_DelItem(tp_dict, name) < 0) {
|
|
2685
|
-
PyErr_Format(PyExc_AttributeError, "type object '%.100s' has no attribute '%U'", ((PyTypeObject*)cls)->tp_name, name);
|
|
2686
|
-
return -1;
|
|
2687
|
-
}
|
|
2688
|
-
type_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2689
|
-
subtype_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2690
|
-
return 0;
|
|
2691
|
-
}
|
|
2692
|
-
if (PyDict_SetItem(tp_dict, name, value) < 0) {
|
|
2693
|
-
return -1;
|
|
2694
|
-
}
|
|
2695
|
-
type_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2696
|
-
subtype_change_all_slots((PyTypeObject*)cls, name_str.c_str());
|
|
2697
|
-
return 0;
|
|
2698
|
-
}
|
|
2699
2597
|
PyTypeObject* base = Py_TYPE(cls)->tp_base;
|
|
2700
2598
|
while (base && base->tp_base && base->tp_setattro == PrivateAttrType_setattr) {
|
|
2701
2599
|
base = base->tp_base;
|
|
2702
2600
|
}
|
|
2703
2601
|
if (!base) {
|
|
2704
|
-
|
|
2705
|
-
ensure_tp((PyTypeObject*)cls);
|
|
2706
|
-
ensure_subclass_tp((PyTypeObject*)cls);
|
|
2707
|
-
return result;
|
|
2602
|
+
return new_type_tp_setattro(cls, name, value);
|
|
2708
2603
|
}
|
|
2709
2604
|
int result = base->tp_setattro(cls, name, value);
|
|
2710
2605
|
ensure_tp((PyTypeObject*)cls);
|
|
@@ -2790,7 +2685,7 @@ static const char* PrivateAttrBase_doc = "The class to help to create private at
|
|
|
2790
2685
|
static PyObject*
|
|
2791
2686
|
create_private_attr_base_simple(void) noexcept
|
|
2792
2687
|
{
|
|
2793
|
-
PyObject* name =
|
|
2688
|
+
PyObject* name = PyUnicode_InternFromString("PrivateAttrBase");
|
|
2794
2689
|
if (!name) return NULL;
|
|
2795
2690
|
PyObject* bases = PyTuple_New(0);
|
|
2796
2691
|
if (!bases) {
|
|
@@ -2812,8 +2707,8 @@ create_private_attr_base_simple(void) noexcept
|
|
|
2812
2707
|
}
|
|
2813
2708
|
PyDict_SetItemString(dict, "__private_attrs__", private_attrs);
|
|
2814
2709
|
PyDict_SetItemString(dict, "__slots__", private_attrs);
|
|
2815
|
-
PyDict_SetItemString(dict, "__doc__",
|
|
2816
|
-
PyDict_SetItemString(dict, "__module__",
|
|
2710
|
+
PyDict_SetItemString(dict, "__doc__", PyUnicode_InternFromString(PrivateAttrBase_doc));
|
|
2711
|
+
PyDict_SetItemString(dict, "__module__", PyUnicode_InternFromString("private_attribute"));
|
|
2817
2712
|
PyObject *args = PyTuple_Pack(3, name, bases, dict);
|
|
2818
2713
|
PyObject* base_type;
|
|
2819
2714
|
if (args) {
|
|
@@ -2905,7 +2800,7 @@ PrivateTempObject_dealloc(PyObject* self) noexcept
|
|
|
2905
2800
|
|
|
2906
2801
|
static PyTypeObject PrivateTempType = {
|
|
2907
2802
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
2908
|
-
"
|
|
2803
|
+
"private_attribute._PrivateTemp", // tp_name
|
|
2909
2804
|
sizeof(PrivateTempObject), // tp_basicsize
|
|
2910
2805
|
0, //tp_itemsize
|
|
2911
2806
|
PrivateTempObject_dealloc, //tp_dealloc
|
|
@@ -3021,8 +2916,40 @@ static PyMethodDef weakref_callback_def = {
|
|
|
3021
2916
|
NULL
|
|
3022
2917
|
};
|
|
3023
2918
|
|
|
2919
|
+
static bool
|
|
2920
|
+
is_class_of_registed_type(PyObject* metaclass) noexcept
|
|
2921
|
+
{
|
|
2922
|
+
std::shared_lock lock(::AllData::all_register_new_metaclass_mutex);
|
|
2923
|
+
for (auto& [id, instanceref]: ::AllData::all_register_type_weak_ref){
|
|
2924
|
+
if (!PyWeakref_CheckRef(instanceref)) {
|
|
2925
|
+
continue;
|
|
2926
|
+
}
|
|
2927
|
+
#if PY_VERSION_HEX < 0x030D0000
|
|
2928
|
+
PyObject* instance = PyWeakref_GET_OBJECT(instanceref);
|
|
2929
|
+
if (instance == metaclass) continue;
|
|
2930
|
+
if (PyObject_IsInstance(instance, metaclass)) {
|
|
2931
|
+
return true;
|
|
2932
|
+
}
|
|
2933
|
+
#else
|
|
2934
|
+
PyObject* instance;
|
|
2935
|
+
if (PyWeakref_GetRef(instanceref, &instance) == 1) {
|
|
2936
|
+
if (instance == metaclass) {
|
|
2937
|
+
Py_DECREF(instance);
|
|
2938
|
+
continue;
|
|
2939
|
+
}
|
|
2940
|
+
if (PyObject_IsInstance(instance, metaclass)) {
|
|
2941
|
+
Py_DECREF(instance);
|
|
2942
|
+
return true;
|
|
2943
|
+
}
|
|
2944
|
+
Py_DECREF(instance);
|
|
2945
|
+
}
|
|
2946
|
+
#endif
|
|
2947
|
+
}
|
|
2948
|
+
return false;
|
|
2949
|
+
}
|
|
2950
|
+
|
|
3024
2951
|
static PyObject*
|
|
3025
|
-
|
|
2952
|
+
register_metaclass_head(PyObject* metaclass) noexcept
|
|
3026
2953
|
{
|
|
3027
2954
|
if (!PyType_Check(metaclass)) {
|
|
3028
2955
|
PyErr_SetString(PyExc_TypeError, "metaclass must be a type");
|
|
@@ -3032,6 +2959,18 @@ register_metaclass(PyObject* /*self*/, PyObject* metaclass) noexcept
|
|
|
3032
2959
|
PyErr_SetString(PyExc_TypeError, "metaclass must be a metatype");
|
|
3033
2960
|
return NULL;
|
|
3034
2961
|
}
|
|
2962
|
+
if (metaclass == (PyObject*)&PyType_Type) {
|
|
2963
|
+
PyErr_SetString(PyExc_ValueError, "cannot register type itself");
|
|
2964
|
+
return NULL;
|
|
2965
|
+
}
|
|
2966
|
+
if (need_analyse_type(metaclass)) {
|
|
2967
|
+
PyErr_SetString(PyExc_ValueError, "cannot register type that is the instance of 'PrivateAttrType' or registed type");
|
|
2968
|
+
return NULL;
|
|
2969
|
+
}
|
|
2970
|
+
if (is_class_of_registed_type(metaclass)) {
|
|
2971
|
+
PyErr_SetString(PyExc_ValueError, "cannot register type that is the class of registed type");
|
|
2972
|
+
return NULL;
|
|
2973
|
+
}
|
|
3035
2974
|
uintptr_t id = (uintptr_t)metaclass;
|
|
3036
2975
|
|
|
3037
2976
|
std::unique_lock lock(::AllData::all_register_new_metaclass_mutex);
|
|
@@ -3062,6 +3001,27 @@ register_metaclass(PyObject* /*self*/, PyObject* metaclass) noexcept
|
|
|
3062
3001
|
Py_RETURN_NONE;
|
|
3063
3002
|
}
|
|
3064
3003
|
|
|
3004
|
+
static PyObject*
|
|
3005
|
+
register_metaclass(PyObject* /*self*/, PyObject* metaclass) noexcept
|
|
3006
|
+
{
|
|
3007
|
+
if (!register_metaclass_head(metaclass)) return NULL;
|
|
3008
|
+
PyObject* subclasses = PyObject_CallMethod((PyObject*)&PyType_Type, "__subclasses__", "O", metaclass);
|
|
3009
|
+
if (!subclasses) {
|
|
3010
|
+
PyErr_Clear();
|
|
3011
|
+
Py_RETURN_NONE;
|
|
3012
|
+
}
|
|
3013
|
+
Py_ssize_t list_len = PyList_GET_SIZE(subclasses);
|
|
3014
|
+
for (Py_ssize_t i = 0; i < list_len; i++) {
|
|
3015
|
+
PyObject* subclass = PyList_GET_ITEM(subclasses, i);
|
|
3016
|
+
if (!register_metaclass(0, subclass)) {
|
|
3017
|
+
Py_DECREF(subclasses);
|
|
3018
|
+
return NULL;
|
|
3019
|
+
}
|
|
3020
|
+
}
|
|
3021
|
+
Py_DECREF(subclasses);
|
|
3022
|
+
Py_RETURN_NONE;
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3065
3025
|
static PyObject*
|
|
3066
3026
|
ensure_type_tp(PyObject* /*self*/, PyObject* type) noexcept
|
|
3067
3027
|
{
|
|
@@ -3144,8 +3104,16 @@ PrivateModule_dir(PyObject* self, PyObject* /*args*/) noexcept
|
|
|
3144
3104
|
return result;
|
|
3145
3105
|
}
|
|
3146
3106
|
|
|
3107
|
+
#define PrivateModule_GETATTRO_CASE(name) \
|
|
3108
|
+
do {\
|
|
3109
|
+
if (strcmp(name_cstr, #name) == 0) {\
|
|
3110
|
+
PyObject* attr = PrivateModule_get_##name(NULL, NULL);\
|
|
3111
|
+
return attr;\
|
|
3112
|
+
}\
|
|
3113
|
+
} while (0)
|
|
3114
|
+
|
|
3147
3115
|
static int
|
|
3148
|
-
PrivateModule_setattro(PyObject*
|
|
3116
|
+
PrivateModule_setattro(PyObject* self, PyObject* name, PyObject* value) noexcept
|
|
3149
3117
|
{
|
|
3150
3118
|
// if name is "__class__" it do nothing and return success
|
|
3151
3119
|
if (PyUnicode_Check(name)) {
|
|
@@ -3153,8 +3121,25 @@ PrivateModule_setattro(PyObject* cls, PyObject* name, PyObject* value) noexcept
|
|
|
3153
3121
|
if (name_cstr && strcmp(name_cstr, "__class__") == 0) {
|
|
3154
3122
|
return 0;
|
|
3155
3123
|
}
|
|
3124
|
+
static const char* unsetable_attrs[] = {
|
|
3125
|
+
"PrivateWrapProxy",
|
|
3126
|
+
"PrivateAttrType",
|
|
3127
|
+
"PrivateAttrBase",
|
|
3128
|
+
"prepare",
|
|
3129
|
+
"postprocess",
|
|
3130
|
+
"register_metaclass",
|
|
3131
|
+
"ensure_type",
|
|
3132
|
+
"ensure_metaclass"
|
|
3133
|
+
};
|
|
3134
|
+
const size_t num_attrs = sizeof(unsetable_attrs) / sizeof(unsetable_attrs[0]);
|
|
3135
|
+
for (size_t i = 0; i < num_attrs; ++i) {
|
|
3136
|
+
if (strcmp(name_cstr, unsetable_attrs[i]) == 0) {
|
|
3137
|
+
PyErr_Format(PyExc_AttributeError, "attribute '%s' of 'private_attribute_module' objects is not writable", name_cstr);
|
|
3138
|
+
return -1;
|
|
3139
|
+
}
|
|
3140
|
+
}
|
|
3156
3141
|
}
|
|
3157
|
-
return
|
|
3142
|
+
return PyModule_Type.tp_setattro(self, name, value);
|
|
3158
3143
|
}
|
|
3159
3144
|
|
|
3160
3145
|
static const char* prepare_and_postprocess_doc = R"(function for custom metaclass to create private attributes class.
|
|
@@ -3251,38 +3236,60 @@ static PyMethodDef PrivateModule_methods_def[] = {
|
|
|
3251
3236
|
{NULL} // Sentinel
|
|
3252
3237
|
};
|
|
3253
3238
|
|
|
3239
|
+
static PyObject*
|
|
3240
|
+
PrivateModule_getattro(PyObject* self, PyObject* name) noexcept
|
|
3241
|
+
{
|
|
3242
|
+
if (!PyUnicode_Check(name)) {
|
|
3243
|
+
PyErr_SetString(PyExc_TypeError, "attribute name must be a string");
|
|
3244
|
+
return NULL;
|
|
3245
|
+
}
|
|
3246
|
+
const char* name_cstr = PyUnicode_AsUTF8(name);
|
|
3247
|
+
if (!name_cstr) {
|
|
3248
|
+
return NULL;
|
|
3249
|
+
}
|
|
3250
|
+
PrivateModule_GETATTRO_CASE(PrivateWrapProxy);
|
|
3251
|
+
PrivateModule_GETATTRO_CASE(PrivateAttrType);
|
|
3252
|
+
PrivateModule_GETATTRO_CASE(PrivateAttrBase);
|
|
3253
|
+
PrivateModule_GETATTRO_CASE(prepare);
|
|
3254
|
+
PrivateModule_GETATTRO_CASE(postprocess);
|
|
3255
|
+
PrivateModule_GETATTRO_CASE(register_metaclass);
|
|
3256
|
+
PrivateModule_GETATTRO_CASE(ensure_type);
|
|
3257
|
+
PrivateModule_GETATTRO_CASE(ensure_metaclass);
|
|
3258
|
+
return PyModule_Type.tp_getattro(self, name);
|
|
3259
|
+
}
|
|
3260
|
+
|
|
3254
3261
|
static PyTypeObject PrivateModuleType = {
|
|
3255
3262
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
3256
|
-
"private_attribute_module", //tp_name
|
|
3257
|
-
PyModule_Type.tp_basicsize + 8,
|
|
3258
|
-
0,
|
|
3259
|
-
0,
|
|
3260
|
-
0,
|
|
3261
|
-
0,
|
|
3262
|
-
0,
|
|
3263
|
-
0,
|
|
3264
|
-
0,
|
|
3265
|
-
0,
|
|
3266
|
-
0,
|
|
3267
|
-
0,
|
|
3268
|
-
0,
|
|
3269
|
-
0,
|
|
3270
|
-
0,
|
|
3271
|
-
|
|
3272
|
-
(setattrofunc)PrivateModule_setattro,
|
|
3273
|
-
0,
|
|
3274
|
-
Py_TPFLAGS_DEFAULT,
|
|
3275
|
-
0,
|
|
3276
|
-
0,
|
|
3277
|
-
0,
|
|
3278
|
-
0,
|
|
3279
|
-
0,
|
|
3280
|
-
0,
|
|
3281
|
-
0,
|
|
3282
|
-
PrivateModule_methods_def,
|
|
3283
|
-
0,
|
|
3284
|
-
PrivateModule_getsetters,
|
|
3285
|
-
&PyModule_Type,
|
|
3263
|
+
"private_attribute.private_attribute_module", //tp_name
|
|
3264
|
+
PyModule_Type.tp_basicsize + 8, //tp_basicsize size of module object + 8 bytes for basicsize to avoid changing attribute '__class__'
|
|
3265
|
+
0, //tp_itemsize
|
|
3266
|
+
0, //tp_dealloc
|
|
3267
|
+
0, //tp_print
|
|
3268
|
+
0, //tp_getattr
|
|
3269
|
+
0, //tp_setattr
|
|
3270
|
+
0, //tp_compare
|
|
3271
|
+
0, //tp_repr
|
|
3272
|
+
0, //tp_as_number
|
|
3273
|
+
0, //tp_as_sequence
|
|
3274
|
+
0, //tp_as_mapping
|
|
3275
|
+
0, //tp_hash
|
|
3276
|
+
0, //tp_call
|
|
3277
|
+
0, //tp_str
|
|
3278
|
+
(getattrofunc)PrivateModule_getattro, //tp_getattro
|
|
3279
|
+
(setattrofunc)PrivateModule_setattro, //tp_setattro
|
|
3280
|
+
0, //tp_as_buffer
|
|
3281
|
+
Py_TPFLAGS_DEFAULT, //tp_flags
|
|
3282
|
+
0, //tp_doc
|
|
3283
|
+
0, //tp_traverse
|
|
3284
|
+
0, //tp_clear
|
|
3285
|
+
0, //tp_richcompare
|
|
3286
|
+
0, //tp_weaklistoffset
|
|
3287
|
+
0, //tp_iter
|
|
3288
|
+
0, //tp_iternext
|
|
3289
|
+
PrivateModule_methods_def, //tp_methods
|
|
3290
|
+
0, //tp_members
|
|
3291
|
+
PrivateModule_getsetters, //tp_getset
|
|
3292
|
+
&PyModule_Type, //tp_base
|
|
3286
3293
|
};
|
|
3287
3294
|
|
|
3288
3295
|
static const char* module_doc = R"(
|
{private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0/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:
|
|
3
|
+
Version: 2.0.0
|
|
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='
|
|
21
|
+
version='2.0.0',
|
|
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.',
|
|
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
|
{private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_class_private_attrs.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{private_attribute_cpp-1.4.11 → private_attribute_cpp-2.0.0}/tests/test_private_inheritance.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|