private-attribute-cpp 2.0.1__tar.gz → 2.0.3__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 (21) hide show
  1. {private_attribute_cpp-2.0.1/private_attribute_cpp.egg-info → private_attribute_cpp-2.0.3}/PKG-INFO +1 -1
  2. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/private_attribute.cpp +104 -210
  3. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3/private_attribute_cpp.egg-info}/PKG-INFO +1 -1
  4. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/setup.py +1 -1
  5. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/LICENSE +0 -0
  6. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/MANIFEST.in +0 -0
  7. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/README.md +0 -0
  8. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/picosha2.h +0 -0
  9. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/private_attribute.pyi +0 -0
  10. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/private_attribute_cpp.egg-info/SOURCES.txt +0 -0
  11. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/private_attribute_cpp.egg-info/dependency_links.txt +0 -0
  12. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/private_attribute_cpp.egg-info/not-zip-safe +0 -0
  13. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/private_attribute_cpp.egg-info/top_level.txt +0 -0
  14. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/setup.cfg +0 -0
  15. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/tests/test_class_private_attrs.py +0 -0
  16. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/tests/test_private_abc.py +0 -0
  17. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/tests/test_private_attrs.py +0 -0
  18. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/tests/test_private_func.py +0 -0
  19. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/tests/test_private_inheritance.py +0 -0
  20. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/tests/test_private_method.py +0 -0
  21. {private_attribute_cpp-2.0.1 → private_attribute_cpp-2.0.3}/tests/test_private_wrap.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.0.1
3
+ Version: 2.0.3
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
@@ -33,6 +33,12 @@ PyDict_ContainsString(PyObject *op, const char *key) noexcept
33
33
  return res;
34
34
  }
35
35
  #endif
36
+
37
+ // python >= 3.15 has PyAnyDict_Check. Under 3.15 defined it as PyDict_Check
38
+ #if PY_VERSION_HEX < 0x030F0000
39
+ #define PyAnyDict_Check(op) PyDict_Check(op)
40
+ #endif
41
+
36
42
  static const auto module_running_time = std::chrono::system_clock::now();
37
43
 
38
44
  static std::string
@@ -277,178 +283,67 @@ default_random_string(uintptr_t obj_id, const std::string& attr_name) noexcept
277
283
  return result;
278
284
  }
279
285
 
280
- class RestorePythonException : public std::exception
281
- {
282
- public:
283
- RestorePythonException(PyObject* type, PyObject* value, PyObject* traceback) noexcept
284
- : type(type), value(value), traceback(traceback) {
285
- }
286
-
287
- ~RestorePythonException() noexcept {
288
- Py_XDECREF(type);
289
- Py_XDECREF(value);
290
- Py_XDECREF(traceback);
291
- }
292
-
293
- RestorePythonException(const RestorePythonException&) = delete;
294
- RestorePythonException& operator=(RestorePythonException&& other) noexcept {
295
- if (this != &other) {
296
- type = other.type;
297
- value = other.value;
298
- traceback = other.traceback;
299
- other.type = nullptr;
300
- other.value = nullptr;
301
- other.traceback = nullptr;
302
- }
303
- return *this;
304
- }
305
-
306
- // Move constructor
307
- RestorePythonException(RestorePythonException&& other) noexcept
308
- : type(other.type), value(other.value), traceback(other.traceback) {
309
- other.type = nullptr;
310
- other.value = nullptr;
311
- other.traceback = nullptr;
312
- }
313
-
314
- void restore() noexcept {
315
- PyErr_Restore(type, value, traceback);
316
- type = value = traceback = nullptr;
317
- }
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
-
376
- private:
377
- PyObject* type = nullptr;
378
- PyObject* value = nullptr;
379
- PyObject* traceback = nullptr;
380
- mutable std::string msg_;
286
+ struct RestorePythonExceptionResult {
287
+ std::string value;
288
+ bool ok = true;
381
289
  };
382
290
 
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
-
390
- static std::string
391
- custom_random_string(uintptr_t obj_id, const std::string& attr_name, PyObject* func)
291
+ static RestorePythonExceptionResult
292
+ custom_random_string(uintptr_t obj_id, const std::string& attr_name, PyObject* func) noexcept
392
293
  {
294
+ RestorePythonExceptionResult result;
393
295
  AllPyobjectAttrCacheKey key(obj_id, attr_name);
394
- std::string result;
395
296
  {
396
297
  std::shared_lock<std::shared_mutex> lock(::AllData::cache_mutex);
397
298
  auto it = ::AllData::cache.find(key);
398
299
  if (it != ::AllData::cache.end()) {
399
- result = it->second;
300
+ result.value = it->second;
400
301
  return result;
401
302
  } else {
402
303
  lock.unlock();
403
- PyObject* args = PyTuple_New(2);
404
- PyTuple_SetItem(args, 0, PyLong_FromSize_t(static_cast<size_t>(obj_id)));
405
- PyTuple_SetItem(args, 1, PyUnicode_FromString(attr_name.c_str()));
406
-
407
- PyObject* python_result = PyObject_CallObject((PyObject*)func, args);
408
-
409
- Py_DECREF(args);
304
+ PyObject* python_result = PyObject_CallFunction(
305
+ func,
306
+ "ns",
307
+ static_cast<Py_ssize_t>(obj_id),
308
+ attr_name.c_str()
309
+ );
410
310
  if (python_result) {
411
311
  if (!PyUnicode_Check(python_result)) {
412
312
  Py_DECREF(python_result);
413
313
  PyErr_SetString(PyExc_TypeError, "private_func function must return a string");
414
- PyObject *type, *value, *traceback;
415
- PyErr_Fetch(&type, &value, &traceback);
416
- throw RestorePythonException(type, value, traceback);
314
+ result.ok = false;
315
+ result.value = "private_func function must return a string";
316
+ return result;
417
317
  }
418
- result = PyUnicode_AsUTF8(python_result);
318
+ result.value = PyUnicode_AsUTF8(python_result);
419
319
  Py_DECREF(python_result);
420
- std::string original_result = result;
320
+ std::string original_result = result.value;
421
321
  unsigned long long i = 1;
422
322
  std::unique_lock<std::shared_mutex> lock2(::AllData::cache_mutex);
423
323
  auto it = ::AllData::cache.find(key); // twice check
424
324
  if (it != ::AllData::cache.end()) {
425
- result = it->second;
325
+ result.value = it->second;
426
326
  return result;
427
327
  }
428
- while (::AllData::all_exist_name.find(result) != ::AllData::all_exist_name.end()) {
429
- result = original_result + "_" + std::to_string(i);
328
+ while (::AllData::all_exist_name.find(result.value) != ::AllData::all_exist_name.end()) {
329
+ result.value = original_result + "_" + std::to_string(i);
430
330
  i++;
431
331
  }
432
332
  if (::AllData::obj_attr_keys.find(obj_id) == ::AllData::obj_attr_keys.end()) {
433
333
  ::AllData::obj_attr_keys[obj_id] = {};
434
334
  }
435
335
  ::AllData::obj_attr_keys[obj_id].push_back(key);
436
- ::AllData::cache[key] = result;
437
- ::AllData::all_exist_name.insert(result);
336
+ ::AllData::cache[key] = result.value;
337
+ ::AllData::all_exist_name.insert(result.value);
438
338
  } else {
439
- PyObject *type, *value, *traceback;
440
- PyErr_Fetch(&type, &value, &traceback);
441
- throw RestorePythonException(type, value, traceback);
339
+ result.ok = false;
340
+ result.value = "python exception while calling private function";
442
341
  }
443
342
  }
444
343
  }
445
344
  return result;
446
345
  }
447
346
 
448
- #ifdef _MSC_VER
449
- #pragma warning(pop)
450
- #endif
451
-
452
347
  static void
453
348
  clear_obj(uintptr_t obj_id) noexcept
454
349
  {
@@ -500,12 +395,11 @@ id_getattr(const std::string& attr_name, PyObject* obj, PyObject* typ) noexcept
500
395
  obj_need_call = ::AllData::type_need_call[final_id];
501
396
  }
502
397
  if (obj_need_call) {
503
- try {
504
- obj_private_name = custom_random_string(obj_id, attr_name, obj_need_call);
505
- } catch (RestorePythonException& e) {
506
- e.restore();
398
+ auto private_name_result = custom_random_string(obj_id, attr_name, obj_need_call);
399
+ if (!private_name_result.ok) {
507
400
  return NULL;
508
401
  }
402
+ obj_private_name = private_name_result.value;
509
403
  } else {
510
404
  obj_private_name = default_random_string(obj_id, attr_name);
511
405
  }
@@ -582,9 +476,7 @@ id_getattr(const std::string& attr_name, PyObject* obj, PyObject* typ) noexcept
582
476
  if (type_name == NULL) {
583
477
  return NULL;
584
478
  }
585
- std::string string_type_name = type_name;
586
- std::string exception_information = "'" + string_type_name + "' objects has no attribute '" + attr_name + "'";
587
- PyErr_SetString(PyExc_AttributeError, exception_information.c_str());
479
+ PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type_name, attr_name.c_str());
588
480
  return NULL;
589
481
  }
590
482
 
@@ -616,9 +508,7 @@ type_getattr(PyObject* typ, const std::string& attr_name) noexcept
616
508
  if (type_name == NULL) {
617
509
  return NULL;
618
510
  }
619
- std::string string_type_name = type_name;
620
- std::string message = "type object '" + string_type_name + "' has no attribute '" + attr_name + "'";
621
- PyErr_SetString(PyExc_AttributeError, message.c_str());
511
+ PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type_name, attr_name.c_str());
622
512
  return NULL;
623
513
  }
624
514
 
@@ -641,12 +531,11 @@ id_setattr(const std::string& attr_name, PyObject* obj, PyObject* typ, PyObject*
641
531
  obj_need_call = ::AllData::type_need_call[final_id];
642
532
  }
643
533
  if (obj_need_call) {
644
- try {
645
- obj_private_name = custom_random_string(obj_id, attr_name, obj_need_call);
646
- } catch (RestorePythonException& e) {
647
- e.restore();
534
+ auto private_name_result = custom_random_string(obj_id, attr_name, obj_need_call);
535
+ if (!private_name_result.ok) {
648
536
  return -1;
649
537
  }
538
+ obj_private_name = private_name_result.value;
650
539
  } else {
651
540
  obj_private_name = default_random_string(obj_id, attr_name);
652
541
  }
@@ -710,12 +599,11 @@ type_setattr(PyObject* typ, const std::string& attr_name, PyObject* value) noexc
710
599
  type_need_call = NULL;
711
600
  }
712
601
  if (type_need_call) {
713
- try {
714
- final_key = custom_random_string(typ_id, attr_name, type_need_call);
715
- } catch (RestorePythonException& e) {
716
- e.restore();
602
+ auto private_name_result = custom_random_string(typ_id, attr_name, type_need_call);
603
+ if (!private_name_result.ok) {
717
604
  return -1;
718
605
  }
606
+ final_key = private_name_result.value;
719
607
  } else {
720
608
  final_key = default_random_string(typ_id, attr_name);
721
609
  }
@@ -785,12 +673,11 @@ id_delattr(const std::string& attr_name, PyObject* obj, PyObject* typ) noexcept
785
673
  obj_need_call = ::AllData::type_need_call[final_id];
786
674
  }
787
675
  if (obj_need_call) {
788
- try {
789
- obj_private_name = custom_random_string(obj_id, attr_name, obj_need_call);
790
- } catch (RestorePythonException& e) {
791
- e.restore();
676
+ auto private_name_result = custom_random_string(obj_id, attr_name, obj_need_call);
677
+ if (!private_name_result.ok) {
792
678
  return -1;
793
679
  }
680
+ obj_private_name = private_name_result.value;
794
681
  } else {
795
682
  obj_private_name = default_random_string(obj_id, attr_name);
796
683
  }
@@ -832,10 +719,7 @@ id_delattr(const std::string& attr_name, PyObject* obj, PyObject* typ) noexcept
832
719
  if (type_name == NULL) {
833
720
  return -1;
834
721
  }
835
- std::string string_type_name = type_name;
836
- std::string exception_information = "'" + string_type_name + "' objects has no attribute '" + attr_name + "'";
837
- PyErr_SetString(PyExc_AttributeError, exception_information.c_str());
838
- return -1;
722
+ PyErr_Format(PyExc_AttributeError, "'%s' object has no attribute '%s'", type_name, attr_name.c_str());
839
723
  }
840
724
  PyObject* delete_obj = ::AllData::all_object_attr[final_id][obj_id][obj_private_name];
841
725
  ::AllData::all_object_attr[final_id][obj_id].erase(obj_private_name);
@@ -857,12 +741,11 @@ type_delattr(PyObject* typ, const std::string& attr_name) noexcept
857
741
  type_need_call = NULL;
858
742
  }
859
743
  if (type_need_call) {
860
- try {
861
- final_key = custom_random_string(typ_id, attr_name, type_need_call);
862
- } catch (RestorePythonException& e) {
863
- e.restore();
744
+ auto private_name_result = custom_random_string(typ_id, attr_name, type_need_call);
745
+ if (!private_name_result.ok) {
864
746
  return -1;
865
747
  }
748
+ final_key = private_name_result.value;
866
749
  } else {
867
750
  final_key = default_random_string(typ_id, attr_name);
868
751
  }
@@ -884,9 +767,7 @@ type_delattr(PyObject* typ, const std::string& attr_name) noexcept
884
767
  if (type_name == NULL) {
885
768
  return -1;
886
769
  }
887
- std::string string_type_name = type_name;
888
- std::string message = "type object '" + string_type_name + "' has no attribute '" + attr_name + "'";
889
- PyErr_SetString(PyExc_AttributeError, message.c_str());
770
+ PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '%s'", type_name, attr_name.c_str());
890
771
  return -1;
891
772
  }
892
773
  PyObject* delete_obj = ::AllData::type_attr_dict[typ_id][final_key];
@@ -912,9 +793,7 @@ type_delattr(PyObject* typ, const std::string& attr_name) noexcept
912
793
  if (type_name == NULL) {
913
794
  return -1;
914
795
  }
915
- std::string string_type_name = type_name;
916
- std::string message = "type object '" + string_type_name + "' has no attribute '" + attr_name + "'";
917
- PyErr_SetString(PyExc_AttributeError, message.c_str());
796
+ PyErr_Format(PyExc_AttributeError, "type object '%s' has no attribute '%s'", type_name, attr_name.c_str());
918
797
  return -1;
919
798
  }
920
799
  PyObject* delete_obj = ::AllData::all_type_subclass_attr[final_id][typ_id][final_key];
@@ -1577,12 +1456,11 @@ type_get_final_attr(uintptr_t type_id, const std::string& name) noexcept
1577
1456
  }
1578
1457
  std::string key;
1579
1458
  if (type_need_call != NULL) {
1580
- try {
1581
- key = custom_random_string(type_id, name, type_need_call);
1582
- } catch (RestorePythonException& e) {
1583
- e.restore();
1459
+ auto private_name_result = custom_random_string(type_id, name, type_need_call);
1460
+ if (!private_name_result.ok) {
1584
1461
  return -2; // -2 means exception
1585
1462
  }
1463
+ key = private_name_result.value;
1586
1464
  } else {
1587
1465
  key = default_random_string(type_id, name);
1588
1466
  }
@@ -1616,12 +1494,11 @@ type_get_final_attr(uintptr_t type_id, const std::string& name) noexcept
1616
1494
  if (::AllData::type_need_call.find(now_visited_id) != ::AllData::type_need_call.end()) {
1617
1495
  PyObject* func = ::AllData::type_need_call[now_visited_id];
1618
1496
  if (func != NULL) {
1619
- try {
1620
- key = custom_random_string(now_visited_id, name, func);
1621
- } catch (RestorePythonException& e) {
1622
- e.restore();
1497
+ auto private_name_result = custom_random_string(now_visited_id, name, func);
1498
+ if (!private_name_result.ok) {
1623
1499
  return -2; // -2 means exception
1624
1500
  }
1501
+ key = private_name_result.value;
1625
1502
  } else {
1626
1503
  key = default_random_string(now_visited_id, name);
1627
1504
  }
@@ -1647,12 +1524,11 @@ type_get_final_attr(uintptr_t type_id, const std::string& name) noexcept
1647
1524
  if (::AllData::type_need_call.find(parent_id) != ::AllData::type_need_call.end()) {
1648
1525
  PyObject* func = ::AllData::type_need_call[parent_id];
1649
1526
  if (func != NULL) {
1650
- try {
1651
- key = custom_random_string(parent_id, name, ::AllData::type_need_call[parent_id]);
1652
- } catch (RestorePythonException& e) {
1653
- e.restore();
1527
+ auto private_name_result = custom_random_string(parent_id, name, func);
1528
+ if (!private_name_result.ok) {
1654
1529
  return -2; // -2 means exception
1655
1530
  }
1531
+ key = private_name_result.value;
1656
1532
  } else {
1657
1533
  key = default_random_string(parent_id, name);
1658
1534
  }
@@ -1975,7 +1851,7 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
1975
1851
  return false;
1976
1852
  }
1977
1853
 
1978
- if (!PyDict_Check(data.attrs)) {
1854
+ if (!PyAnyDict_Check(data.attrs)) {
1979
1855
  PyErr_SetString(PyExc_TypeError, "attrs must be a dict");
1980
1856
  return false;
1981
1857
  }
@@ -2050,26 +1926,46 @@ PrivateAttrType_preprocess(PyObject* args, PyObject* kwds, PrivateAttrCreationDa
2050
1926
 
2051
1927
  if (has_slots) {
2052
1928
  PyObject* all_slots = PyDict_GetItemString(data.attrs_copy, "__slots__");
2053
- PyObject* slot_seq = PySequence_Fast(all_slots, "__slots__ must be a sequence");
2054
- if (!slot_seq) {
2055
- return false;
2056
- }
2057
-
2058
- Py_ssize_t slot_len = PySequence_Fast_GET_SIZE(slot_seq);
2059
-
2060
- for (Py_ssize_t j = 0; j < slot_len; j++) {
2061
- PyObject* slot = PySequence_Fast_GET_ITEM(slot_seq, j);
2062
- if (PyUnicode_Check(slot)) {
2063
- const char* slot_cstr = PyUnicode_AsUTF8(slot);
2064
- if (data.private_attrs_vector_string.find((std::string)slot_cstr) != data.private_attrs_vector_string.end()){
2065
- std::string error_msg = "'__slots__' and '__private_attrs__' cannot have the same attribute name: '" + std::string(slot_cstr) + "'";
2066
- PyErr_SetString(PyExc_TypeError, error_msg.c_str());
2067
- Py_DECREF(slot_seq);
1929
+ if (!all_slots) {return false;}
1930
+ if (PyUnicode_Check(all_slots)) {
1931
+ const char* slot_cstr = PyUnicode_AsUTF8(all_slots);
1932
+ if (data.private_attrs_vector_string.find((std::string)slot_cstr) != data.private_attrs_vector_string.end()){
1933
+ std::string error_msg = "'__slots__' and '__private_attrs__' cannot have the same attribute name: '" + std::string(slot_cstr) + "'";
1934
+ PyErr_SetString(PyExc_TypeError, error_msg.c_str());
1935
+ return false;
1936
+ }
1937
+ } else {
1938
+ PyObject* slot_seq;
1939
+ if (PyAnyDict_Check(all_slots)) {
1940
+ // use the key of the dict as the slot name
1941
+ PyObject* keys = PyDict_Keys(all_slots);
1942
+ if (!keys) {
2068
1943
  return false;
2069
1944
  }
1945
+ slot_seq = keys;
1946
+ } else {
1947
+ slot_seq = PySequence_Fast(all_slots, "__slots__ must be a sequence");
1948
+ }
1949
+ if (!slot_seq) {
1950
+ return false;
1951
+ }
1952
+
1953
+ Py_ssize_t slot_len = PySequence_Fast_GET_SIZE(slot_seq);
1954
+
1955
+ for (Py_ssize_t j = 0; j < slot_len; j++) {
1956
+ PyObject* slot = PySequence_Fast_GET_ITEM(slot_seq, j);
1957
+ if (PyUnicode_Check(slot)) {
1958
+ const char* slot_cstr = PyUnicode_AsUTF8(slot);
1959
+ if (data.private_attrs_vector_string.find((std::string)slot_cstr) != data.private_attrs_vector_string.end()){
1960
+ std::string error_msg = "'__slots__' and '__private_attrs__' cannot have the same attribute name: '" + std::string(slot_cstr) + "'";
1961
+ PyErr_SetString(PyExc_TypeError, error_msg.c_str());
1962
+ Py_DECREF(slot_seq);
1963
+ return false;
1964
+ }
1965
+ }
2070
1966
  }
1967
+ Py_DECREF(slot_seq);
2071
1968
  }
2072
- Py_DECREF(slot_seq);
2073
1969
  }
2074
1970
 
2075
1971
  Py_ssize_t bases_len = PyTuple_GET_SIZE(data.bases);
@@ -2312,12 +2208,11 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2312
2208
  for (auto& [key, value]: data.need_remove_itself) {
2313
2209
  std::string final_key;
2314
2210
  if (data.private_func) {
2315
- try {
2316
- final_key = custom_random_string(type_id, key, data.private_func);
2317
- } catch (RestorePythonException& e) {
2318
- e.restore();
2211
+ auto private_name_result = custom_random_string(type_id, key, data.private_func);
2212
+ if (!private_name_result.ok) {
2319
2213
  return false;
2320
2214
  }
2215
+ final_key = private_name_result.value;
2321
2216
  } else {
2322
2217
  final_key = default_random_string(type_id, key);
2323
2218
  }
@@ -2341,12 +2236,11 @@ PrivateAttrType_postprocess(PyObject* new_type, PrivateAttrCreationData& data) n
2341
2236
  for (auto& [key, value]: map) {
2342
2237
  std::string final_key;
2343
2238
  if (data.private_func) {
2344
- try {
2345
- final_key = custom_random_string(type_id, key, data.private_func);
2346
- } catch (RestorePythonException& e) {
2347
- e.restore();
2239
+ auto private_name_result = custom_random_string(type_id, key, data.private_func);
2240
+ if (!private_name_result.ok) {
2348
2241
  return false;
2349
2242
  }
2243
+ final_key = private_name_result.value;
2350
2244
  } else {
2351
2245
  final_key = default_random_string(type_id, key);
2352
2246
  }
@@ -3136,7 +3030,7 @@ PrivateModule_setattro(PyObject* self, PyObject* name, PyObject* value) noexcept
3136
3030
  const size_t num_attrs = sizeof(unsetable_attrs) / sizeof(unsetable_attrs[0]);
3137
3031
  for (size_t i = 0; i < num_attrs; ++i) {
3138
3032
  if (strcmp(name_cstr, unsetable_attrs[i]) == 0) {
3139
- PyErr_Format(PyExc_AttributeError, "attribute '%s' of 'private_attribute_module' objects is not writable", name_cstr);
3033
+ PyErr_Format(PyExc_AttributeError, "attribute '%s' of 'private_attribute.private_attribute_module' objects is not writable", name_cstr);
3140
3034
  return -1;
3141
3035
  }
3142
3036
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 2.0.1
3
+ Version: 2.0.3
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='2.0.1',
21
+ version='2.0.3',
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.',