private-attribute-cpp 2.1.12__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.12/private_attribute_cpp.egg-info → private_attribute_cpp-2.1.13}/PKG-INFO +1 -1
  2. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/private_attribute.cpp +94 -53
  3. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
  4. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/setup.py +1 -1
  5. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/LICENSE +0 -0
  6. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/MANIFEST.in +0 -0
  7. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/README.md +0 -0
  8. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/picosha2.h +0 -0
  9. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/private_attribute.pyi +0 -0
  10. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
  11. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  12. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  13. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  14. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/setup.cfg +0 -0
  15. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_attr_classify_owner.py +0 -0
  16. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_class_private_attrs.py +0 -0
  17. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_gc_collect.py +0 -0
  18. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_private_abc.py +0 -0
  19. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_private_attrs.py +0 -0
  20. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_private_func.py +0 -0
  21. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_private_inheritance.py +0 -0
  22. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_private_method.py +0 -0
  23. {private_attribute_cpp-2.1.12 → private_attribute_cpp-2.1.13}/tests/test_private_wrap.py +0 -0
  24. {private_attribute_cpp-2.1.12 → 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.12
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] = {};
@@ -2956,21 +2958,21 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2956
2958
  ::AllData::all_type_parent_id[type_id] = mro_vector;
2957
2959
 
2958
2960
  ::AllData::type_allowed_code_map[type_id] = {};
2959
- ::AllData::all_object_mutex[type_id] = {};
2960
- ::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>();
2961
2963
  ::AllData::all_object_attr[type_id] = {};
2962
2964
  ::AllData::all_type_subclass_attr[type_id] = {};
2963
- ::AllData::all_type_subclass_mutex[type_id] = {};
2965
+ ::AllData::all_type_subclass_mutex[type_id].clear();
2964
2966
 
2965
2967
  for (uintptr_t i: mro_vector) {
2966
2968
  if (::AllData::all_type_subclass_attr.find(i) == ::AllData::all_type_subclass_attr.end()) {
2967
2969
  ::AllData::all_type_subclass_attr[i] = {};
2968
2970
  }
2969
2971
  if (::AllData::all_type_subclass_mutex.find(i) == ::AllData::all_type_subclass_mutex.end()) {
2970
- ::AllData::all_type_subclass_mutex[i] = {};
2972
+ ::AllData::all_type_subclass_mutex[i].clear();
2971
2973
  }
2972
2974
  ::AllData::all_type_subclass_attr[i][type_id] = {};
2973
- ::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>();
2974
2976
  }
2975
2977
 
2976
2978
  for (auto& [key, value]: data.need_remove_itself) {
@@ -2992,13 +2994,13 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2992
2994
  ::AllData::all_type_subclass_attr[i] = {};
2993
2995
  }
2994
2996
  if (::AllData::all_type_subclass_mutex.find(i) == ::AllData::all_type_subclass_mutex.end()) {
2995
- ::AllData::all_type_subclass_mutex[i] = {};
2997
+ ::AllData::all_type_subclass_mutex[i].clear();
2996
2998
  }
2997
2999
  if (::AllData::all_type_subclass_attr[i].find(type_id) == ::AllData::all_type_subclass_attr[i].end()) {
2998
3000
  ::AllData::all_type_subclass_attr[i][type_id] = {};
2999
3001
  }
3000
3002
  if (::AllData::all_type_subclass_mutex[i].find(type_id) == ::AllData::all_type_subclass_mutex[i].end()) {
3001
- ::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>();
3002
3004
  }
3003
3005
  for (auto& [key, value]: map) {
3004
3006
  std::string final_key;
@@ -4004,13 +4006,22 @@ PrivateModule_get_PrivateAttrType(PyObject* /*self*/, void* /*closure*/) noexcep
4004
4006
  static PyObject*
4005
4007
  PrivateModule_get_PrivateAttrBase(PyObject* /*self*/, void* /*closure*/) noexcept
4006
4008
  {
4007
- static PyObject* PrivateAttrBase = create_private_attr_base_simple();
4008
- if (!PrivateAttrBase) {
4009
- if (!PyErr_Occurred()) {
4010
- 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;
4011
4019
  }
4012
- return NULL;
4020
+ AllData::store_module_self[AllData::kPrivateAttrBaseKey] = base;
4021
+ Py_DECREF(base);
4022
+ it = AllData::store_module_self.find(AllData::kPrivateAttrBaseKey);
4013
4023
  }
4024
+ PyObject* PrivateAttrBase = it->second.get();
4014
4025
  Py_INCREF(PrivateAttrBase);
4015
4026
  return PrivateAttrBase;
4016
4027
  }
@@ -4259,13 +4270,25 @@ class MyClass(PrivateAttrBase):
4259
4270
  ```
4260
4271
  )";
4261
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
+
4262
4285
  static PyModuleDef def = {
4263
4286
  PyModuleDef_HEAD_INIT,
4264
4287
  "private_attribute",
4265
4288
  module_doc,
4266
4289
  0,
4267
4290
  NULL,
4268
- NULL,
4291
+ PrivateModule_slots,
4269
4292
  NULL,
4270
4293
  NULL,
4271
4294
  NULL
@@ -4310,47 +4333,44 @@ atexit_register_clean_func(void) noexcept
4310
4333
  return 0;
4311
4334
  }
4312
4335
 
4313
- PyMODINIT_FUNC
4314
- PyInit_private_attribute(void) noexcept
4336
+ static PyObject*
4337
+ PrivateModule_create(PyObject* spec, PyModuleDef* /*def*/) noexcept
4315
4338
  {
4316
- // check if AllData::store_module_self has first value
4317
- if (AllData::store_module_self.size() >= 1) {
4318
- PyObject* m = AllData::store_module_self[0];
4319
- Py_INCREF(m);
4320
- return m;
4321
- }
4322
- if (init_all_slots() <0 ||
4323
- atexit_register_clean_func() < 0 ||
4324
- PyType_Ready(&PrivateWrapType) < 0 ||
4325
- PyType_Ready(&PrivateWrapProxyType) < 0 ||
4326
- PyType_Ready(&PrivateAttrType) < 0 ||
4327
- PyType_Ready(&PrivateModuleType) < 0 ||
4328
- PyType_Ready(&PrivateTempType) < 0) {
4339
+ PyObject* name = PyObject_GetAttrString(spec, "name");
4340
+ if (!name) {
4329
4341
  return NULL;
4330
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
+ {
4331
4356
  // Eagerly create PrivateAttrBase so that CPython's subtype_traverse /
4332
4357
  // subtype_clear pointers are captured at import time (see
4333
4358
  // PrivateAttrCaptureGuard and ::AllData::captured_subtype_*), instead of
4334
4359
  // waiting for the first lazy attribute access to the module.
4335
4360
  PyObject* private_attr_base = PrivateModule_get_PrivateAttrBase(NULL, NULL);
4336
4361
  if (!private_attr_base) {
4337
- return NULL;
4362
+ return -1;
4338
4363
  }
4339
4364
  PyObject* all = PyList_New(0);
4340
4365
  if (!all) {
4341
4366
  Py_DECREF(private_attr_base);
4342
- return NULL;
4367
+ return -1;
4343
4368
  }
4344
- PyObject* m = PyModule_Create(&def);
4345
- if (!m) {
4369
+ if (PyModule_AddObject(m, "__all__", all) < 0) {
4346
4370
  Py_DECREF(all);
4347
4371
  Py_DECREF(private_attr_base);
4348
- return NULL;
4372
+ return -1;
4349
4373
  }
4350
- #ifdef Py_GIL_DISABLED
4351
- PyUnstable_Module_SetGIL(m, Py_MOD_GIL_NOT_USED);
4352
- #endif
4353
- PyModule_AddObject(m, "__all__", all);
4354
4374
  /* all contains:
4355
4375
  * PrivateWrapProxy
4356
4376
  * PrivateAttrType
@@ -4369,10 +4389,31 @@ PyInit_private_attribute(void) noexcept
4369
4389
  PyList_AppendString(all, "register_metaclass");
4370
4390
  PyList_AppendString(all, "ensure_type");
4371
4391
  PyList_AppendString(all, "ensure_metaclass");
4372
- Py_SET_TYPE(m, &PrivateModuleType);
4373
4392
 
4374
4393
  Py_DECREF(private_attr_base);
4375
- AllData::store_module_self.push_back(m); // store module self
4394
+ AllData::store_module_self[AllData::kModuleSelfKey] = m; // store module self
4376
4395
 
4377
- 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);
4378
4419
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.1.12
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.12',
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.',