private-attribute-cpp 1.3.8__tar.gz → 1.4.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.3.8/private_attribute_cpp.egg-info → private_attribute_cpp-1.4.0}/PKG-INFO +2 -1
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/README.md +1 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/private_attribute.cpp +157 -68
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0/private_attribute_cpp.egg-info}/PKG-INFO +2 -1
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/setup.py +1 -1
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/LICENSE +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/MANIFEST.in +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/picosha2.h +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/private_attribute.pyi +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/private_attribute_cpp.egg-info/top_level.txt +0 -0
- {private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.0}/setup.cfg +0 -0
{private_attribute_cpp-1.3.8/private_attribute_cpp.egg-info → private_attribute_cpp-1.4.0}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: private_attribute_cpp
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.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
|
|
@@ -250,6 +250,7 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
|
|
|
250
250
|
- One class defined in another class cannot use another class's private attribute.
|
|
251
251
|
- One parent class defined an attribute which not in `__private_attrs__` or not a `PrivateAttrType` instance, the child class shouldn't contain the attribute in its `__private_attrs__`.
|
|
252
252
|
- CPython may change "tp_getattro", "tp_setattro" and so on when you change the attribute "\_\_getattribute\_\_", "\_\_setattr\_\_" and so on. If you are fear about it, you can use `ensure_type` to reset those tp slots. For the other metaclasses, you can use `ensure_metaclass` to reset those tp slots. Also, don't set those methods on these classes in your code.
|
|
253
|
+
- `private_attribute.register_metaclass` must be called with the metaclass which support weakref.
|
|
253
254
|
|
|
254
255
|
## License
|
|
255
256
|
|
|
@@ -231,6 +231,7 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
|
|
|
231
231
|
- One class defined in another class cannot use another class's private attribute.
|
|
232
232
|
- One parent class defined an attribute which not in `__private_attrs__` or not a `PrivateAttrType` instance, the child class shouldn't contain the attribute in its `__private_attrs__`.
|
|
233
233
|
- CPython may change "tp_getattro", "tp_setattro" and so on when you change the attribute "\_\_getattribute\_\_", "\_\_setattr\_\_" and so on. If you are fear about it, you can use `ensure_type` to reset those tp slots. For the other metaclasses, you can use `ensure_metaclass` to reset those tp slots. Also, don't set those methods on these classes in your code.
|
|
234
|
+
- `private_attribute.register_metaclass` must be called with the metaclass which support weakref.
|
|
234
235
|
|
|
235
236
|
## License
|
|
236
237
|
|
|
@@ -140,6 +140,7 @@ namespace {
|
|
|
140
140
|
static std::shared_mutex all_register_new_metaclass_mutex;
|
|
141
141
|
static std::vector<PyTypeObject*> all_register_new_metaclass;
|
|
142
142
|
static std::unordered_set<uintptr_t> all_register_new_metaclass_id;
|
|
143
|
+
static std::unordered_map<uintptr_t, PyObject*> all_register_type_weak_ref;
|
|
143
144
|
};
|
|
144
145
|
};
|
|
145
146
|
|
|
@@ -155,13 +156,11 @@ struct FinalObject
|
|
|
155
156
|
int status = 0;
|
|
156
157
|
FinalObject(PyObject* result)
|
|
157
158
|
: result(result) {
|
|
158
|
-
|
|
159
|
+
Py_XINCREF(result);
|
|
159
160
|
}
|
|
160
161
|
FinalObject(int status): status(status) {}
|
|
161
162
|
~FinalObject() {
|
|
162
|
-
|
|
163
|
-
Py_DECREF(result);
|
|
164
|
-
}
|
|
163
|
+
Py_XDECREF(result);
|
|
165
164
|
}
|
|
166
165
|
};
|
|
167
166
|
|
|
@@ -185,18 +184,39 @@ is_class_code(uintptr_t typ_id, PyCodeObject* code)
|
|
|
185
184
|
}
|
|
186
185
|
|
|
187
186
|
static bool
|
|
188
|
-
|
|
187
|
+
is_type_private(uintptr_t typ_id, std::string name)
|
|
189
188
|
{
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
189
|
+
if (::AllData::all_type_attr_set.find(typ_id) != ::AllData::all_type_attr_set.end()){
|
|
190
|
+
auto& attr_set = ::AllData::all_type_attr_set[typ_id];
|
|
191
|
+
TwoStringTuple key = get_string_hash_tuple2(name);
|
|
192
|
+
if (attr_set.find(key) != attr_set.end()){
|
|
193
|
+
return true;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
return false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
static bool
|
|
200
|
+
attr_classify(uintptr_t typ_id, std::string name, PyCodeObject* code)
|
|
201
|
+
{
|
|
202
|
+
if (is_class_code(typ_id, code)) {
|
|
203
|
+
return true;
|
|
204
|
+
}
|
|
205
|
+
if (is_type_private(typ_id, name)) {
|
|
206
|
+
return false;
|
|
207
|
+
}
|
|
208
|
+
if (::AllData::all_type_parent_id.find(typ_id) != ::AllData::all_type_parent_id.end()) {
|
|
209
|
+
std::vector<uintptr_t> parent_ids = ::AllData::all_type_parent_id[typ_id];
|
|
210
|
+
for (auto& parent_id : parent_ids) {
|
|
211
|
+
if (is_class_code(parent_id, code)) {
|
|
195
212
|
return true;
|
|
196
213
|
}
|
|
214
|
+
if (is_type_private(parent_id, name)) {
|
|
215
|
+
return false;
|
|
216
|
+
}
|
|
197
217
|
}
|
|
198
218
|
}
|
|
199
|
-
return
|
|
219
|
+
return true;
|
|
200
220
|
}
|
|
201
221
|
|
|
202
222
|
static std::string
|
|
@@ -404,6 +424,9 @@ get_name_from_tp_name(PyTypeObject* typ)
|
|
|
404
424
|
return final_name;
|
|
405
425
|
}
|
|
406
426
|
|
|
427
|
+
static void ensure_tp(PyTypeObject* type_instance);
|
|
428
|
+
static void ensure_subclass_tp(PyTypeObject* type_instance);
|
|
429
|
+
|
|
407
430
|
static PyObject*
|
|
408
431
|
id_getattr(std::string attr_name, PyObject* obj, PyObject* typ)
|
|
409
432
|
{
|
|
@@ -451,21 +474,23 @@ id_getattr(std::string attr_name, PyObject* obj, PyObject* typ)
|
|
|
451
474
|
if (final_object.status != -1) {
|
|
452
475
|
result = final_object.result;
|
|
453
476
|
}
|
|
454
|
-
|
|
477
|
+
PyTypeObject* result_typ = nullptr;
|
|
455
478
|
|
|
456
479
|
if (result) {
|
|
457
|
-
result_typ =
|
|
480
|
+
result_typ = Py_TYPE(result);
|
|
458
481
|
if (!result_typ) return NULL;
|
|
459
482
|
}
|
|
460
|
-
|
|
461
|
-
|
|
483
|
+
bool has_get = false;
|
|
484
|
+
bool has_set = false;
|
|
462
485
|
if (result_typ) {
|
|
463
|
-
has_get =
|
|
464
|
-
has_set =
|
|
486
|
+
has_get = result_typ->tp_descr_get != NULL;
|
|
487
|
+
has_set = result_typ->tp_descr_set != NULL;
|
|
465
488
|
}
|
|
466
489
|
if (has_get && has_set) {
|
|
467
|
-
PyObject*
|
|
468
|
-
|
|
490
|
+
PyObject* final_result = result_typ->tp_descr_get(result, obj, typ);
|
|
491
|
+
ensure_tp((PyTypeObject*)typ);
|
|
492
|
+
ensure_subclass_tp((PyTypeObject*)typ);
|
|
493
|
+
return final_result;
|
|
469
494
|
}
|
|
470
495
|
|
|
471
496
|
{
|
|
@@ -477,10 +502,12 @@ id_getattr(std::string attr_name, PyObject* obj, PyObject* typ)
|
|
|
477
502
|
return NULL;
|
|
478
503
|
}
|
|
479
504
|
// if obj is a type, call result.__get__(None, obj)
|
|
480
|
-
if (PyType_Check(obj)
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
505
|
+
if (PyType_Check(obj)) {
|
|
506
|
+
PyTypeObject* obj_type = Py_TYPE(python_obj);
|
|
507
|
+
if (obj_type->tp_descr_get != NULL) {
|
|
508
|
+
lock.unlock();
|
|
509
|
+
return obj_type->tp_descr_get(python_obj, Py_None, obj);
|
|
510
|
+
}
|
|
484
511
|
}
|
|
485
512
|
Py_XINCREF(python_obj);
|
|
486
513
|
return python_obj;
|
|
@@ -488,8 +515,10 @@ id_getattr(std::string attr_name, PyObject* obj, PyObject* typ)
|
|
|
488
515
|
}
|
|
489
516
|
|
|
490
517
|
if (has_get) {
|
|
491
|
-
PyObject*
|
|
492
|
-
|
|
518
|
+
PyObject* final_result = result_typ->tp_descr_get(result, obj, typ);
|
|
519
|
+
ensure_tp((PyTypeObject*)typ);
|
|
520
|
+
ensure_subclass_tp((PyTypeObject*)typ);
|
|
521
|
+
return final_result;
|
|
493
522
|
}
|
|
494
523
|
if (result) {
|
|
495
524
|
Py_INCREF(result);
|
|
@@ -518,9 +547,12 @@ type_getattr(PyObject* typ, std::string attr_name)
|
|
|
518
547
|
result = final_object.result;
|
|
519
548
|
}
|
|
520
549
|
if (result) {
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
550
|
+
PyTypeObject* type = Py_TYPE(result);
|
|
551
|
+
if (type->tp_descr_get != NULL) {
|
|
552
|
+
PyObject* final_result = type->tp_descr_get(result, Py_None, (PyObject*)type);
|
|
553
|
+
ensure_tp((PyTypeObject*)type);
|
|
554
|
+
ensure_subclass_tp((PyTypeObject*)type);
|
|
555
|
+
return final_result;
|
|
524
556
|
} else {
|
|
525
557
|
Py_INCREF(result);
|
|
526
558
|
return result;
|
|
@@ -531,7 +563,7 @@ type_getattr(PyObject* typ, std::string attr_name)
|
|
|
531
563
|
return NULL;
|
|
532
564
|
}
|
|
533
565
|
std::string string_type_name = type_name;
|
|
534
|
-
std::string message = "type '" + string_type_name + "' has no attribute '" + attr_name + "'";
|
|
566
|
+
std::string message = "type object '" + string_type_name + "' has no attribute '" + attr_name + "'";
|
|
535
567
|
PyErr_SetString(PyExc_AttributeError, message.c_str());
|
|
536
568
|
return NULL;
|
|
537
569
|
}
|
|
@@ -584,13 +616,14 @@ id_setattr(std::string attr_name, PyObject* obj, PyObject* typ, PyObject* value)
|
|
|
584
616
|
if (final_object.status != -1) {
|
|
585
617
|
result = final_object.result;
|
|
586
618
|
}
|
|
587
|
-
if (result
|
|
588
|
-
|
|
589
|
-
if (
|
|
590
|
-
|
|
619
|
+
if (result) {
|
|
620
|
+
PyTypeObject* type = Py_TYPE(result);
|
|
621
|
+
if (type->tp_descr_set != NULL) {
|
|
622
|
+
if (type->tp_descr_set(result, obj, value) < 0) {
|
|
623
|
+
return -1;
|
|
624
|
+
}
|
|
625
|
+
return 0;
|
|
591
626
|
}
|
|
592
|
-
Py_DECREF(python_result);
|
|
593
|
-
return 0;
|
|
594
627
|
}
|
|
595
628
|
|
|
596
629
|
// second: set attribute on obj
|
|
@@ -727,13 +760,14 @@ id_delattr(std::string attr_name, PyObject* obj, PyObject* typ)
|
|
|
727
760
|
if (final_object.status == 0) {
|
|
728
761
|
result = final_object.result;
|
|
729
762
|
}
|
|
730
|
-
if (result
|
|
731
|
-
|
|
732
|
-
if (
|
|
733
|
-
|
|
763
|
+
if (result) {
|
|
764
|
+
PyTypeObject* type = Py_TYPE(result);
|
|
765
|
+
if (type->tp_descr_set != NULL) {
|
|
766
|
+
if (type->tp_descr_set(result, result, NULL) < 0) {
|
|
767
|
+
return -1;
|
|
768
|
+
}
|
|
769
|
+
return 0;
|
|
734
770
|
}
|
|
735
|
-
Py_XDECREF(delete_result);
|
|
736
|
-
return 0;
|
|
737
771
|
}
|
|
738
772
|
// second: delete attribute on obj
|
|
739
773
|
{
|
|
@@ -797,7 +831,7 @@ type_delattr(PyObject* typ, std::string attr_name)
|
|
|
797
831
|
return -1;
|
|
798
832
|
}
|
|
799
833
|
std::string string_type_name = type_name;
|
|
800
|
-
std::string message = "type '" + string_type_name + "' has no attribute '" + attr_name + "'";
|
|
834
|
+
std::string message = "type object '" + string_type_name + "' has no attribute '" + attr_name + "'";
|
|
801
835
|
PyErr_SetString(PyExc_AttributeError, message.c_str());
|
|
802
836
|
return -1;
|
|
803
837
|
}
|
|
@@ -825,7 +859,7 @@ type_delattr(PyObject* typ, std::string attr_name)
|
|
|
825
859
|
return -1;
|
|
826
860
|
}
|
|
827
861
|
std::string string_type_name = type_name;
|
|
828
|
-
std::string message = "type '" + string_type_name + "' has no attribute '" + attr_name + "'";
|
|
862
|
+
std::string message = "type object '" + string_type_name + "' has no attribute '" + attr_name + "'";
|
|
829
863
|
PyErr_SetString(PyExc_AttributeError, message.c_str());
|
|
830
864
|
return -1;
|
|
831
865
|
}
|
|
@@ -1210,8 +1244,6 @@ typedef struct {
|
|
|
1210
1244
|
} PrivateAttrTypeObject;
|
|
1211
1245
|
|
|
1212
1246
|
static void PrivateAttr_object_init_private_dict(uintptr_t obj_id, uintptr_t type_id);
|
|
1213
|
-
static void ensure_tp(PyTypeObject* type_instance);
|
|
1214
|
-
static void ensure_subclass_tp(PyTypeObject* type_instance);
|
|
1215
1247
|
static int PrivateAttr_tp_setattro(PyObject* self, PyObject* name, PyObject* value);
|
|
1216
1248
|
static void PrivateAttr_tp_finalize(PyObject* self);
|
|
1217
1249
|
|
|
@@ -1224,7 +1256,7 @@ PrivateAttr_tp_getattro(PyObject* self, PyObject* name)
|
|
|
1224
1256
|
std::string name_str = PyUnicode_AsUTF8(name);
|
|
1225
1257
|
auto code = get_now_code();
|
|
1226
1258
|
if (type_private_attr(type_id, name_str)) {
|
|
1227
|
-
if (!code ||
|
|
1259
|
+
if (!code || !attr_classify(type_id, name_str, code)){
|
|
1228
1260
|
Py_XDECREF(code);
|
|
1229
1261
|
PyErr_SetString(PyExc_AttributeError, "private attribute");
|
|
1230
1262
|
return NULL;
|
|
@@ -1256,7 +1288,7 @@ PrivateAttr_tp_setattro(PyObject* self, PyObject* name, PyObject* value)
|
|
|
1256
1288
|
std::string name_str(c_name);
|
|
1257
1289
|
auto code = get_now_code();
|
|
1258
1290
|
if (type_private_attr(typ_id, name_str)) {
|
|
1259
|
-
if (!code ||
|
|
1291
|
+
if (!code || !attr_classify(typ_id, name_str, code)){
|
|
1260
1292
|
PyErr_SetString(PyExc_AttributeError, "private attribute");
|
|
1261
1293
|
Py_XDECREF(code);
|
|
1262
1294
|
return -1;
|
|
@@ -1765,10 +1797,25 @@ need_analyse_type(PyObject* type)
|
|
|
1765
1797
|
return true;
|
|
1766
1798
|
}
|
|
1767
1799
|
std::shared_lock lock(::AllData::all_register_new_metaclass_mutex);
|
|
1768
|
-
for (auto
|
|
1769
|
-
if (
|
|
1800
|
+
for (auto& [id, metaclassref]: ::AllData::all_register_type_weak_ref){
|
|
1801
|
+
if (!PyWeakref_CheckRef(metaclassref)) {
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
#if PY_VERSION_HEX < 0x030D0000
|
|
1805
|
+
PyObject* metaclass = PyWeakref_GET_OBJECT(metaclassref);
|
|
1806
|
+
if (metaclass == (PyObject*)Py_TYPE(type)) {
|
|
1770
1807
|
return true;
|
|
1771
1808
|
}
|
|
1809
|
+
#else
|
|
1810
|
+
PyObject* metaclass;
|
|
1811
|
+
if (PyWeakref_GetRef(metaclassref, &metaclass) == 1) {
|
|
1812
|
+
if (PyObject_IsInstance(type, metaclass)) {
|
|
1813
|
+
Py_DECREF(metaclass);
|
|
1814
|
+
return true;
|
|
1815
|
+
}
|
|
1816
|
+
Py_DECREF(metaclass);
|
|
1817
|
+
}
|
|
1818
|
+
#endif
|
|
1772
1819
|
}
|
|
1773
1820
|
return false;
|
|
1774
1821
|
}
|
|
@@ -2250,7 +2297,7 @@ ensure_subclass_tp(PyTypeObject* type_instance)
|
|
|
2250
2297
|
ensure_tp((PyTypeObject*)subclass);
|
|
2251
2298
|
#else
|
|
2252
2299
|
PyObject* subclass;
|
|
2253
|
-
if (PyWeakref_GetRef(value, (PyObject**)&subclass)
|
|
2300
|
+
if (PyWeakref_GetRef(value, (PyObject**)&subclass) == 0) {
|
|
2254
2301
|
continue;
|
|
2255
2302
|
}
|
|
2256
2303
|
if (!subclass || !PyType_Check(subclass)) {
|
|
@@ -2414,7 +2461,7 @@ PrivateAttrType_getattr(PyObject* cls, PyObject* name)
|
|
|
2414
2461
|
std::string name_str = PyUnicode_AsUTF8(name);
|
|
2415
2462
|
PyCodeObject* now_code = get_now_code();
|
|
2416
2463
|
if (type_private_attr(typ_id, name_str)) {
|
|
2417
|
-
if (!now_code ||
|
|
2464
|
+
if (!now_code || !attr_classify(typ_id, name_str, now_code)) {
|
|
2418
2465
|
PyErr_SetString(PyExc_AttributeError, "private attribute");
|
|
2419
2466
|
Py_XDECREF(now_code);
|
|
2420
2467
|
return NULL;
|
|
@@ -2585,7 +2632,7 @@ PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value)
|
|
|
2585
2632
|
}
|
|
2586
2633
|
PyCodeObject* now_code = get_now_code();
|
|
2587
2634
|
if (type_private_attr(typ_id, name_str)) {
|
|
2588
|
-
if (!now_code ||
|
|
2635
|
+
if (!now_code || !attr_classify(typ_id, name_str, now_code)) {
|
|
2589
2636
|
PyErr_SetString(PyExc_AttributeError, "private attribute");
|
|
2590
2637
|
Py_XDECREF(now_code);
|
|
2591
2638
|
return -1;
|
|
@@ -2920,6 +2967,34 @@ register_finalize(PyObject* cls)
|
|
|
2920
2967
|
PrivateAttrType_finalize(cls);
|
|
2921
2968
|
}
|
|
2922
2969
|
|
|
2970
|
+
|
|
2971
|
+
static PyObject*
|
|
2972
|
+
metaclass_weakref_callback(PyObject* self, PyObject* /*weakref*/)
|
|
2973
|
+
{
|
|
2974
|
+
void* pointer = PyCapsule_GetPointer(self, "metaclass_id");
|
|
2975
|
+
if (!pointer) {
|
|
2976
|
+
Py_RETURN_NONE;
|
|
2977
|
+
}
|
|
2978
|
+
uintptr_t id = (uintptr_t)pointer;
|
|
2979
|
+
|
|
2980
|
+
std::unique_lock lock(::AllData::all_register_new_metaclass_mutex);
|
|
2981
|
+
|
|
2982
|
+
auto it = ::AllData::all_register_type_weak_ref.find(id);
|
|
2983
|
+
if (it != ::AllData::all_register_type_weak_ref.end()) {
|
|
2984
|
+
Py_DECREF(it->second);
|
|
2985
|
+
::AllData::all_register_type_weak_ref.erase(it);
|
|
2986
|
+
}
|
|
2987
|
+
|
|
2988
|
+
Py_RETURN_NONE;
|
|
2989
|
+
}
|
|
2990
|
+
|
|
2991
|
+
static PyMethodDef weakref_callback_def = {
|
|
2992
|
+
"metaclass_weakref_callback",
|
|
2993
|
+
(PyCFunction)metaclass_weakref_callback,
|
|
2994
|
+
METH_O,
|
|
2995
|
+
NULL
|
|
2996
|
+
};
|
|
2997
|
+
|
|
2923
2998
|
static PyObject*
|
|
2924
2999
|
register_metaclass(PyObject* /*self*/, PyObject* metaclass)
|
|
2925
3000
|
{
|
|
@@ -2931,12 +3006,30 @@ register_metaclass(PyObject* /*self*/, PyObject* metaclass)
|
|
|
2931
3006
|
PyErr_SetString(PyExc_TypeError, "metaclass must be a metatype");
|
|
2932
3007
|
return NULL;
|
|
2933
3008
|
}
|
|
2934
|
-
Py_INCREF(metaclass);
|
|
2935
3009
|
uintptr_t id = (uintptr_t)metaclass;
|
|
3010
|
+
|
|
2936
3011
|
std::unique_lock lock(::AllData::all_register_new_metaclass_mutex);
|
|
2937
|
-
if (::AllData::
|
|
2938
|
-
|
|
2939
|
-
|
|
3012
|
+
if (::AllData::all_register_type_weak_ref.find(id) != ::AllData::all_register_type_weak_ref.end()) {
|
|
3013
|
+
Py_RETURN_NONE;
|
|
3014
|
+
}
|
|
3015
|
+
|
|
3016
|
+
PyObject* capsule = PyCapsule_New((void*)metaclass, "metaclass_id", NULL);
|
|
3017
|
+
if (!capsule) {
|
|
3018
|
+
return NULL;
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
PyObject* callback = PyCFunction_New(&weakref_callback_def, capsule);
|
|
3022
|
+
if (!callback) {
|
|
3023
|
+
Py_DECREF(capsule);
|
|
3024
|
+
return NULL;
|
|
3025
|
+
}
|
|
3026
|
+
PyObject* ref = PyWeakref_NewRef(metaclass, callback);
|
|
3027
|
+
if (!ref) {
|
|
3028
|
+
Py_DECREF(callback);
|
|
3029
|
+
Py_DECREF(capsule);
|
|
3030
|
+
return NULL;
|
|
3031
|
+
}
|
|
3032
|
+
::AllData::all_register_type_weak_ref[id] = ref;
|
|
2940
3033
|
((PyTypeObject*)metaclass)->tp_getattro = PrivateAttrType_getattr;
|
|
2941
3034
|
((PyTypeObject*)metaclass)->tp_setattro = PrivateAttrType_setattr;
|
|
2942
3035
|
((PyTypeObject*)metaclass)->tp_finalize = register_finalize;
|
|
@@ -2962,7 +3055,7 @@ static PyObject*
|
|
|
2962
3055
|
ensure_metaclass_tp(PyObject* /*self*/, PyObject* metaclass)
|
|
2963
3056
|
{
|
|
2964
3057
|
uintptr_t id = (uintptr_t)metaclass;
|
|
2965
|
-
if (::AllData::
|
|
3058
|
+
if (::AllData::all_register_type_weak_ref.find(id) != ::AllData::all_register_type_weak_ref.end()) {
|
|
2966
3059
|
((PyTypeObject*)metaclass)->tp_getattro = PrivateAttrType_getattr;
|
|
2967
3060
|
((PyTypeObject*)metaclass)->tp_setattro = PrivateAttrType_setattr;
|
|
2968
3061
|
((PyTypeObject*)metaclass)->tp_finalize = register_finalize;
|
|
@@ -2970,10 +3063,6 @@ ensure_metaclass_tp(PyObject* /*self*/, PyObject* metaclass)
|
|
|
2970
3063
|
Py_RETURN_NONE;
|
|
2971
3064
|
}
|
|
2972
3065
|
|
|
2973
|
-
typedef struct PrivateModule {
|
|
2974
|
-
PyObject_HEAD
|
|
2975
|
-
}PrivateModule;
|
|
2976
|
-
|
|
2977
3066
|
static PyObject*
|
|
2978
3067
|
PrivateModule_get_PrivateWrapProxy(PyObject* /*self*/, void* /*closure*/)
|
|
2979
3068
|
{
|
|
@@ -3006,7 +3095,7 @@ PrivateModule_get_PrivateAttrBase(PyObject* /*self*/, void* /*closure*/)
|
|
|
3006
3095
|
}
|
|
3007
3096
|
|
|
3008
3097
|
static PyObject*
|
|
3009
|
-
PrivateModule_dir(PyObject* self)
|
|
3098
|
+
PrivateModule_dir(PyObject* self, PyObject* /*args*/)
|
|
3010
3099
|
{
|
|
3011
3100
|
PyObject* parent_dir = PyObject_CallMethod((PyObject*)&PyModule_Type, "__dir__", "O", self);
|
|
3012
3101
|
if (!parent_dir) return NULL;
|
|
@@ -3089,18 +3178,18 @@ def ensure_metaclass(metaclass: type) -> None:
|
|
|
3089
3178
|
|
|
3090
3179
|
static PyMethodDef PrivateModule_methods[] = {
|
|
3091
3180
|
{"__dir__", (PyCFunction)PrivateModule_dir, METH_NOARGS, NULL},
|
|
3092
|
-
{"prepare", (PyCFunction)prepare_for_PrivateAttr, METH_VARARGS | METH_KEYWORDS, prepare_and_postprocess_doc},
|
|
3093
|
-
{"postprocess", (PyCFunction)postprocess_for_PrivateAttr, METH_VARARGS, prepare_and_postprocess_doc},
|
|
3094
|
-
{"register_metaclass", (PyCFunction)register_metaclass, METH_O, prepare_and_postprocess_doc},
|
|
3095
|
-
{"ensure_type", (PyCFunction)ensure_type_tp, METH_O, ensure_type_doc},
|
|
3096
|
-
{"ensure_metaclass", (PyCFunction)ensure_metaclass_tp, METH_O, ensure_metaclass_doc},
|
|
3181
|
+
{"prepare", (PyCFunction)prepare_for_PrivateAttr, METH_VARARGS | METH_KEYWORDS | METH_STATIC, prepare_and_postprocess_doc},
|
|
3182
|
+
{"postprocess", (PyCFunction)postprocess_for_PrivateAttr, METH_VARARGS | METH_STATIC, prepare_and_postprocess_doc},
|
|
3183
|
+
{"register_metaclass", (PyCFunction)register_metaclass, METH_O | METH_STATIC, prepare_and_postprocess_doc},
|
|
3184
|
+
{"ensure_type", (PyCFunction)ensure_type_tp, METH_O | METH_STATIC, ensure_type_doc},
|
|
3185
|
+
{"ensure_metaclass", (PyCFunction)ensure_metaclass_tp, METH_O | METH_STATIC, ensure_metaclass_doc},
|
|
3097
3186
|
{NULL} // Sentinel
|
|
3098
3187
|
};
|
|
3099
3188
|
|
|
3100
3189
|
static PyTypeObject PrivateModuleType = {
|
|
3101
3190
|
PyVarObject_HEAD_INIT(NULL, 0)
|
|
3102
3191
|
"private_attribute_module", //tp_name
|
|
3103
|
-
|
|
3192
|
+
PyModule_Type.tp_basicsize + 8, //tp_basicsize size of module object + 8 bytes for flag to avoid change attribute '__class__'
|
|
3104
3193
|
0, //tp_itemsize
|
|
3105
3194
|
0, //tp_dealloc
|
|
3106
3195
|
0, //tp_print
|
{private_attribute_cpp-1.3.8 → private_attribute_cpp-1.4.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: 1.
|
|
3
|
+
Version: 1.4.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
|
|
@@ -250,6 +250,7 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
|
|
|
250
250
|
- One class defined in another class cannot use another class's private attribute.
|
|
251
251
|
- One parent class defined an attribute which not in `__private_attrs__` or not a `PrivateAttrType` instance, the child class shouldn't contain the attribute in its `__private_attrs__`.
|
|
252
252
|
- CPython may change "tp_getattro", "tp_setattro" and so on when you change the attribute "\_\_getattribute\_\_", "\_\_setattr\_\_" and so on. If you are fear about it, you can use `ensure_type` to reset those tp slots. For the other metaclasses, you can use `ensure_metaclass` to reset those tp slots. Also, don't set those methods on these classes in your code.
|
|
253
|
+
- `private_attribute.register_metaclass` must be called with the metaclass which support weakref.
|
|
253
254
|
|
|
254
255
|
## License
|
|
255
256
|
|
|
@@ -19,7 +19,7 @@ readme = open('README.md').read()
|
|
|
19
19
|
|
|
20
20
|
setup(
|
|
21
21
|
name='private_attribute_cpp',
|
|
22
|
-
version='1.
|
|
22
|
+
version='1.4.0',
|
|
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
|