private-attribute-cpp 2.1.17__tar.gz → 2.1.19__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (24) hide show
  1. {private_attribute_cpp-2.1.17/private_attribute_cpp.egg-info → private_attribute_cpp-2.1.19}/PKG-INFO +1 -1
  2. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/private_attribute.cpp +384 -48
  3. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/private_attribute.pyi +13 -2
  4. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
  5. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/setup.py +1 -1
  6. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/LICENSE +0 -0
  7. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/MANIFEST.in +0 -0
  8. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/README.md +0 -0
  9. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/picosha2.h +0 -0
  10. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
  11. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  12. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  13. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  14. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/setup.cfg +0 -0
  15. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_attr_classify_owner.py +0 -0
  16. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_class_private_attrs.py +0 -0
  17. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_gc_collect.py +0 -0
  18. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_private_abc.py +0 -0
  19. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_private_attrs.py +0 -0
  20. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_private_func.py +0 -0
  21. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_private_inheritance.py +0 -0
  22. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_private_method.py +0 -0
  23. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_private_wrap.py +0 -0
  24. {private_attribute_cpp-2.1.17 → private_attribute_cpp-2.1.19}/tests/test_slots_cycle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.1.17
3
+ Version: 2.1.19
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
@@ -931,6 +931,270 @@ type_delattr(PyObject* typ, const std::string& attr_name) noexcept
931
931
  return 0;
932
932
  }
933
933
 
934
+ // list proxy
935
+ // privatewrap.funcs return this type after 2.1.19
936
+
937
+ typedef struct {
938
+ PyObject_HEAD
939
+ PyObject *list;
940
+ } listproxy;
941
+
942
+ static bool
943
+ listproxy_check(listproxy *obj) noexcept
944
+ {
945
+ if (!obj->list) {
946
+ PyErr_SetString(PyExc_RuntimeError, "listproxy object has no list");
947
+ return false;
948
+ }
949
+ if (!PyList_CheckExact(obj->list)) {
950
+ PyErr_Format(PyExc_TypeError, "listproxy object can only proxy list, not '%s'", Py_TYPE(obj->list)->tp_name);
951
+ return false;
952
+ }
953
+ return true;
954
+ }
955
+
956
+ static PyObject*
957
+ listproxy_copy(PyObject* self, PyObject* /*args*/) noexcept
958
+ {
959
+ listproxy* obj = (listproxy*)self;
960
+ if (!listproxy_check(obj)) {
961
+ return NULL;
962
+ }
963
+ return PySequence_List(obj->list);
964
+ }
965
+
966
+ static PyObject*
967
+ listproxy_count(PyObject* self, PyObject* value) noexcept
968
+ {
969
+ listproxy* obj = (listproxy*)self;
970
+ if (!listproxy_check(obj)) {
971
+ return NULL;
972
+ }
973
+ Py_ssize_t m = PySequence_Count(obj->list, value);
974
+ if (m < 0) {
975
+ return NULL;
976
+ }
977
+ PyObject* result = PyLong_FromLong(m);
978
+ return result;
979
+ }
980
+
981
+ static PyObject*
982
+ listproxy_index(PyObject* self, PyObject* args) noexcept
983
+ {
984
+ listproxy* obj = (listproxy*)self;
985
+ if (!listproxy_check(obj)) {
986
+ return NULL;
987
+ }
988
+ PyObject* method = PyObject_GetAttrString(obj->list, "index");
989
+ if (!method) {
990
+ return NULL;
991
+ }
992
+ PyObject* result = PyObject_Call(method, args, NULL);
993
+ Py_DECREF(method);
994
+ return result;
995
+ }
996
+
997
+ static Py_ssize_t
998
+ listproxy_length(PyObject* self) noexcept
999
+ {
1000
+ listproxy* obj = (listproxy*)self;
1001
+ if (!listproxy_check(obj)) {
1002
+ return -1;
1003
+ }
1004
+ return PyList_Size(obj->list);
1005
+ }
1006
+
1007
+ static PyObject*
1008
+ listproxy_iter(PyObject* self) noexcept
1009
+ {
1010
+ listproxy* obj = (listproxy*)self;
1011
+ if (!listproxy_check(obj)) {
1012
+ return NULL;
1013
+ }
1014
+ return PyObject_GetIter(obj->list);
1015
+ }
1016
+
1017
+ static PyObject*
1018
+ listproxy_item(PyObject* self, Py_ssize_t i) noexcept
1019
+ {
1020
+ listproxy* obj = (listproxy*)self;
1021
+ if (!listproxy_check(obj)) {
1022
+ return NULL;
1023
+ }
1024
+ Py_ssize_t size = PyList_Size(obj->list);
1025
+ if (i < 0) {
1026
+ i += size;
1027
+ }
1028
+ if (i < 0 || i >= size) {
1029
+ PyErr_SetString(PyExc_IndexError, "listproxy index out of range");
1030
+ return NULL;
1031
+ }
1032
+ PyObject* item = PyList_GetItem(obj->list, i);
1033
+ if (!item) {
1034
+ return NULL;
1035
+ }
1036
+ Py_INCREF(item);
1037
+ return item;
1038
+ }
1039
+
1040
+ static PyObject*
1041
+ listproxy_subscript(PyObject* self, PyObject* key) noexcept
1042
+ {
1043
+ listproxy* obj = (listproxy*)self;
1044
+ if (!listproxy_check(obj)) {
1045
+ return NULL;
1046
+ }
1047
+ return PyObject_GetItem(obj->list, key);
1048
+ }
1049
+
1050
+ static int
1051
+ listproxy_contains(PyObject* self, PyObject* value) noexcept
1052
+ {
1053
+ listproxy* obj = (listproxy*)self;
1054
+ if (!listproxy_check(obj)) {
1055
+ return -1;
1056
+ }
1057
+ return PySequence_Contains(obj->list, value);
1058
+ }
1059
+
1060
+ static PyObject*
1061
+ listproxy_repr(PyObject* self) noexcept
1062
+ {
1063
+ listproxy* obj = (listproxy*)self;
1064
+ if (!listproxy_check(obj)) {
1065
+ return NULL;
1066
+ }
1067
+ PyObject* inner = PyObject_Repr(obj->list);
1068
+ if (!inner) {
1069
+ return NULL;
1070
+ }
1071
+ PyObject* result = PyUnicode_FromFormat("listproxy(%U)", inner);
1072
+ Py_DECREF(inner);
1073
+ return result;
1074
+ }
1075
+
1076
+ static PyObject*
1077
+ listproxy_richcompare(PyObject* self, PyObject* other, int op) noexcept
1078
+ {
1079
+ listproxy* obj = (listproxy*)self;
1080
+ if (!listproxy_check(obj)) {
1081
+ return NULL;
1082
+ }
1083
+
1084
+ // If the counterpart is a genuine Python list, compare the underlying
1085
+ // list directly. Otherwise copy the counterpart into a real list first
1086
+ // (so that listproxy == listproxy and listproxy == tuple behave like a
1087
+ // list-to-list comparison), then compare.
1088
+ PyObject* self_list = obj->list;
1089
+ bool decref_self_list = false;
1090
+ if (!PyList_CheckExact(other)) {
1091
+ self_list = PySequence_List(obj->list);
1092
+ if (!self_list) {
1093
+ PyErr_Clear();
1094
+ Py_RETURN_NOTIMPLEMENTED;
1095
+ }
1096
+ decref_self_list = true;
1097
+ }
1098
+
1099
+ PyObject* result = PyObject_RichCompare(self_list, other, op);
1100
+ if (decref_self_list) {
1101
+ Py_DECREF(self_list);
1102
+ }
1103
+ return result;
1104
+ }
1105
+
1106
+ static void
1107
+ listproxy_dealloc(listproxy* self) noexcept
1108
+ {
1109
+ Py_XDECREF(self->list);
1110
+ Py_TYPE(self)->tp_free((PyObject*)self);
1111
+ }
1112
+
1113
+ static PySequenceMethods listproxy_as_sequence = {
1114
+ listproxy_length, // sq_length
1115
+ 0, // sq_concat
1116
+ 0, // sq_repeat
1117
+ listproxy_item, // sq_item
1118
+ 0, // was_sq_slice
1119
+ 0, // sq_ass_item
1120
+ 0, // was_sq_ass_slice
1121
+ listproxy_contains, // sq_contains
1122
+ 0, // sq_inplace_concat
1123
+ 0, // sq_inplace_repeat
1124
+ };
1125
+
1126
+ static PyMappingMethods listproxy_as_mapping = {
1127
+ listproxy_length, // mp_length
1128
+ listproxy_subscript, // mp_subscript
1129
+ 0, // mp_ass_subscript
1130
+ };
1131
+
1132
+ static PyMethodDef listproxy_methods[] = {
1133
+ {"copy", listproxy_copy, METH_NOARGS, "Return a copy of the proxied list."},
1134
+ {"count", listproxy_count, METH_O, "Return number of occurrences of value."},
1135
+ {"index", listproxy_index, METH_VARARGS, "Return first index of value."},
1136
+ {NULL, NULL, 0, NULL}
1137
+ };
1138
+
1139
+ static int
1140
+ listproxy_traverse(PyObject* self, visitproc visit, void* arg) noexcept
1141
+ {
1142
+ listproxy* obj = (listproxy*)self;
1143
+ Py_VISIT(obj->list);
1144
+ return 0;
1145
+ }
1146
+
1147
+ static int
1148
+ listproxy_clear(PyObject* self) noexcept
1149
+ {
1150
+ listproxy* obj = (listproxy*)self;
1151
+ Py_CLEAR(obj->list);
1152
+ return 0;
1153
+ }
1154
+
1155
+ static PyTypeObject listproxyType = {
1156
+ PyVarObject_HEAD_INIT(NULL, 0)
1157
+ "private_attribute.listproxy", // tp_name
1158
+ sizeof(listproxy), // tp_basicsize
1159
+ 0, // tp_itemsize
1160
+ (destructor)listproxy_dealloc, // tp_dealloc
1161
+ 0, // tp_print
1162
+ 0, // tp_getattr
1163
+ 0, // tp_setattr
1164
+ 0, // tp_reserved
1165
+ listproxy_repr, // tp_repr
1166
+ 0, // tp_as_number
1167
+ &listproxy_as_sequence, // tp_as_sequence
1168
+ &listproxy_as_mapping, // tp_as_mapping
1169
+ 0, // tp_hash
1170
+ 0, // tp_call
1171
+ 0, // tp_str
1172
+ 0, // tp_getattro
1173
+ 0, // tp_setattro
1174
+ 0, // tp_as_buffer
1175
+ Py_TPFLAGS_DEFAULT| Py_TPFLAGS_HAVE_GC, // tp_flags
1176
+ "A read-only proxy of a list.", // tp_doc
1177
+ listproxy_traverse, // tp_traverse
1178
+ listproxy_clear, // tp_clear
1179
+ listproxy_richcompare, // tp_richcompare
1180
+ 0, // tp_weaklistoffset
1181
+ listproxy_iter, // tp_iter
1182
+ 0, // tp_iternext
1183
+ listproxy_methods, // tp_methods
1184
+ };
1185
+
1186
+ static PyObject*
1187
+ listproxy_new(PyObject* list) noexcept
1188
+ {
1189
+ listproxy* obj = PyObject_GC_New(listproxy, &listproxyType);
1190
+ if (!obj) {
1191
+ return NULL;
1192
+ }
1193
+ obj->list = list;
1194
+ Py_INCREF(list);
1195
+ return (PyObject*)obj;
1196
+ }
1197
+
934
1198
  // ================================================================
935
1199
  // _PrivateWrap
936
1200
  // ================================================================
@@ -957,7 +1221,7 @@ PrivateWrap_funcs(PyObject *obj, void* /*closure*/) noexcept
957
1221
  Py_RETURN_NONE;
958
1222
  }
959
1223
 
960
- return PySequence_Tuple(((PrivateWrapObject*)obj)->func_list);
1224
+ return listproxy_new(((PrivateWrapObject*)obj)->func_list);
961
1225
  }
962
1226
 
963
1227
  static PyObject*
@@ -1120,41 +1384,67 @@ PrivateWrap_descrset(PyObject* obj, PyObject* name, PyObject* value) noexcept
1120
1384
  }
1121
1385
  }
1122
1386
 
1387
+ static int
1388
+ PrivateWrap_traverse(PyObject* obj, visitproc visit, void* arg) noexcept
1389
+ {
1390
+ PrivateWrapObject* self = (PrivateWrapObject*)obj;
1391
+ if (self->result) {
1392
+ Py_VISIT(self->result);
1393
+ }
1394
+ if (self->func_list) {
1395
+ Py_VISIT(self->func_list);
1396
+ }
1397
+ return 0;
1398
+ }
1399
+
1400
+ static int
1401
+ PrivateWrap_clear(PyObject* obj) noexcept
1402
+ {
1403
+ PrivateWrapObject* self = (PrivateWrapObject*)obj;
1404
+ if (self->result) {
1405
+ Py_CLEAR(self->result);
1406
+ }
1407
+ if (self->func_list) {
1408
+ Py_CLEAR(self->func_list);
1409
+ }
1410
+ return 0;
1411
+ }
1412
+
1123
1413
  static PyTypeObject PrivateWrapType = {
1124
1414
  PyVarObject_HEAD_INIT(NULL, 0)
1125
- "_PrivateWrap", // tp_name
1126
- sizeof(PrivateWrapObject), // tp_basicsize
1127
- 0, // tp_itemsize
1128
- (destructor)PrivateWrap_dealloc, // tp_dealloc
1129
- 0, // tp_print
1130
- 0, // tp_getattr
1131
- 0, // tp_setattr
1132
- 0, // tp_reserved
1133
- 0, // tp_repr
1134
- 0, // tp_as_number
1135
- 0, // tp_as_sequence
1136
- 0, // tp_as_mapping
1137
- 0, // tp_hash
1138
- (ternaryfunc)PrivateWrap_call, // tp_call
1139
- 0, // tp_str
1140
- PrivateWrap_getattro, // tp_getattro
1141
- 0, // tp_setattro
1142
- 0, // tp_as_buffer
1143
- Py_TPFLAGS_DEFAULT, // tp_flags
1144
- "private_attribute._PrivateWrap", // tp_doc
1145
- 0, // tp_traverse
1146
- 0, // tp_clear
1147
- 0, // tp_richcompare
1148
- 0, // tp_weaklistoffset
1149
- 0, // tp_iter
1150
- 0, // tp_iternext
1151
- 0, // tp_methods
1152
- PrivateWrap_members, // tp_members
1153
- PrivateWrap_getset, // tp_getset
1154
- 0, // tp_base
1155
- 0, // tp_dict
1156
- PrivateWrap_descrget, // tp_descr_get
1157
- PrivateWrap_descrset, // tp_descr_set
1415
+ "private_attribute._PrivateWrap", // tp_name
1416
+ sizeof(PrivateWrapObject), // tp_basicsize
1417
+ 0, // tp_itemsize
1418
+ (destructor)PrivateWrap_dealloc, // tp_dealloc
1419
+ 0, // tp_print
1420
+ 0, // tp_getattr
1421
+ 0, // tp_setattr
1422
+ 0, // tp_reserved
1423
+ 0, // tp_repr
1424
+ 0, // tp_as_number
1425
+ 0, // tp_as_sequence
1426
+ 0, // tp_as_mapping
1427
+ 0, // tp_hash
1428
+ (ternaryfunc)PrivateWrap_call, // tp_call
1429
+ 0, // tp_str
1430
+ PrivateWrap_getattro, // tp_getattro
1431
+ 0, // tp_setattro
1432
+ 0, // tp_as_buffer
1433
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, // tp_flags
1434
+ "private_attribute._PrivateWrap", // tp_doc
1435
+ PrivateWrap_traverse, // tp_traverse
1436
+ PrivateWrap_clear, // tp_clear
1437
+ 0, // tp_richcompare
1438
+ 0, // tp_weaklistoffset
1439
+ 0, // tp_iter
1440
+ 0, // tp_iternext
1441
+ 0, // tp_methods
1442
+ PrivateWrap_members, // tp_members
1443
+ PrivateWrap_getset, // tp_getset
1444
+ 0, // tp_base
1445
+ 0, // tp_dict
1446
+ PrivateWrap_descrget, // tp_descr_get
1447
+ PrivateWrap_descrset, // tp_descr_set
1158
1448
  };
1159
1449
 
1160
1450
  static PrivateWrapObject*
@@ -1171,7 +1461,7 @@ PrivateWrap_New(PyObject *decorator, PyObject *func, PyObject *list) noexcept
1171
1461
  }
1172
1462
 
1173
1463
  PrivateWrapObject *self =
1174
- PyObject_New(PrivateWrapObject, &PrivateWrapType);
1464
+ PyObject_GC_New(PrivateWrapObject, &PrivateWrapType);
1175
1465
  self->func_list = list;
1176
1466
  Py_INCREF(list);
1177
1467
 
@@ -1207,7 +1497,7 @@ static PyObject*
1207
1497
  PrivateWrapProxy_call(PrivateWrapProxyObject *self, PyObject *args, PyObject* /* kwgs */) noexcept
1208
1498
  {
1209
1499
  PyObject *func;
1210
- if (!PyArg_ParseTuple(args, "O", &func)) return NULL;
1500
+ if (!PyArg_ParseTuple(args, "O:private_attribute.PrivateWrapProxy.__call__", &func)) return NULL;
1211
1501
  if(PyObject_TypeCheck(func, &PrivateWrapType)) {
1212
1502
  return (PyObject*)PrivateWrap_New(
1213
1503
  self->decorator,
@@ -1262,6 +1552,22 @@ class MyClass(PrivateAttrBase):
1262
1552
  ```
1263
1553
  )";
1264
1554
 
1555
+ static int
1556
+ PrivateWrapProxy_traverse(PrivateWrapProxyObject *self, visitproc visit, void *arg) noexcept
1557
+ {
1558
+ Py_VISIT(self->decorator);
1559
+ Py_VISIT(self->func_list);
1560
+ return 0;
1561
+ }
1562
+
1563
+ static int
1564
+ PrivateWrapProxy_clear(PrivateWrapProxyObject *self) noexcept
1565
+ {
1566
+ Py_CLEAR(self->decorator);
1567
+ Py_CLEAR(self->func_list);
1568
+ return 0;
1569
+ }
1570
+
1265
1571
  static PyTypeObject PrivateWrapProxyType = {
1266
1572
  PyVarObject_HEAD_INIT(NULL, 0)
1267
1573
  "private_attribute.PrivateWrapProxy", // tp_name
@@ -1282,10 +1588,10 @@ static PyTypeObject PrivateWrapProxyType = {
1282
1588
  0, // tp_getattro
1283
1589
  0, // tp_setattro
1284
1590
  0, // tp_as_buffer
1285
- Py_TPFLAGS_DEFAULT, // tp_flags
1591
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,// tp_flags
1286
1592
  PrivateWrapProxy_doc, // tp_doc
1287
- 0, // tp_traverse
1288
- 0, // tp_clear
1593
+ (traverseproc)PrivateWrapProxy_traverse,// tp_traverse
1594
+ (inquiry)PrivateWrapProxy_clear, // tp_clear
1289
1595
  0, // tp_richcompare
1290
1596
  0, // tp_weaklistoffset
1291
1597
  0, // tp_iter
@@ -1310,7 +1616,7 @@ PrivateWrapProxy_New(PyTypeObject *type, PyObject *args, PyObject* /*kwds*/) noe
1310
1616
  PyObject *decorator;
1311
1617
  PyObject *orig = NULL;
1312
1618
 
1313
- if (!PyArg_ParseTuple(args, "O|O", &decorator, &orig))
1619
+ if (!PyArg_ParseTuple(args, "O|O:private_attribute.PrivateWrapProxy", &decorator, &orig))
1314
1620
  return NULL;
1315
1621
 
1316
1622
  self = (PrivateWrapProxyObject*)type->tp_alloc(type, 0);
@@ -2522,7 +2828,7 @@ need_analyse_type(PyObject* type) noexcept
2522
2828
  }
2523
2829
 
2524
2830
  static bool
2525
- PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationData& data) noexcept
2831
+ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationData& data, const std::string& func_name = "") noexcept
2526
2832
  {
2527
2833
  static const char* invalid_name[] = {"__private_attrs__", "__slots__", "__getattribute__", "__getattr__", "__init__",
2528
2834
  "__setattr__", "__delattr__", "__name__", "__module__", "__doc__", "__getstate__", "__setstate__",
@@ -2534,7 +2840,11 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
2534
2840
  }
2535
2841
 
2536
2842
  // only parse name, bases, attrs
2537
- if (!PyArg_ParseTuple(args, "OOO", &data.name, &data.bases, &data.attrs)) {
2843
+ std::string parse = "OOO";
2844
+ if (func_name.length() > 0) {
2845
+ parse += ":" + func_name;
2846
+ }
2847
+ if (!PyArg_ParseTuple(args, parse.c_str(), &data.name, &data.bases, &data.attrs)) {
2538
2848
  return false;
2539
2849
  }
2540
2850
  Py_INCREF(data.name);
@@ -3069,7 +3379,7 @@ PrivateAttrType_new(PyTypeObject* type, PyObject* args, PyObject* kwds) noexcept
3069
3379
  PrivateAttrCreationData data;
3070
3380
  PyObject* new_type = nullptr;
3071
3381
 
3072
- if (!PrivateAttrType_preprocess(args, kwds, data)) {
3382
+ if (!PrivateAttrType_preprocess(args, kwds, data, "private_attribute.PrivateAttrType")) {
3073
3383
  return nullptr;
3074
3384
  }
3075
3385
 
@@ -3705,6 +4015,31 @@ static PyMethodDef PrivateTempObject_methods[] = {
3705
4015
  {NULL}
3706
4016
  };
3707
4017
 
4018
+ static int
4019
+ PrivateTempObject_traverse(PyObject* self, visitproc visit, void* arg) noexcept
4020
+ {
4021
+ PrivateTempObject* tmp = (PrivateTempObject*)self;
4022
+ if (tmp->tmp) {
4023
+ PrivateAttrCreationData* data = tmp->tmp;
4024
+ if (!data->cleared) {
4025
+ Py_VISIT(data->attrs_copy);
4026
+ Py_VISIT(data->base_kwds);
4027
+ Py_VISIT(data->attrs);
4028
+ }
4029
+ }
4030
+ return 0;
4031
+ }
4032
+
4033
+ static int
4034
+ PrivateTempObject_clear(PyObject* self) noexcept
4035
+ {
4036
+ PrivateTempObject* tmp = (PrivateTempObject*)self;
4037
+ if (tmp->tmp && !tmp->tmp->cleared) {
4038
+ tmp->tmp->clear();
4039
+ }
4040
+ return 0;
4041
+ }
4042
+
3708
4043
  static PyTypeObject PrivateTempType = {
3709
4044
  PyVarObject_HEAD_INIT(NULL, 0)
3710
4045
  "private_attribute._PrivateTemp", // tp_name
@@ -3725,10 +4060,10 @@ static PyTypeObject PrivateTempType = {
3725
4060
  0, //tp_getattro
3726
4061
  0, //tp_setattro
3727
4062
  0, //tp_as_buffer
3728
- Py_TPFLAGS_DEFAULT, //tp_flags
4063
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, //tp_flags
3729
4064
  0, //tp_doc
3730
- 0, //tp_traverse
3731
- 0, //tp_clear
4065
+ PrivateTempObject_traverse, //tp_traverse
4066
+ PrivateTempObject_clear, //tp_clear
3732
4067
  0, //tp_richcompare
3733
4068
  0, //tp_weaklistoffset
3734
4069
  0, //tp_iter
@@ -3742,12 +4077,12 @@ static PyObject*
3742
4077
  prepare_for_PrivateAttr(PyObject* /*self*/, PyObject* args, PyObject* kwargs) noexcept
3743
4078
  {
3744
4079
  PrivateAttrCreationData* tmp_data = new PrivateAttrCreationData();
3745
- if (!PrivateAttrType_preprocess(args, kwargs, *tmp_data)) {
4080
+ if (!PrivateAttrType_preprocess(args, kwargs, *tmp_data, "private_attribute.prepare")) {
3746
4081
  tmp_data->clear();
3747
4082
  delete tmp_data;
3748
4083
  return NULL;
3749
4084
  }
3750
- PrivateTempObject* tmp = PyObject_New(PrivateTempObject, &PrivateTempType);
4085
+ PrivateTempObject* tmp = PyObject_GC_New(PrivateTempObject, &PrivateTempType);
3751
4086
  if (!tmp) {
3752
4087
  tmp_data->clear();
3753
4088
  delete tmp_data;
@@ -4425,6 +4760,7 @@ PyInit_private_attribute(void) noexcept
4425
4760
  }
4426
4761
  if (init_all_slots() <0 ||
4427
4762
  atexit_register_clean_func() < 0 ||
4763
+ PyType_Ready(&listproxyType) < 0 ||
4428
4764
  PyType_Ready(&PrivateWrapType) < 0 ||
4429
4765
  PyType_Ready(&PrivateWrapProxyType) < 0 ||
4430
4766
  PyType_Ready(&PrivateAttrType) < 0 ||
@@ -15,8 +15,9 @@ class MyClass(PrivateAttrBase):
15
15
  return self._private_attr1
16
16
  ```
17
17
  """
18
- from typing import Any, TypeVar, Callable, TypedDict, Sequence, Generic, Optional, cast
18
+ from typing import Any, TypeVar, Callable, TypedDict, Sequence, Generic, Optional, cast, Iterator
19
19
  from types import FunctionType
20
+ import sys
20
21
 
21
22
  # define the dict that must have a key "__private_attrs__" and value must be the sequence of strings
22
23
  class _PrivateAttrDict(TypedDict):
@@ -24,6 +25,16 @@ class _PrivateAttrDict(TypedDict):
24
25
 
25
26
  _T = TypeVar('_T')
26
27
 
28
+ class listproxy(Generic[_T]):
29
+ "a read-only proxy of a list"
30
+ def copy(self) -> list[_T]: ...
31
+ def count(self, value: Any, /) -> int: ...
32
+ def index(self, value: Any, start: int = 0, stop: int = sys.maxsize, /) -> int: ...
33
+ def __len__(self) -> int: ...
34
+ def __iter__(self) -> Iterator[_T]: ...
35
+ def __getitem__(self, key: int | slice) -> Any: ...
36
+ def __contains__(self, value: object) -> bool: ...
37
+
27
38
  class _PrivateWrap(Generic[_T]):
28
39
  @property
29
40
  def result(self) -> _T:
@@ -31,7 +42,7 @@ class _PrivateWrap(Generic[_T]):
31
42
  ...
32
43
 
33
44
  @property
34
- def funcs(self) -> tuple[FunctionType]:
45
+ def funcs(self) -> listproxy[FunctionType]:
35
46
  "the original functions"
36
47
  ...
37
48
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.1.17
3
+ Version: 2.1.19
4
4
  Summary: A Python package that provides a way to define private attributes in C++ implementation.
5
5
  Home-page: https://github.com/Locked-chess-official/private_attribute_cpp
6
6
  Author: HuangHaoHua
@@ -24,7 +24,7 @@ readme = open('README.md').read()
24
24
 
25
25
  setup(
26
26
  name='private_attribute_cpp',
27
- version='2.1.17',
27
+ version='2.1.19',
28
28
  author="HuangHaoHua",
29
29
  author_email="13140752715@example.com",
30
30
  description='A Python package that provides a way to define private attributes in C++ implementation.',