private-attribute-cpp 1.3.3__tar.gz → 1.3.4__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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Locked-chess-official
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -1,18 +1,20 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.3.3
3
+ Version: 1.3.4
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
7
7
  Author-email: 13140752715@example.com
8
8
  License: MIT
9
9
  Description-Content-Type: text/markdown
10
+ License-File: LICENSE
10
11
  Dynamic: author
11
12
  Dynamic: author-email
12
13
  Dynamic: description
13
14
  Dynamic: description-content-type
14
15
  Dynamic: home-page
15
16
  Dynamic: license
17
+ Dynamic: license-file
16
18
  Dynamic: summary
17
19
 
18
20
  # Private Attribute (c++ implementation)
@@ -247,7 +249,6 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
247
249
  - Finally the `_PrivateWrap` object will be recoveried to the original object.
248
250
  - One class defined in another class cannot use another class's private attribute.
249
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__`.
250
- - When combine with other metaclass, be ensure that the parent metaclass has no classmethod that can set subclasses' attributes. If it has, it will fail on new metaclass because the new metaclass you defined and registered will be immutable.
251
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.
252
253
 
253
254
  ## License
@@ -230,7 +230,6 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
230
230
  - Finally the `_PrivateWrap` object will be recoveried to the original object.
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
- - When combine with other metaclass, be ensure that the parent metaclass has no classmethod that can set subclasses' attributes. If it has, it will fail on new metaclass because the new metaclass you defined and registered will be immutable.
234
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.
235
234
 
236
235
  ## License
@@ -935,16 +935,19 @@ PrivateWrap_type_params(PyObject* obj, void* /*closure*/)
935
935
  return type_params;
936
936
  }
937
937
 
938
+ static const char* PrivateWrap_result_doc = "the final result of decorating";
939
+ static const char* PrivateWrap_funcs_doc = "the original functions";
940
+
938
941
  static PyGetSetDef PrivateWrap_getset[] = {
939
- {"result", (getter)PrivateWrap_result, NULL, "final result", NULL},
940
- {"funcs", (getter)PrivateWrap_funcs, NULL, "funcs", NULL},
941
- {"__wrapped__", (getter)PrivateWrap_result, NULL, "final result", NULL},
942
- {"__doc__", (getter)PrivateWrap_doc, NULL, "doc", NULL},
943
- {"__module__", (getter)PrivateWrap_module, NULL, "module", NULL},
944
- {"__name__", (getter)PrivateWarp_name, NULL, "name", NULL},
945
- {"__qualname__", (getter)PrivateWrap_qualname, NULL, "qualname", NULL},
946
- {"__annotate__", (getter)PrivateWrap_annotate, NULL, "annotate", NULL},
947
- {"__type_params__", (getter)PrivateWrap_type_params, NULL, "type_params", NULL},
942
+ {"result", (getter)PrivateWrap_result, NULL, PrivateWrap_result_doc, NULL},
943
+ {"funcs", (getter)PrivateWrap_funcs, NULL, PrivateWrap_funcs_doc, NULL},
944
+ {"__wrapped__", (getter)PrivateWrap_result, NULL, NULL, NULL},
945
+ {"__doc__", (getter)PrivateWrap_doc, NULL, NULL, NULL},
946
+ {"__module__", (getter)PrivateWrap_module, NULL, NULL, NULL},
947
+ {"__name__", (getter)PrivateWarp_name, NULL, NULL, NULL},
948
+ {"__qualname__", (getter)PrivateWrap_qualname, NULL, NULL, NULL},
949
+ {"__annotate__", (getter)PrivateWrap_annotate, NULL, NULL, NULL},
950
+ {"__type_params__", (getter)PrivateWrap_type_params, NULL, NULL, NULL},
948
951
  {NULL}
949
952
  };
950
953
 
@@ -1070,6 +1073,35 @@ PrivateWrapProxy_call(PrivateWrapProxyObject *self, PyObject *args, PyObject* /*
1070
1073
 
1071
1074
  static void PrivateWrapProxy_dealloc(PrivateWrapProxyObject *self);
1072
1075
  static PyObject* PrivateWrapProxy_New(PyTypeObject *type, PyObject *args, PyObject *kwds);
1076
+ static const char* PrivateWrapProxy_doc = R"(
1077
+ PrivateWrapProxy is a proxy for private attributes.
1078
+ Usage:
1079
+ ```
1080
+ from private_attribute import PrivateWrapProxy, PrivateAttrBase
1081
+
1082
+ class MyClass(PrivateAttrBase):
1083
+ __private_attrs__ = ()
1084
+ @PrivateWrapProxy(decorator)
1085
+ def my_method(self): ...
1086
+
1087
+ @PrivateWrapProxy(decorator)
1088
+ def my_method2(self): ...
1089
+ ```
1090
+ It returned a '_PrivateWrap' object.
1091
+
1092
+ If you need to decorate more function, use like this:
1093
+ ```
1094
+ from private_attribute import PrivateWrapProxy, PrivateAttrBase
1095
+
1096
+ class MyClass(PrivateAttrBase):
1097
+ __private_attrs__ = ()
1098
+ @PrivateWrapProxy(decorator)
1099
+ def my_method(self): ...
1100
+
1101
+ @PrivateWrapProxy(my_method.some_decorator, my_method)
1102
+ def my_method(self): ...
1103
+ ```
1104
+ )";
1073
1105
 
1074
1106
  static PyTypeObject PrivateWrapProxyType = {
1075
1107
  PyVarObject_HEAD_INIT(NULL, 0)
@@ -1092,7 +1124,7 @@ static PyTypeObject PrivateWrapProxyType = {
1092
1124
  0, // tp_setattro
1093
1125
  0, // tp_as_buffer
1094
1126
  Py_TPFLAGS_DEFAULT, // tp_flags
1095
- "PrivateWrapProxy", // tp_doc
1127
+ PrivateWrapProxy_doc, // tp_doc
1096
1128
  0, // tp_traverse
1097
1129
  0, // tp_clear
1098
1130
  0, // tp_richcompare
@@ -1307,66 +1339,45 @@ static PyObject* PrivateAttrType_getattr(PyObject* cls, PyObject* name);
1307
1339
  static int PrivateAttrType_setattr(PyObject* cls, PyObject* name, PyObject* value);
1308
1340
  static void PrivateAttrType_del(PyObject* cls);
1309
1341
 
1310
- static int
1311
- PrivateAttrType_init(PyObject* self, PyObject* args, PyObject* kwds)
1312
- {
1313
- PyTypeObject* base = Py_TYPE(self);
1314
- while (base->tp_init == PrivateAttrType_init) {
1315
- base = base->tp_base;
1316
- }
1317
- if (base->tp_init == NULL) {
1318
- int result = PyType_Type.tp_init(self, args, kwds);
1319
- if (result == 0) {
1320
- ensure_tp((PyTypeObject*)self);
1321
- }
1322
- return result;
1323
- }
1324
- int result = base->tp_init(self, args, kwds);
1325
- if (result == 0) {
1326
- ensure_tp((PyTypeObject*)self);
1327
- }
1328
- return result;
1329
- }
1330
-
1331
1342
  static PyTypeObject PrivateAttrType = {
1332
1343
  PyVarObject_HEAD_INIT(NULL, 0)
1333
- "private_attribute.PrivateAttrType", // tp_name
1334
- sizeof(PrivateAttrTypeObject), // tp_basicsize
1335
- 0, // tp_itemsize
1336
- (destructor)PrivateAttrType_del, // tp_dealloc
1337
- 0, // tp_print
1338
- 0, // tp_getattr
1339
- 0, // tp_setattr
1340
- 0, // tp_reserved
1341
- 0, // tp_repr
1342
- 0, // tp_as_number
1343
- 0, // tp_as_sequence
1344
- 0, // tp_as_mapping
1345
- 0, // tp_hash
1346
- 0, // tp_call
1347
- 0, // tp_str
1348
- (getattrofunc)PrivateAttrType_getattr, // tp_getattro
1349
- (setattrofunc)PrivateAttrType_setattr, // tp_setattro
1350
- 0, // tp_as_buffer
1351
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
1352
- "metaclass for private attributes", // tp_doc
1353
- 0, // tp_travers
1354
- 0, // tp_clear
1355
- 0, // tp_richcompare
1356
- 0, // tp_weaklistoffset
1357
- 0, // tp_iter
1358
- 0, // tp_iternext
1359
- 0, // tp_methods
1360
- 0, // tp_members
1361
- 0, // tp_getset
1362
- &PyType_Type, // tp_base
1363
- 0, // tp_dict
1364
- 0, // tp_descr_get
1365
- 0, // tp_descr_set
1366
- 0, // tp_dictoffset
1367
- PrivateAttrType_init, // tp_init
1368
- 0, // tp_alloc
1369
- (newfunc)PrivateAttrType_new, // tp_new
1344
+ "private_attribute.PrivateAttrType", // tp_name
1345
+ sizeof(PrivateAttrTypeObject), // tp_basicsize
1346
+ 0, // tp_itemsize
1347
+ (destructor)PrivateAttrType_del, // tp_dealloc
1348
+ 0, // tp_print
1349
+ 0, // tp_getattr
1350
+ 0, // tp_setattr
1351
+ 0, // tp_reserved
1352
+ 0, // tp_repr
1353
+ 0, // tp_as_number
1354
+ 0, // tp_as_sequence
1355
+ 0, // tp_as_mapping
1356
+ 0, // tp_hash
1357
+ 0, // tp_call
1358
+ 0, // tp_str
1359
+ (getattrofunc)PrivateAttrType_getattr, // tp_getattro
1360
+ (setattrofunc)PrivateAttrType_setattr, // tp_setattro
1361
+ 0, // tp_as_buffer
1362
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, // tp_flags
1363
+ "metaclass for private attributes", // tp_doc
1364
+ 0, // tp_travers
1365
+ 0, // tp_clear
1366
+ 0, // tp_richcompare
1367
+ 0, // tp_weaklistoffset
1368
+ 0, // tp_iter
1369
+ 0, // tp_iternext
1370
+ 0, // tp_methods
1371
+ 0, // tp_members
1372
+ 0, // tp_getset
1373
+ &PyType_Type, // tp_base
1374
+ 0, // tp_dict
1375
+ 0, // tp_descr_get
1376
+ 0, // tp_descr_set
1377
+ 0, // tp_dictoffset
1378
+ 0, // tp_init
1379
+ 0, // tp_alloc
1380
+ (newfunc)PrivateAttrType_new, // tp_new
1370
1381
  };
1371
1382
 
1372
1383
  static PyObject*
@@ -2027,6 +2038,7 @@ ensure_subclass_tp(PyTypeObject* type_instance)
2027
2038
  continue;
2028
2039
  }
2029
2040
  ensure_tp((PyTypeObject*)subclass);
2041
+ ensure_subclass_tp((PyTypeObject*)subclass);
2030
2042
  }
2031
2043
  Py_DECREF(type_subclasses);
2032
2044
  }
@@ -2303,6 +2315,9 @@ PrivateAttrType_del(PyObject* cls)
2303
2315
  (Py_TYPE(cls))->tp_free(cls);
2304
2316
  }
2305
2317
 
2318
+ static const char* PrivateAttrBase_doc = "The class to help to create private attribute. "
2319
+ "It does not have any special behavior, but it can be used as a base class for PrivateAttrType to avoid some conflicts with other metaclasses.";
2320
+
2306
2321
  // PrivateAttrBase
2307
2322
  static PyObject*
2308
2323
  create_private_attr_base_simple(void)
@@ -2329,6 +2344,7 @@ create_private_attr_base_simple(void)
2329
2344
  }
2330
2345
  PyDict_SetItemString(dict, "__private_attrs__", private_attrs);
2331
2346
  PyDict_SetItemString(dict, "__slots__", private_attrs);
2347
+ PyDict_SetItemString(dict, "__doc__", PyUnicode_FromString(PrivateAttrBase_doc));
2332
2348
  PyObject *args = PyTuple_Pack(3, name, bases, dict);
2333
2349
  PyObject* base_type;
2334
2350
  if (args) {
@@ -2406,10 +2422,10 @@ PrivateTempObject_kwds(PyObject* self, void* /*closure*/)
2406
2422
  }
2407
2423
 
2408
2424
  static PyGetSetDef PrivateTempObject_getsets[] = {
2409
- {"name", (getter)PrivateTempObject_name, NULL, NULL, NULL},
2410
- {"bases", (getter)PrivateTempObject_base, NULL, NULL, NULL},
2411
- {"attrs", (getter)PrivateTempObject_attrs, NULL, NULL, NULL},
2412
- {"kwds", (getter)PrivateTempObject_kwds, NULL, NULL, NULL},
2425
+ {"name", (getter)PrivateTempObject_name, NULL, "The name for submetaclass.__new__ argument 1", NULL},
2426
+ {"bases", (getter)PrivateTempObject_base, NULL, "The base classes for submetaclass.__new__ argument 2", NULL},
2427
+ {"attrs", (getter)PrivateTempObject_attrs, NULL, "The attributes for submetaclass.__new__ argument 3", NULL},
2428
+ {"kwds", (getter)PrivateTempObject_kwds, NULL, "The keyword arguments for submetaclass.__new__", NULL},
2413
2429
  {NULL}
2414
2430
  };
2415
2431
 
@@ -2526,7 +2542,6 @@ register_metaclass(PyObject* /*self*/, PyObject* metaclass)
2526
2542
  ((PyTypeObject*)metaclass)->tp_getattro = PrivateAttrType_getattr;
2527
2543
  ((PyTypeObject*)metaclass)->tp_setattro = PrivateAttrType_setattr;
2528
2544
  ((PyTypeObject*)metaclass)->tp_finalize = register_finalize;
2529
- ((PyTypeObject*)metaclass)->tp_init = PrivateAttrType_init;
2530
2545
  ((PyTypeObject*)metaclass)->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
2531
2546
  Py_RETURN_NONE;
2532
2547
  }
@@ -2554,7 +2569,6 @@ ensure_metaclass_tp(PyObject* /*self*/, PyObject* metaclass)
2554
2569
  ((PyTypeObject*)metaclass)->tp_getattro = PrivateAttrType_getattr;
2555
2570
  ((PyTypeObject*)metaclass)->tp_setattro = PrivateAttrType_setattr;
2556
2571
  ((PyTypeObject*)metaclass)->tp_finalize = register_finalize;
2557
- ((PyTypeObject*)metaclass)->tp_init = PrivateAttrType_init;
2558
2572
  }
2559
2573
  Py_RETURN_NONE;
2560
2574
  }
@@ -2638,13 +2652,52 @@ static PyGetSetDef PrivateModule_getsetters[] = {
2638
2652
  {NULL}
2639
2653
  };
2640
2654
 
2655
+ static const char* prepare_and_postprocess_doc = R"(function for custom metaclass to create private attributes class.
2656
+
2657
+ def prepare(name: str, bases: tuple, attrs: dict, **kwds) -> tempobject:
2658
+ the function to prepare for creating private attributes class. It will return a temporary object which has the same information as the arguments. The custom metaclass can call this function in its __prepare__ method to get the information for creating private attributes class.
2659
+
2660
+ def postprocess(type: type, tmp: tempobject) -> None:
2661
+ the function to postprocess for creating private attributes class. The custom metaclass can call this
2662
+
2663
+ def register_metaclass(metaclass: type) -> None:
2664
+ the function to register custom metaclass. The custom metaclass must call this function to register itself before creating any private attributes class, otherwise the private attributes class created by this custom metaclass will not work.
2665
+
2666
+ All usage of this module should be like:
2667
+ ```
2668
+ from abc import ABCMeta
2669
+ import private_attribute
2670
+
2671
+ class PrivateAbcMeta(ABCMeta):
2672
+ def __new__(cls, *args, **kwargs):
2673
+ temp = private_attribute.prepare(*args, **kwargs)
2674
+ typ = super().__new__(cls, temp.name, temp.bases, temp.attrs, **temp.kwds)
2675
+ private_attribute.postprocess(typ, temp)
2676
+ return typ
2677
+
2678
+
2679
+ private_attribute.register_metaclass(PrivateAbcMeta)
2680
+ ```
2681
+ )";
2682
+
2683
+ static const char* ensure_type_doc = R"(function for custom metaclass to ensure the type is a private attributes class.
2684
+
2685
+ def ensure_type(type: type) -> None:
2686
+ the function to ensure the type is a private attributes class `tp_getattro`, `tp_setattro` and `tp_finalizer`.
2687
+ )";
2688
+
2689
+ static const char* ensure_metaclass_doc = R"(function for custom metaclass to ensure the metaclass is registered.
2690
+ def ensure_metaclass(metaclass: type) -> None:
2691
+ the function to ensure the metaclass `tp_getattro`, `tp_setattro` and `tp_finalizer`.
2692
+ )";
2693
+
2641
2694
  static PyMethodDef PrivateModule_methods[] = {
2642
2695
  {"__dir__", (PyCFunction)PrivateModule_dir, METH_NOARGS, NULL},
2643
- {"prepare", (PyCFunction)prepare_for_PrivateAttr, METH_VARARGS | METH_KEYWORDS, NULL},
2644
- {"postprocess", (PyCFunction)postprocess_for_PrivateAttr, METH_VARARGS, NULL},
2645
- {"register_metaclass", (PyCFunction)register_metaclass, METH_O, NULL},
2646
- {"ensure_type", (PyCFunction)ensure_type_tp, METH_O, NULL},
2647
- {"ensure_metaclass", (PyCFunction)ensure_metaclass_tp, METH_O, NULL},
2696
+ {"prepare", (PyCFunction)prepare_for_PrivateAttr, METH_VARARGS | METH_KEYWORDS, prepare_and_postprocess_doc},
2697
+ {"postprocess", (PyCFunction)postprocess_for_PrivateAttr, METH_VARARGS, prepare_and_postprocess_doc},
2698
+ {"register_metaclass", (PyCFunction)register_metaclass, METH_O, prepare_and_postprocess_doc},
2699
+ {"ensure_type", (PyCFunction)ensure_type_tp, METH_O, ensure_type_doc},
2700
+ {"ensure_metaclass", (PyCFunction)ensure_metaclass_tp, METH_O, ensure_metaclass_doc},
2648
2701
  {NULL} // Sentinel
2649
2702
  };
2650
2703
 
@@ -2682,10 +2735,29 @@ static PyTypeObject PrivateModuleType = {
2682
2735
  &PyModule_Type, //tp_base
2683
2736
  };
2684
2737
 
2738
+ static const char* module_doc = R"(
2739
+ A module that provides a metaclass for creating classes with private attributes.
2740
+ Private attributes are defined in the `__private_attrs__` sequence and are only
2741
+ You can use the `PrivateAttrBase` metaclass to create classes with private attributes.
2742
+ The attributes which are private are not on the instance's `__dict__` and cannot be accessed outside
2743
+ but in the classmethods it is reachable.
2744
+ Usage example:
2745
+ ```python
2746
+ class MyClass(PrivateAttrBase):
2747
+ __private_attrs__ = ('_private_attr1',)
2748
+ def __init__(self):
2749
+ self._private_attr1 = 1
2750
+
2751
+ @property
2752
+ def public_attr1(self):
2753
+ return self._private_attr1
2754
+ ```
2755
+ )";
2756
+
2685
2757
  static PyModuleDef def = {
2686
2758
  PyModuleDef_HEAD_INIT,
2687
2759
  "private_attribute",
2688
- NULL,
2760
+ module_doc,
2689
2761
  0,
2690
2762
  NULL,
2691
2763
  NULL,
@@ -1,18 +1,20 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: private_attribute_cpp
3
- Version: 1.3.3
3
+ Version: 1.3.4
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
7
7
  Author-email: 13140752715@example.com
8
8
  License: MIT
9
9
  Description-Content-Type: text/markdown
10
+ License-File: LICENSE
10
11
  Dynamic: author
11
12
  Dynamic: author-email
12
13
  Dynamic: description
13
14
  Dynamic: description-content-type
14
15
  Dynamic: home-page
15
16
  Dynamic: license
17
+ Dynamic: license-file
16
18
  Dynamic: summary
17
19
 
18
20
  # Private Attribute (c++ implementation)
@@ -247,7 +249,6 @@ TypeError: Can't instantiate abstract class MyClass without an implementation fo
247
249
  - Finally the `_PrivateWrap` object will be recoveried to the original object.
248
250
  - One class defined in another class cannot use another class's private attribute.
249
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__`.
250
- - When combine with other metaclass, be ensure that the parent metaclass has no classmethod that can set subclasses' attributes. If it has, it will fail on new metaclass because the new metaclass you defined and registered will be immutable.
251
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.
252
253
 
253
254
  ## License
@@ -19,7 +19,7 @@ readme = open('README.md').read()
19
19
 
20
20
  setup(
21
21
  name='private_attribute_cpp',
22
- version='1.3.3',
22
+ version='1.3.4',
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.',