private-attribute-cpp 2.1.11__tar.gz → 2.1.13__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.11/private_attribute_cpp.egg-info → private_attribute_cpp-2.1.13}/PKG-INFO +1 -1
  2. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/private_attribute.cpp +96 -54
  3. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
  4. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/setup.py +1 -1
  5. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/LICENSE +0 -0
  6. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/MANIFEST.in +0 -0
  7. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/README.md +0 -0
  8. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/picosha2.h +0 -0
  9. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/private_attribute.pyi +0 -0
  10. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
  11. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  12. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  13. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  14. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/setup.cfg +0 -0
  15. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_attr_classify_owner.py +0 -0
  16. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_class_private_attrs.py +0 -0
  17. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_gc_collect.py +0 -0
  18. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_private_abc.py +0 -0
  19. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_private_attrs.py +0 -0
  20. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_private_func.py +0 -0
  21. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_private_inheritance.py +0 -0
  22. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_private_method.py +0 -0
  23. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/tests/test_private_wrap.py +0 -0
  24. {private_attribute_cpp-2.1.11 → private_attribute_cpp-2.1.13}/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.11
3
+ Version: 2.1.13
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
@@ -194,14 +194,14 @@ namespace {
194
194
  static std::unordered_map<uintptr_t, std::unordered_map<std::string, PyObjectStorage>> type_attr_dict;
195
195
  };
196
196
  static std::unordered_map<uintptr_t, std::unordered_map<uintptr_t, PyObjectStorage>> type_allowed_code_map;
197
- static std::unordered_map<uintptr_t, std::shared_ptr<std::shared_mutex>> all_type_mutex;
197
+ static std::unordered_map<uintptr_t, std::unique_ptr<std::shared_mutex>> all_type_mutex;
198
198
  static std::unordered_map<uintptr_t, PyObjectStorage> type_need_call;
199
199
  static std::unordered_map<uintptr_t, std::unordered_set<TwoStringTuple>> all_type_attr_set;
200
200
  namespace {
201
201
  static std::unordered_map<uintptr_t, std::unordered_map<uintptr_t,
202
202
  std::unordered_map<std::string, PyObjectStorage>>> all_object_attr, all_type_subclass_attr;
203
203
  };
204
- static std::unordered_map<uintptr_t, std::unordered_map<uintptr_t, std::shared_ptr<std::shared_mutex>>>
204
+ static std::unordered_map<uintptr_t, std::unordered_map<uintptr_t, std::unique_ptr<std::shared_mutex>>>
205
205
  all_object_mutex, all_type_subclass_mutex;
206
206
  static std::mutex object_creatmutex_mutex, type_createmutex_mutex, type_parenttype_createmutex_mutex;
207
207
  static std::unordered_map<uintptr_t, std::vector<uintptr_t>> all_type_parent_id;
@@ -224,7 +224,12 @@ namespace {
224
224
 
225
225
  static std::shared_mutex all_register_new_metaclass_mutex;
226
226
  static std::unordered_map<uintptr_t, PyObjectStorage> all_register_type_weak_ref;
227
- static std::vector<PyObjectStorage> store_module_self;
227
+ // Single dict-backed strong-ref cache shared by the module itself (keyed by
228
+ // kModuleSelfKey) and by PrivateAttrBase (keyed by kPrivateAttrBaseKey),
229
+ // so clean_all_storages can release everything at interpreter shutdown.
230
+ static std::unordered_map<uintptr_t, PyObjectStorage> store_module_self;
231
+ static constexpr uintptr_t kModuleSelfKey = 0;
232
+ static constexpr uintptr_t kPrivateAttrBaseKey = 1;
228
233
  };
229
234
  };
230
235
 
@@ -237,11 +242,10 @@ object_create_mutex(uintptr_t final_id, uintptr_t obj_id) noexcept
237
242
  ::AllData::all_object_attr[final_id][obj_id] = {};
238
243
  }
239
244
  if (::AllData::all_object_mutex.find(final_id) == ::AllData::all_object_mutex.end()) {
240
- ::AllData::all_object_mutex[final_id] = {};
245
+ ::AllData::all_object_mutex[final_id].clear();
241
246
  }
242
247
  if (::AllData::all_object_mutex[final_id].find(obj_id) == ::AllData::all_object_mutex[final_id].end()) {
243
- std::shared_ptr<std::shared_mutex> lock(new std::shared_mutex());
244
- ::AllData::all_object_mutex[final_id][obj_id] = lock;
248
+ ::AllData::all_object_mutex[final_id][obj_id] = std::make_unique<std::shared_mutex>();
245
249
  }
246
250
  }
247
251
 
@@ -252,8 +256,7 @@ type_create_mutex(uintptr_t typ_id) noexcept {
252
256
  ::AllData::type_attr_dict[typ_id] = {};
253
257
  }
254
258
  if (::AllData::all_type_mutex.find(typ_id) == ::AllData::all_type_mutex.end()) {
255
- std::shared_ptr<std::shared_mutex> lock(new std::shared_mutex());
256
- ::AllData::all_type_mutex[typ_id] = lock;
259
+ ::AllData::all_type_mutex[typ_id] = std::make_unique<std::shared_mutex>();
257
260
  }
258
261
  }
259
262
 
@@ -268,11 +271,10 @@ type_parenttype_create_mutex(uintptr_t final_id, uintptr_t typ_id) noexcept
268
271
  ::AllData::all_type_subclass_attr[final_id][typ_id] = {};
269
272
  }
270
273
  if (::AllData::all_type_subclass_mutex.find(final_id) == ::AllData::all_type_subclass_mutex.end()) {
271
- ::AllData::all_type_subclass_mutex[final_id] = {};
274
+ ::AllData::all_type_subclass_mutex[final_id].clear();
272
275
  }
273
276
  if (::AllData::all_type_subclass_mutex[final_id].find(typ_id) == ::AllData::all_type_subclass_mutex[final_id].end()) {
274
- std::shared_ptr<std::shared_mutex> lock(new std::shared_mutex());
275
- ::AllData::all_type_subclass_mutex[final_id][typ_id] = lock;
277
+ ::AllData::all_type_subclass_mutex[final_id][typ_id] = std::make_unique<std::shared_mutex>();
276
278
  }
277
279
  }
278
280
 
@@ -2057,13 +2059,13 @@ static void
2057
2059
  PrivateAttr_object_init_private_dict(uintptr_t obj_id, uintptr_t type_id) noexcept
2058
2060
  {
2059
2061
  if (::AllData::all_object_mutex.find(type_id) == ::AllData::all_object_mutex.end()) {
2060
- ::AllData::all_object_mutex[type_id] = {};
2062
+ ::AllData::all_object_mutex[type_id].clear();
2061
2063
  }
2062
2064
  if (::AllData::all_object_attr.find(type_id) == ::AllData::all_object_attr.end()) {
2063
2065
  ::AllData::all_object_attr[type_id] = {};
2064
2066
  }
2065
2067
  if (::AllData::all_object_mutex[type_id].find(obj_id) == ::AllData::all_object_mutex[type_id].end()) {
2066
- ::AllData::all_object_mutex[type_id][obj_id] = std::shared_ptr<std::shared_mutex>(new std::shared_mutex());
2068
+ ::AllData::all_object_mutex[type_id][obj_id] = std::make_unique<std::shared_mutex>();
2067
2069
  }
2068
2070
  if (::AllData::all_object_attr[type_id].find(obj_id) == ::AllData::all_object_attr[type_id].end()) {
2069
2071
  ::AllData::all_object_attr[type_id][obj_id] = {};
@@ -2413,10 +2415,11 @@ real_class_name(const std::string& name, const std::string& class_name) noexcept
2413
2415
  {
2414
2416
  size_t start_pos = class_name.find_first_not_of('_');
2415
2417
  std::string cleaned_class_name = (start_pos == std::string::npos) ? "" : class_name.substr(start_pos);
2418
+ std::string pre_underline = cleaned_class_name.size() > 0 ? "_" : "";
2416
2419
 
2417
2420
  // if the name starts with "__" but does not end with "__", change to _ClassName__name
2418
2421
  if (name.length() >= 2 && name.substr(0, 2) == "__" && name.substr(name.length() - 2) != "__") {
2419
- return "_" + cleaned_class_name + name;
2422
+ return pre_underline + cleaned_class_name + name;
2420
2423
  }
2421
2424
  return name;
2422
2425
  }
@@ -2955,21 +2958,21 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2955
2958
  ::AllData::all_type_parent_id[type_id] = mro_vector;
2956
2959
 
2957
2960
  ::AllData::type_allowed_code_map[type_id] = {};
2958
- ::AllData::all_object_mutex[type_id] = {};
2959
- ::AllData::all_type_mutex[type_id] = std::make_shared<std::shared_mutex>();
2961
+ ::AllData::all_object_mutex[type_id].clear();
2962
+ ::AllData::all_type_mutex[type_id] = std::make_unique<std::shared_mutex>();
2960
2963
  ::AllData::all_object_attr[type_id] = {};
2961
2964
  ::AllData::all_type_subclass_attr[type_id] = {};
2962
- ::AllData::all_type_subclass_mutex[type_id] = {};
2965
+ ::AllData::all_type_subclass_mutex[type_id].clear();
2963
2966
 
2964
2967
  for (uintptr_t i: mro_vector) {
2965
2968
  if (::AllData::all_type_subclass_attr.find(i) == ::AllData::all_type_subclass_attr.end()) {
2966
2969
  ::AllData::all_type_subclass_attr[i] = {};
2967
2970
  }
2968
2971
  if (::AllData::all_type_subclass_mutex.find(i) == ::AllData::all_type_subclass_mutex.end()) {
2969
- ::AllData::all_type_subclass_mutex[i] = {};
2972
+ ::AllData::all_type_subclass_mutex[i].clear();
2970
2973
  }
2971
2974
  ::AllData::all_type_subclass_attr[i][type_id] = {};
2972
- ::AllData::all_type_subclass_mutex[i][type_id] = std::make_shared<std::shared_mutex>();
2975
+ ::AllData::all_type_subclass_mutex[i][type_id] = std::make_unique<std::shared_mutex>();
2973
2976
  }
2974
2977
 
2975
2978
  for (auto& [key, value]: data.need_remove_itself) {
@@ -2991,13 +2994,13 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2991
2994
  ::AllData::all_type_subclass_attr[i] = {};
2992
2995
  }
2993
2996
  if (::AllData::all_type_subclass_mutex.find(i) == ::AllData::all_type_subclass_mutex.end()) {
2994
- ::AllData::all_type_subclass_mutex[i] = {};
2997
+ ::AllData::all_type_subclass_mutex[i].clear();
2995
2998
  }
2996
2999
  if (::AllData::all_type_subclass_attr[i].find(type_id) == ::AllData::all_type_subclass_attr[i].end()) {
2997
3000
  ::AllData::all_type_subclass_attr[i][type_id] = {};
2998
3001
  }
2999
3002
  if (::AllData::all_type_subclass_mutex[i].find(type_id) == ::AllData::all_type_subclass_mutex[i].end()) {
3000
- ::AllData::all_type_subclass_mutex[i][type_id] = std::make_shared<std::shared_mutex>();
3003
+ ::AllData::all_type_subclass_mutex[i][type_id] = std::make_unique<std::shared_mutex>();
3001
3004
  }
3002
3005
  for (auto& [key, value]: map) {
3003
3006
  std::string final_key;
@@ -4003,13 +4006,22 @@ PrivateModule_get_PrivateAttrType(PyObject* /*self*/, void* /*closure*/) noexcep
4003
4006
  static PyObject*
4004
4007
  PrivateModule_get_PrivateAttrBase(PyObject* /*self*/, void* /*closure*/) noexcept
4005
4008
  {
4006
- static PyObject* PrivateAttrBase = create_private_attr_base_simple();
4007
- if (!PrivateAttrBase) {
4008
- if (!PyErr_Occurred()) {
4009
- PyErr_SetString(PyExc_RuntimeError, "failed to create PrivateAttrBase");
4009
+ static std::mutex base_mutex;
4010
+ std::lock_guard<std::mutex> lock(base_mutex);
4011
+ auto it = AllData::store_module_self.find(AllData::kPrivateAttrBaseKey);
4012
+ if (it == AllData::store_module_self.end()) {
4013
+ PyObject* base = create_private_attr_base_simple();
4014
+ if (!base) {
4015
+ if (!PyErr_Occurred()) {
4016
+ PyErr_SetString(PyExc_RuntimeError, "failed to create PrivateAttrBase");
4017
+ }
4018
+ return NULL;
4010
4019
  }
4011
- return NULL;
4020
+ AllData::store_module_self[AllData::kPrivateAttrBaseKey] = base;
4021
+ Py_DECREF(base);
4022
+ it = AllData::store_module_self.find(AllData::kPrivateAttrBaseKey);
4012
4023
  }
4024
+ PyObject* PrivateAttrBase = it->second.get();
4013
4025
  Py_INCREF(PrivateAttrBase);
4014
4026
  return PrivateAttrBase;
4015
4027
  }
@@ -4258,13 +4270,25 @@ class MyClass(PrivateAttrBase):
4258
4270
  ```
4259
4271
  )";
4260
4272
 
4273
+ static int PrivateModule_exec(PyObject* m) noexcept;
4274
+ static PyObject* PrivateModule_create(PyObject* spec, PyModuleDef* def) noexcept;
4275
+
4276
+ static PyModuleDef_Slot PrivateModule_slots[] = {
4277
+ {Py_mod_create, (void*)PrivateModule_create},
4278
+ {Py_mod_exec, (void*)PrivateModule_exec},
4279
+ #if PY_VERSION_HEX >= 0x030D0000
4280
+ {Py_mod_gil, Py_MOD_GIL_NOT_USED},
4281
+ #endif
4282
+ {0, NULL}
4283
+ };
4284
+
4261
4285
  static PyModuleDef def = {
4262
4286
  PyModuleDef_HEAD_INIT,
4263
4287
  "private_attribute",
4264
4288
  module_doc,
4265
4289
  0,
4266
4290
  NULL,
4267
- NULL,
4291
+ PrivateModule_slots,
4268
4292
  NULL,
4269
4293
  NULL,
4270
4294
  NULL
@@ -4309,47 +4333,44 @@ atexit_register_clean_func(void) noexcept
4309
4333
  return 0;
4310
4334
  }
4311
4335
 
4312
- PyMODINIT_FUNC
4313
- PyInit_private_attribute(void) noexcept
4336
+ static PyObject*
4337
+ PrivateModule_create(PyObject* spec, PyModuleDef* /*def*/) noexcept
4314
4338
  {
4315
- // check if AllData::store_module_self has first value
4316
- if (AllData::store_module_self.size() >= 1) {
4317
- PyObject* m = AllData::store_module_self[0];
4318
- Py_INCREF(m);
4319
- return m;
4320
- }
4321
- if (init_all_slots() <0 ||
4322
- atexit_register_clean_func() < 0 ||
4323
- PyType_Ready(&PrivateWrapType) < 0 ||
4324
- PyType_Ready(&PrivateWrapProxyType) < 0 ||
4325
- PyType_Ready(&PrivateAttrType) < 0 ||
4326
- PyType_Ready(&PrivateModuleType) < 0 ||
4327
- PyType_Ready(&PrivateTempType) < 0) {
4339
+ PyObject* name = PyObject_GetAttrString(spec, "name");
4340
+ if (!name) {
4328
4341
  return NULL;
4329
4342
  }
4343
+ // Instantiate the module directly as an instance of PrivateModuleType
4344
+ // (a subclass of `module`) so that the object returned from
4345
+ // PyInit_private_attribute is genuinely a
4346
+ // `private_attribute.private_attribute_module` instance from the start,
4347
+ // rather than a plain module re-typed with Py_SET_TYPE afterwards.
4348
+ PyObject* m = PyObject_CallFunction((PyObject*)&PrivateModuleType, "O", name);
4349
+ Py_DECREF(name);
4350
+ return m;
4351
+ }
4352
+
4353
+ static int
4354
+ PrivateModule_exec(PyObject* m) noexcept
4355
+ {
4330
4356
  // Eagerly create PrivateAttrBase so that CPython's subtype_traverse /
4331
4357
  // subtype_clear pointers are captured at import time (see
4332
4358
  // PrivateAttrCaptureGuard and ::AllData::captured_subtype_*), instead of
4333
4359
  // waiting for the first lazy attribute access to the module.
4334
4360
  PyObject* private_attr_base = PrivateModule_get_PrivateAttrBase(NULL, NULL);
4335
4361
  if (!private_attr_base) {
4336
- return NULL;
4362
+ return -1;
4337
4363
  }
4338
4364
  PyObject* all = PyList_New(0);
4339
4365
  if (!all) {
4340
4366
  Py_DECREF(private_attr_base);
4341
- return NULL;
4367
+ return -1;
4342
4368
  }
4343
- PyObject* m = PyModule_Create(&def);
4344
- if (!m) {
4369
+ if (PyModule_AddObject(m, "__all__", all) < 0) {
4345
4370
  Py_DECREF(all);
4346
4371
  Py_DECREF(private_attr_base);
4347
- return NULL;
4372
+ return -1;
4348
4373
  }
4349
- #ifdef Py_GIL_DISABLED
4350
- PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
4351
- #endif
4352
- PyModule_AddObject(m, "__all__", all);
4353
4374
  /* all contains:
4354
4375
  * PrivateWrapProxy
4355
4376
  * PrivateAttrType
@@ -4368,10 +4389,31 @@ PyInit_private_attribute(void) noexcept
4368
4389
  PyList_AppendString(all, "register_metaclass");
4369
4390
  PyList_AppendString(all, "ensure_type");
4370
4391
  PyList_AppendString(all, "ensure_metaclass");
4371
- Py_SET_TYPE(m, &PrivateModuleType);
4372
4392
 
4373
4393
  Py_DECREF(private_attr_base);
4374
- AllData::store_module_self.push_back(m); // store module self
4394
+ AllData::store_module_self[AllData::kModuleSelfKey] = m; // store module self
4375
4395
 
4376
- return m;
4396
+ return 0;
4397
+ }
4398
+
4399
+ PyMODINIT_FUNC
4400
+ PyInit_private_attribute(void) noexcept
4401
+ {
4402
+ // check if AllData::store_module_self already holds the module
4403
+ auto it = AllData::store_module_self.find(AllData::kModuleSelfKey);
4404
+ if (it != AllData::store_module_self.end()) {
4405
+ PyObject* m = it->second.get();
4406
+ Py_INCREF(m);
4407
+ return m;
4408
+ }
4409
+ if (init_all_slots() <0 ||
4410
+ atexit_register_clean_func() < 0 ||
4411
+ PyType_Ready(&PrivateWrapType) < 0 ||
4412
+ PyType_Ready(&PrivateWrapProxyType) < 0 ||
4413
+ PyType_Ready(&PrivateAttrType) < 0 ||
4414
+ PyType_Ready(&PrivateModuleType) < 0 ||
4415
+ PyType_Ready(&PrivateTempType) < 0) {
4416
+ return NULL;
4417
+ }
4418
+ return PyModuleDef_Init(&def);
4377
4419
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.1.11
3
+ Version: 2.1.13
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.11',
27
+ version='2.1.13',
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.',