db-attribute 2.1__py3-none-any.whl

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,942 @@
1
+ import copy, ast, functools, inspect, sys
2
+ import datetime
3
+ import pickle
4
+ import json
5
+ import orjson
6
+ import collections
7
+
8
+ def MethodDecorator(func=None, /, convert_arguments=True, call_the_decoreted_func=False, call_update_obj=True):
9
+ """
10
+ decorator for methods, where updated obj | args can convert
11
+ :param convert_arguments: if True (default), convert all arguments from args and kwargs to DbClass objects (if this type obj is supported) (not convert if this class methode)
12
+ :param call_the_decoreted_func: if False (default), call this func from self._standart_class, if True, call from self.__class__
13
+ :param call_update_obj: if True (default), call the self._update_obj(), set False if func not updated the obj
14
+ :return:
15
+ """
16
+ def wrap(func):
17
+ @functools.wraps(func)
18
+ def wrapper(self, *args, **kwargs):
19
+ if convert_arguments:
20
+ args = (cheaker.create_db_class(i, _first_container=self._first_container if self._first_container else _FirstContainer(self)) for i in args)
21
+ kwargs = {key: cheaker.create_db_class(kwargs[key], _first_container=self._first_container if self._first_container else _FirstContainer(self)) for key in kwargs}
22
+
23
+ if call_the_decoreted_func:
24
+ data = func(self, *args, **kwargs)
25
+ if call_update_obj:
26
+ self._update_obj()
27
+ return data
28
+
29
+ data = getattr(self._standart_class, func.__name__)(self, *args, **kwargs)
30
+ if call_update_obj:
31
+ self._update_obj()
32
+ return data
33
+ return wrapper
34
+ if func:
35
+ return wrap(func)
36
+ return wrap
37
+
38
+ def DbClassDecorator(cls=None, /, convert_arguments_ioperation_methodes=False, convert_arguments_changes_methodes=True, list_of_non_replaceable_methodes=None, list_of_methodes_with_converted_arguments=None, methode__new__needs_arguments=False):
39
+ """
40
+ Use DbClassDecorator for
41
+ 1) set cls._standart_class (example: for DbList standart class is list)
42
+ 2) automatic create __setitem__, __delitem__, __setattr__, __delattr__, __iadd__, __isub__, __imul__, __imatmul__, __ipow__, __idiv__, __ifloordiv__, __itruediv__, __ilshift__, __irshift__, __imod__, __ior__, __iand__, __ixor__
43
+ (DbClassDecorator not created __add__, __sub__, __mul__ and other methodes!)
44
+ If a class has any methods (example: __iadd__), these methods are not replaced.
45
+ But if the parent class has these methods, they will be replaced.
46
+ So use the list_of_non_replaceable_methodes to set a list of non-replaceable methods
47
+ :param convert_arguments_ioperation_methodes: convert input arguments of i operation metodes (__iadd__) to DbClasses
48
+ :param convert_arguments_changes_methodes: convert input arguments of changes metodes (__delitem__, __setattr__) to DbClasses
49
+ :param list_of_non_replaceable_methodes: list of method names that belong to the parent class and will not be replaced by the decorator, ex: ['__iadd__']
50
+ :param list_of_methodes_with_converted_arguments: list of methods that need to be individually replaced with arguments, but param convert_arguments... is False, ex: ['__iadd__']
51
+ :return:
52
+ """
53
+ if list_of_non_replaceable_methodes is None:
54
+ list_of_non_replaceable_methodes = []
55
+ if list_of_methodes_with_converted_arguments is None:
56
+ list_of_methodes_with_converted_arguments = []
57
+ def wrapper(cls):
58
+ if cls.__dict__.get('_standart_class', None) is None:
59
+ ind = cls.__mro__.index(DbClass)
60
+ if ind + 1 == len(cls.__mro__):
61
+ raise f'The DbClass the last in {cls}.__mro__, please set _standart_class, or add perent to class'
62
+ cls._standart_class = cls.__mro__[ind + 1]
63
+ if cls.__dict__.get('_methode__new__needs_arguments', None) is None:
64
+ cls._methode__new__needs_arguments = methode__new__needs_arguments
65
+
66
+ def getimethod(truefunc, namefunc=''):
67
+ convert_arguments = convert_arguments_ioperation_methodes
68
+ if namefunc in list_of_methodes_with_converted_arguments:
69
+ convert_arguments = True
70
+ def wrapper(self, *args, _update=True, **kwargs):
71
+ if convert_arguments:
72
+ args = (cheaker.create_db_class(i, _first_container=self._first_container) for i in args)
73
+ kwargs = {key: cheaker.create_db_class(kwargs[key], _first_container=self._first_container) for key in kwargs}
74
+ obj = truefunc(self, *args, **kwargs)
75
+ if _update and isinstance(obj, DbClass):
76
+ obj._update_obj()
77
+ return obj
78
+ return wrapper
79
+
80
+ def getmethod(truefunc, namefunc=''):
81
+ convert_arguments = convert_arguments_changes_methodes
82
+ if namefunc in list_of_methodes_with_converted_arguments:
83
+ convert_arguments = True
84
+ def wrapper(self, *args, _update=True, **kwargs):
85
+ if convert_arguments:
86
+ args = (cheaker.create_db_class(i, _first_container=self._first_container) for i in args)
87
+ kwargs = {key: cheaker.create_db_class(kwargs[key], _first_container=self._first_container) for key in kwargs}
88
+
89
+ data = truefunc(self, *args, **kwargs)
90
+ if _update: self._update_obj()
91
+ return data
92
+ return wrapper
93
+
94
+ for namefunc in ['__iadd__', '__isub__', '__imul__', '__imatmul__', '__ipow__', '__idiv__', '__ifloordiv__', '__itruediv__', '__ilshift__', '__irshift__', '__imod__', '__ior__', '__iand__', '__ixor__']:
95
+ if hasattr(cls, namefunc) and namefunc not in cls.__dict__ and namefunc not in list_of_non_replaceable_methodes:
96
+ func = getimethod(getattr(cls, namefunc), namefunc)
97
+ setattr(cls, namefunc, func)
98
+ for namefunc in ['__setitem__', '__delitem__', '__setattr__', '__delattr__']:
99
+ if hasattr(cls, namefunc) and namefunc not in cls.__dict__ and namefunc not in list_of_non_replaceable_methodes:
100
+ func = getmethod(getattr(cls, namefunc), namefunc)
101
+ setattr(cls, namefunc, func)
102
+ return cls
103
+ if cls is None:
104
+ return wrapper
105
+ return wrapper(cls)
106
+
107
+ class _FirstContainer:
108
+ def __init__(self, _first_container=None):
109
+ self.container = _first_container.container if isinstance(_first_container, _FirstContainer) else _first_container
110
+
111
+ @DbClassDecorator
112
+ class DbClass:
113
+ _standart_class = object
114
+ _obj_dbattribute = None
115
+ _name_attribute = None
116
+ _first_container = None
117
+ _call_init_when_reconstruct = False
118
+ _methode__new__needs_arguments = False
119
+
120
+ def __new__(cls, *args, _use_db=False, _obj_dbattribute=None, _convert_arguments=True, _name_attribute=None, _first_container=None, **kwargs):
121
+ if not _use_db:
122
+ if cls._methode__new__needs_arguments:
123
+ obj = cls._standart_class.__new__(cls._standart_class, *args, **kwargs)
124
+ else:
125
+ obj = cls._standart_class.__new__(cls._standart_class)
126
+ obj.__init__(*args, **kwargs)
127
+ return obj
128
+ if cls._methode__new__needs_arguments:
129
+ return cls._standart_class.__new__(cls, *args, **kwargs)
130
+ return cls._standart_class.__new__(cls)
131
+
132
+ def __init__(self, *args, _use_db=False, _obj_dbattribute=None, _convert_arguments=True, _name_attribute=None, _first_container=None, _call_init=True, **kwargs):
133
+ if _obj_dbattribute:
134
+ self.__dict__['_obj_dbattribute'] = _obj_dbattribute
135
+ if _name_attribute:
136
+ self.__dict__['_name_attribute'] = _name_attribute
137
+ if self._first_container is None:
138
+ if _first_container is None:
139
+ self.__dict__['_first_container'] = _FirstContainer(self)
140
+ else:
141
+ if not isinstance(_first_container, _FirstContainer):
142
+ _first_container = _FirstContainer(_first_container)
143
+ self.__dict__['_first_container'] = _first_container
144
+ if _call_init:
145
+ super().__init__(*args, **kwargs)
146
+ def __repr__(self):
147
+ return self.__get_repr__(set()) if hasattr(self, '__get_repr__') else super().__repr__()
148
+ def __reduce_ex__(self, protocol):
149
+ temp = super().__reduce_ex__(protocol)
150
+ if len(temp) >= 3 and temp[2] is not None:
151
+ temp = list(temp)
152
+ temp[2] = {key: convert_atr_value_to_json_value(temp[2][key]) for key in temp[2] if key not in {'_obj_dbattribute', '_name_attribute', '_first_container'}}
153
+ if len(temp[2]) == 0:
154
+ temp[2] = None
155
+ temp = tuple(temp)
156
+ return temp
157
+
158
+ def _update_obj(self):
159
+ #print(f'update {self} {self._first_container.container if self._first_container else self._first_container}')
160
+ if self._first_container and self._first_container.container and self._first_container.container._obj_dbattribute:
161
+ self._first_container.container._obj_dbattribute._db_attribute_container_update(self._first_container.container._name_attribute, self._first_container.container)
162
+
163
+ def dumps(self, _return_json=True):
164
+ """
165
+ If you create dumps methode for your class, yours methode must return the dict object with keys:
166
+ key 't': type - type of this obj, example: {'t': 'DbList', 'd': [1, 2, 3]} (required key).
167
+ key 'd': data - main data (if you realeseted loads methode, tou can rename this key: use 'd'/'data' and other, it doesn't matter),
168
+ example1 (DbDict): {'t': 'DbDict', 'd': {'0': 1, '1': 2, '2': 3}, 'dk': {'0': 'int', '1': 'int', '2': 'int'}}
169
+ example2 (Develp's Db class): {'t': 'DbUserClass', 'd': {'name': *name*, 'age': *age*, 'books': *jsonDbList*}}
170
+ *and others keys | Develop's keys*
171
+ key 'dk': data key (used DbDict)
172
+ Develop ken create his own keys in dump, and use in load - all dict object dump and load, with json
173
+ required param: _return_json - see documentation
174
+ :param _return_json: if false - return dict, if true - return str: json.dumps(dict)
175
+ """
176
+ data = pickle.dumps(self).decode('latin1')
177
+ if _return_json:
178
+ return json.dumps({'t': self.__class__.__name__, 'd': data}, ensure_ascii=False)
179
+ return {'t': self.__class__.__name__, 'd': data}
180
+
181
+ @classmethod
182
+ def loads(cls, tempdata: str | dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
183
+ """
184
+ (the use of these parameters (_obj_dbattribute, _name_attribute and _first_container) is not intended - they are used inside the project.)
185
+ If you need to create a "loads" method, please give it the name "_loads".
186
+ For create loads methode you can:
187
+ 1) see the _loads methodes of DbList, DbDict, DbDatetime and other... (for example)
188
+ 2) It's all :) What do you do? Do you read this? Who are you? How much time do you spend on documentation?
189
+ Did you know that this documentation is already outdated by several versions?
190
+ An anecdote: A programmer once created a function and wrote its documentation.
191
+ After a few versions, the function changed completely, and the documentation became outdated.
192
+ Another programmer read the anecdote and was confused about the documentation, as it was no longer relevant.
193
+
194
+ :param tempdata: the dumps obj, example: tempdata = {'t': DbList, 'd': [1, 2, 3]}, or json.loads(tempdata) = {'t': DbList, 'd': [1, 2, 3]}
195
+ :param _obj_dbattribute: link to dbattribute obj
196
+ :param _name_attribute: name this attribute
197
+ :param _first_container: link to 'first container', example: a = [1, [2]] for [2] the 'first container' the [1, [2]]
198
+ :return:
199
+ """
200
+ if isinstance(tempdata, str):
201
+ tempdata = orjson.loads(tempdata)
202
+ if (not isinstance(tempdata, dict)) or 't' not in tempdata:
203
+ raise Exception(
204
+ f"load error: {tempdata} is not dict or don't have the 't' key"
205
+ )
206
+ loadcls = cheaker.db_class_name_to_db_class.get(tempdata['t'], None)
207
+ if loadcls is None:
208
+ raise Exception(
209
+ f"load error: cheaker don't support the {tempdata['t']}, add this class to cheaker"
210
+ )
211
+ if hasattr(loadcls, '_loads'):
212
+ return loadcls._loads(tempdata, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
213
+ return cheaker.create_db_class(pickle.loads(tempdata['d'].encode('latin1')), _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
214
+
215
+ @DbClassDecorator(list_of_methodes_with_converted_arguments=['__iadd__'])
216
+ class DbList(DbClass, list):
217
+ _methode__new__needs_arguments = True
218
+ def __init__(self, *args, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
219
+ super().__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False)
220
+ list.__init__(self, *args, **kwargs)
221
+ if _convert_arguments:
222
+ self.__convert_arguments__()
223
+ def __get_repr__(self, Objs: set, now: int = 0):
224
+ return '[' + ', '.join([i.__get_repr__(Objs, now + 1) if hasattr(i, '__get_repr__') else repr(i) for i in self]) + ']'
225
+ @classmethod
226
+ def __convert_to_db__(cls, obj: list, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
227
+ """Converted obj to db object: changed type from list to DbList (you can create yourclass method '__convert_to_db__')"""
228
+ if isinstance(obj, Tlist):
229
+ obj.__class__ = cls
230
+ DbClass.__init__(obj, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
231
+ obj.__convert_arguments__()
232
+ return obj
233
+ return cls(obj, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
234
+
235
+ def __convert_from_db__(self):
236
+ """
237
+ Currently, this method is not implemented and is not supported. However, we plan to implement and support it in future updates.
238
+ Converted db object to object: changed type from DbList to list (you can create yourclass method '__convert_from_db__')
239
+ """
240
+ return NotImplemented
241
+
242
+ def __convert_arguments__(self):
243
+ """Only DbList uses this method"""
244
+ _first_container = self._first_container
245
+ setitem = list.__setitem__
246
+ for key in range(len(self)):
247
+ setitem(self, key, cheaker.create_db_class(self[key], _first_container=_first_container))
248
+
249
+ @MethodDecorator
250
+ def append(self, item, /): pass
251
+ @MethodDecorator
252
+ def insert(self, i, item): pass
253
+ @MethodDecorator
254
+ def pop(self, i=-1): pass
255
+ @MethodDecorator
256
+ def remove(self, item): pass
257
+ @MethodDecorator
258
+ def clear(self): pass
259
+ @MethodDecorator
260
+ def reverse(self): pass
261
+ @MethodDecorator
262
+ def sort(self, /, key=None, reverse=False): pass
263
+ @MethodDecorator
264
+ def extend(self, other): pass
265
+
266
+ def dumps(self, _return_json=True):
267
+ data = [convert_atr_value_to_json_value(i) for i in self]
268
+ if _return_json:
269
+ return json.dumps({'t': self.__class__.__name__, 'd': data})
270
+ return {'t': self.__class__.__name__, 'd': data}
271
+
272
+ @classmethod
273
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
274
+ obj = cls.__new__(cls, _use_db=True)
275
+ if _first_container is None:
276
+ _first_container = _FirstContainer(obj)
277
+ data = [conver_json_value_to_atr_value(value, _first_container=_first_container) for value in tempdata['d']]
278
+ obj.__init__(data, _convert_arguments=False, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
279
+ return obj
280
+
281
+ @DbClassDecorator(list_of_methodes_with_converted_arguments=['__ior__', '__iand__'])
282
+ class DbSet(DbClass, set):
283
+ _call_init_when_reconstruct = True
284
+ _methode__new__needs_arguments = True
285
+
286
+ def __init__(self, *args, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
287
+ super().__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False)
288
+ iterable = set(args[0])
289
+ if _convert_arguments:
290
+ iterable = {cheaker.create_db_class(i, _first_container=self._first_container) for i in iterable}
291
+ set.__init__(self, iterable)
292
+
293
+ def __repr__(self):
294
+ return set(self).__repr__()
295
+
296
+ @classmethod
297
+ def __convert_to_db__(cls, obj: set, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
298
+ return cls(obj, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
299
+
300
+ @MethodDecorator
301
+ def add(self, __element, /): pass
302
+ @MethodDecorator
303
+ def remove(self, __element, /): pass
304
+ @MethodDecorator
305
+ def discard(self, __element, /): pass
306
+ @MethodDecorator
307
+ def update(self, *s): pass
308
+ @MethodDecorator
309
+ def difference_update(self, *s): pass
310
+ @MethodDecorator
311
+ def intersection_update(self, *s): pass
312
+ @MethodDecorator
313
+ def symmetric_difference_update(self, __s, /): pass
314
+
315
+ def dumps(self, _return_json=True):
316
+ data = [convert_atr_value_to_json_value(i) for i in self]
317
+ if _return_json:
318
+ return json.dumps({'t': self.__class__.__name__, 'd': data})
319
+ return {'t': self.__class__.__name__, 'd': data}
320
+
321
+ @classmethod
322
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
323
+ obj = cls.__new__(cls, _use_db=True)
324
+ if _first_container is None:
325
+ _first_container = _FirstContainer(obj)
326
+ data = {conver_json_value_to_atr_value(value, _first_container=_first_container) for value in tempdata['d']}
327
+ obj.__init__(data, _convert_arguments=False, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
328
+ return obj
329
+
330
+ @DbClassDecorator(list_of_methodes_with_converted_arguments=['__ior__'])
331
+ class DbDict(DbClass, dict):
332
+ _methode__new__needs_arguments = True
333
+ def __init__(self, *args, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
334
+ super().__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False)
335
+ dict.__init__(self, *args, **kwargs)
336
+ if _convert_arguments:
337
+ _first_container = self._first_container
338
+ setitem = dict.__setitem__
339
+ for key in self:
340
+ setitem(self, key, cheaker.create_db_class(self[key], _first_container=_first_container))
341
+
342
+ @classmethod
343
+ def __convert_to_db__(cls, obj: dict, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
344
+ return cls(obj, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
345
+
346
+ @MethodDecorator
347
+ def clear(self): pass
348
+ @MethodDecorator
349
+ def pop(self, __key, /): pass
350
+ @MethodDecorator
351
+ def popitem(self): pass
352
+ @MethodDecorator
353
+ def update(self, __m, /, **kwargs): pass
354
+
355
+ def dumps(self, _return_json=True):
356
+ data = {convert_atr_key_to_json_key(i): convert_atr_value_to_json_value(self[i]) for i in self}
357
+ data_key = {convert_atr_key_to_json_key(key): key.__class__.__name__ for key in self if key.__class__ in [tuple, int, bool]}
358
+ if _return_json:
359
+ return json.dumps({'t': self.__class__.__name__, 'dk': data_key, 'd': data})
360
+ return {'t': self.__class__.__name__, 'dk': data_key, 'd': data}
361
+
362
+ @classmethod
363
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
364
+ obj = cls.__new__(cls, _use_db=True)
365
+ if _first_container is None:
366
+ _first_container = _FirstContainer(obj)
367
+ data = {convert_json_key_to_atr_key(key, tempdata['dk'][key] if key in tempdata['dk'] else None)
368
+ : conver_json_value_to_atr_value(value, _first_container=_first_container)
369
+ for key, value in tempdata['d'].items()}
370
+ obj.__init__(data, _convert_arguments=False, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
371
+ return obj
372
+
373
+ @DbClassDecorator
374
+ class DbTuple(DbClass, tuple):
375
+ _methode__new__needs_arguments = True
376
+ _call_init_when_reconstruct = True
377
+ def __new__(cls, *args, _use_db=False, _loads_iterable=False, _obj_dbattribute=None, _convert_arguments=True, _name_attribute=None, _first_container=None, **kwargs):
378
+ if not _use_db:
379
+ return tuple.__new__(DbTuple, *args, **kwargs)
380
+
381
+ if _first_container is None:
382
+ _first_container = _FirstContainer()
383
+
384
+ iterable = tuple(args[0])
385
+ if (not _loads_iterable) and _convert_arguments:
386
+ iterable = tuple((cheaker.create_db_class(i, _first_container=_first_container) for i in iterable))
387
+ if _loads_iterable:
388
+ iterable = tuple((conver_json_value_to_atr_value(value, _first_container=_first_container) for value in iterable))
389
+
390
+ obj = tuple.__new__(DbTuple, iterable)
391
+ if _first_container.container is None:
392
+ _first_container.container = obj
393
+ obj.__dict__['_first_container'] = _first_container
394
+ return obj
395
+
396
+ def __init__(self, *args, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
397
+ super().__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False)
398
+
399
+ def __iadd__(self, other):
400
+ obj = self.__class__(self.__add__(other), _use_db=True, _obj_dbattribute=self._obj_dbattribute, _name_attribute=self._name_attribute, _first_container=self._first_container)
401
+ if self._first_container.container is self:
402
+ obj.__dict__['_first_container'].container = obj
403
+ return obj
404
+
405
+ @classmethod
406
+ def __convert_to_db__(cls, obj: tuple, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
407
+ return cls(obj, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
408
+
409
+ def dumps(self, _return_json=True):
410
+ data = [convert_atr_value_to_json_value(i) for i in self]
411
+ if _return_json:
412
+ return json.dumps({'t': self.__class__.__name__, 'd': data})
413
+ return {'t': self.__class__.__name__, 'd': data}
414
+
415
+ @classmethod
416
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
417
+ obj = cls.__new__(cls, tempdata['d'], _use_db=True, _loads_iterable=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
418
+ obj.__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
419
+ return obj
420
+
421
+ @DbClassDecorator
422
+ class Dbfrozenset(DbClass, frozenset): pass
423
+
424
+ @DbClassDecorator
425
+ class DbDeque(DbClass, collections.deque):
426
+ _methode__new__needs_arguments = True
427
+ def __init__(self, *args, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
428
+ super().__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False)
429
+
430
+ iterable = args[0]
431
+ if _convert_arguments:
432
+ iterable = [cheaker.create_db_class(i, _first_container=self._first_container) for i in iterable]
433
+ collections.deque.__init__(self, iterable)
434
+
435
+ @classmethod
436
+ def __convert_to_db__(cls, obj: collections.deque, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
437
+ return cls(obj, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
438
+
439
+ @DbClassDecorator
440
+ class DbDatetime(DbClass, datetime.datetime):
441
+ _methode__new__needs_arguments = True
442
+ def __init__(self, year, month=None, day=None, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
443
+ super().__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False, **kwargs)
444
+ def __iadd__(self, other):
445
+ obj = cheaker.create_db_class(self.__add__(other), _obj_dbattribute=self._obj_dbattribute, _name_attribute=self._name_attribute, _first_container=self._first_container)
446
+ if self._first_container.container is self: obj.__dict__['_first_container'].container = obj
447
+ return obj
448
+ def __isub__(self, other):
449
+ obj = cheaker.create_db_class(self.__sub__(other), _obj_dbattribute=self._obj_dbattribute, _name_attribute=self._name_attribute, _first_container=self._first_container)
450
+ if self._first_container.container is self: obj.__dict__['_first_container'].container = obj
451
+ return obj
452
+
453
+ @classmethod
454
+ def __convert_to_db__(cls, obj: datetime.datetime, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
455
+ return cls(year=obj.year, month=obj.month, day=obj.day, hour=obj.hour, minute=obj.minute, second=obj.second, microsecond=obj.microsecond, tzinfo=obj.tzinfo, fold=obj.fold, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
456
+
457
+ def dumps(self, _return_json=True):
458
+ if _return_json: return json.dumps({'t': self.__class__.__name__, 'd': self.isoformat()})
459
+ return {'t': self.__class__.__name__, 'd': self.isoformat()}
460
+
461
+ @classmethod
462
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
463
+ return cls.__convert_to_db__(cls.fromisoformat(tempdata['d']), _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
464
+
465
+ @DbClassDecorator
466
+ class DbDate(DbClass, datetime.date):
467
+ _methode__new__needs_arguments = True
468
+ def __init__(self, year, month=None, day=None, *, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
469
+ super().__init__(year=year, month=month, day=day, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False, **kwargs)
470
+ def __iadd__(self, other):
471
+ obj = cheaker.create_db_class(self.__add__(other), _obj_dbattribute=self._obj_dbattribute, _name_attribute=self._name_attribute, _first_container=self._first_container)
472
+ if self._first_container.container is self: obj.__dict__['_first_container'].container = obj
473
+ return obj
474
+ def __isub__(self, other):
475
+ obj = cheaker.create_db_class(self.__sub__(other), _obj_dbattribute=self._obj_dbattribute, _name_attribute=self._name_attribute, _first_container=self._first_container)
476
+ if self._first_container.container is self: obj.__dict__['_first_container'].container = obj
477
+ return obj
478
+ @classmethod
479
+ def __convert_to_db__(cls, obj: datetime.datetime, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
480
+ return cls(year=obj.year, month=obj.month, day=obj.day, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
481
+ def dumps(self, _return_json=True):
482
+ if _return_json: return json.dumps({'t': self.__class__.__name__, 'd': self.isoformat()})
483
+ return {'t': self.__class__.__name__, 'd': self.isoformat()}
484
+ @classmethod
485
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
486
+ return cls.__convert_to_db__(cls.fromisoformat(tempdata['d']), _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
487
+
488
+ @DbClassDecorator
489
+ class DbTime(DbClass, datetime.time):
490
+ _methode__new__needs_arguments = True
491
+ def __init__(self, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
492
+ super().__init__(_obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False, **kwargs)
493
+
494
+ def __iadd__(self, other):
495
+ obj = cheaker.create_db_class(self.__add__(other), _obj_dbattribute=self._obj_dbattribute, _name_attribute=self._name_attribute, _first_container=self._first_container)
496
+ if self._first_container.container is self: obj.__dict__['_first_container'].container = obj
497
+ return obj
498
+ def __isub__(self, other):
499
+ obj = cheaker.create_db_class(self.__sub__(other), _obj_dbattribute=self._obj_dbattribute, _name_attribute=self._name_attribute, _first_container=self._first_container)
500
+ if self._first_container.container is self: obj.__dict__['_first_container'].container = obj
501
+ return obj
502
+
503
+ @classmethod
504
+ def __convert_to_db__(cls, obj: datetime.time, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
505
+ return DbTime(hour=obj.hour, minute=obj.minute, second=obj.second, microsecond=obj.microsecond, tzinfo=obj.tzinfo, fold=obj.fold, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
506
+
507
+ def dumps(self, _return_json=True):
508
+ if _return_json: return json.dumps({'t': self.__class__.__name__, 'd': self.isoformat()})
509
+ return {'t': self.__class__.__name__, 'd': self.isoformat()}
510
+ @classmethod
511
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
512
+ return cls.__convert_to_db__(cls.fromisoformat(tempdata['d']), _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
513
+
514
+ @DbClassDecorator
515
+ class DbTimedelta(DbClass, datetime.timedelta):
516
+ _methode__new__needs_arguments = True
517
+ def __init__(self, *args, _use_db=False, _convert_arguments=True, _obj_dbattribute=None, _name_attribute=None, _first_container=None, **kwargs):
518
+ super().__init__(*args, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container, _call_init=False, **kwargs)
519
+
520
+ def dumps(self, _return_json=True):
521
+ if _return_json: return json.dumps({'t': self.__class__.__name__, 'd': self.total_seconds()})
522
+ return {'t': self.__class__.__name__, 'd': self.total_seconds()}
523
+
524
+ @classmethod
525
+ def _loads(cls, tempdata: dict, *, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
526
+ return cls(seconds=tempdata['d'], _use_db=True, _first_container=_first_container)
527
+
528
+ class Cheaker:
529
+ """
530
+ cheak, if this class is db_class. Convert obj if his class is db_class. And other.
531
+
532
+ db_class_name_to_db_class: {'DbList': DbList, 'DbSet': DbSet, 'DbDict': DbDict} | *other db classes*
533
+ class_name_to_db_class = {'list': DbList, 'dict': DbDict, 'set': DbSet} | *other db classes*
534
+ class_to_db_class = {list: DbList, dict: DbDict, set: DbSet} | *other db classes*
535
+ """
536
+ def __init__(self, _db_classes:dict = None):
537
+ """
538
+ :param _db_classes: example: {datetime.datetime: DbDatetime}
539
+ :type _db_classes: dict
540
+ """
541
+ self._db_classes = _db_classes
542
+ if not _db_classes:
543
+ self._db_classes = dict()
544
+ self.db_class_name_to_db_class = {self._db_classes[i].__name__ : self._db_classes[i] for i in self._db_classes}
545
+ self.class_name_to_db_class = {i.__name__: self._db_classes[i] for i in self._db_classes}
546
+ self.db_class_name_to_clasic_class = {self._db_classes[i].__name__: i for i in self._db_classes}
547
+ self.all_db_classes = set(_db_classes.values())
548
+
549
+
550
+ def set_db_classes(self, _db_classes: dict):
551
+ """
552
+ :param _db_classes: example: {datetime.datetime: DbDatetime}
553
+ :type _db_classes: dict
554
+ """
555
+ self._db_classes = _db_classes
556
+ if not _db_classes:
557
+ self._db_classes = dict()
558
+ self.db_class_name_to_db_class = {self._db_classes[i].__name__ : self._db_classes[i] for i in self._db_classes}
559
+ self.class_name_to_db_class = {i.__name__: self._db_classes[i] for i in self._db_classes}
560
+ self.db_class_name_to_clasic_class = {self._db_classes[i].__name__: i for i in self._db_classes}
561
+ self.all_db_classes = set(_db_classes.values())
562
+
563
+ def add_db_class(self, _db_class: tuple):
564
+ """:param _db_class: example: (datetime.datetime, DbDatetime)"""
565
+ self._db_classes[_db_class[0]] = _db_class[1]
566
+ self.db_class_name_to_db_class[_db_class[1].__name__] = _db_class[1]
567
+ self.class_name_to_db_class[_db_class[0].__name__] = _db_class[1]
568
+ self.db_class_name_to_clasic_class[_db_class[1].__name__] = _db_class[0]
569
+ self.all_db_classes.add(_db_class[1])
570
+
571
+ def remove_db_class(self, name_clasic_class=None, name_db_class=None):
572
+ if name_clasic_class is None and name_db_class is None:
573
+ return
574
+ if name_db_class:
575
+ name_clasic_class = self.db_class_name_to_clasic_class[name_db_class].__name__
576
+ elif name_clasic_class:
577
+ name_db_class = self.class_name_to_db_class[name_clasic_class].__name__
578
+ db_class = self.db_class_name_to_db_class[name_db_class]
579
+ del self._db_classes[db_class]
580
+ del self.db_class_name_to_db_class[name_db_class]
581
+ del self.class_name_to_db_class[name_clasic_class]
582
+ del self.db_class_name_to_clasic_class[name_db_class]
583
+ self.all_db_classes.discard(db_class)
584
+
585
+ def create_any_db_classes(self, *objs, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
586
+ """
587
+ Use for create db_class from other classes. example: from list to DbList, but from int to int.
588
+ :param objs: example: [123, '535', {8, 4, 6} #it's set , {1: 2} # it's dict]
589
+ :param _obj_dbattribute:
590
+ :return: example: [123, '535', {8, 4, 6} #it's DbSet , {1: 2} # it's DbDict]
591
+ """
592
+ return [self.create_db_class(objs[i], _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container) for i in range(len(objs))]
593
+
594
+ def create_db_class(self, obj, *, attribute_type=None, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
595
+ if (attribute_type is None and type(obj) in self._db_classes) or (attribute_type in self._db_classes):
596
+ if attribute_type is None:
597
+ attribute_type = type(obj)
598
+ cls = self._db_classes[attribute_type]
599
+ if hasattr(cls, '__convert_to_db__'):
600
+ return cls.__convert_to_db__(obj, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
601
+ reductor = getattr(obj, "__reduce_ex__", None)
602
+ if reductor is not None:
603
+ rv = reductor(4)
604
+ else:
605
+ reductor = getattr(obj, "__reduce__", None)
606
+ if reductor:
607
+ rv = reductor()
608
+ else:
609
+ raise Exception(f"uncopyable object of type {type(obj)}")
610
+ if isinstance(rv, str):
611
+ raise Exception(f"uncopyable object of type {type(obj)}")
612
+ rv = list(rv)
613
+ if rv[0].__name__ == '__newobj__':
614
+ rv[0] = __newobj__
615
+ elif rv[0].__name__ == '__newobj_ex__':
616
+ rv[0] = __newobj_ex__
617
+ else:
618
+ rv[0] = __newobj__
619
+ rv[1] = (1,) + rv[1]
620
+ rv[1] = (cls,) + rv[1][1:]
621
+ obj = self._reconstruct(*rv, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
622
+ return obj
623
+
624
+ def _reconstruct(self, func, args, state=None, listiter=None, dictiter=None, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
625
+ y = func(*args, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
626
+ if _first_container is None:
627
+ _first_container = _FirstContainer(y)
628
+ if y.__dict__.get('_first_container', None) is None:
629
+ y.__dict__['_first_container'] = _first_container
630
+ if y._call_init_when_reconstruct:
631
+ y.__init__(*args[1:], _obj_dbattribute=None, _name_attribute=None, _first_container=None)
632
+ if state is not None:
633
+ if hasattr(y, '__setstate__'):
634
+ y.__setstate__(state)
635
+ else:
636
+ if isinstance(state, tuple) and len(state) == 2:
637
+ state, slotstate = state
638
+ else:
639
+ slotstate = None
640
+ if state is not None:
641
+ state = {key: self.create_db_class(state[key], _first_container=_first_container) for key in state}
642
+ y.__dict__.update(state)
643
+ if slotstate is not None:
644
+ slotstate = {key: self.create_db_class(slotstate[key], _first_container=_first_container) for key in slotstate}
645
+ for key, value in slotstate.items():
646
+ setattr(y, key, value)
647
+ if listiter is not None:
648
+ for item in listiter:
649
+ y.append(self.create_db_class(item, _first_container=_first_container))
650
+ if dictiter is not None:
651
+ for key, value in dictiter:
652
+ y[key] = self.create_db_class(value, _first_container=_first_container)
653
+ temp = {'_first_container': _first_container}
654
+ if _obj_dbattribute:
655
+ temp['_obj_dbattribute'] = _obj_dbattribute
656
+ if _name_attribute:
657
+ temp['_name_attribute'] = _name_attribute
658
+ if hasattr(y, '__dict__'):
659
+ y.__dict__.update(temp)
660
+ else:
661
+ for key, value in temp.items():
662
+ setattr(y, key, value)
663
+ return y
664
+
665
+ def this_support_class(self, obj, this_is_cls=False):
666
+ return obj in self._db_classes if this_is_cls else type(obj) in self._db_classes
667
+
668
+ def this_db_attribute_support_class(self, obj, this_is_cls=False):
669
+ return obj in self.all_db_classes if this_is_cls else type(obj) in self.all_db_classes
670
+
671
+ class Tlist(list): pass
672
+ class Tset(set): pass
673
+ class Tdict(dict): pass
674
+
675
+
676
+ def __newobj_ex__(cls, args, kwargs, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
677
+ return cls.__new__(cls, *args, *kwargs, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
678
+ def __newobj__(cls, *args, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
679
+ return cls.__new__(cls, *args, _use_db=True, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
680
+
681
+ def convert_atr_value_to_json_value(value):
682
+ return value.dumps(_return_json=False) if cheaker.this_db_attribute_support_class(value) else value
683
+
684
+ def conver_json_value_to_atr_value(value, _obj_dbattribute=None, _name_attribute=None, _first_container=None):
685
+ if isinstance(value, dict):
686
+ return DbClass.loads(value, _obj_dbattribute=_obj_dbattribute, _name_attribute=_name_attribute, _first_container=_first_container)
687
+ return value
688
+
689
+ def convert_atr_key_to_json_key(key):
690
+ """For DbDict"""
691
+ res = key
692
+ if key.__class__ == tuple:
693
+ res = str(key)
694
+ elif key.__class__ == bool:
695
+ res = ' True ' if key else ' False '
696
+ return res
697
+
698
+ def convert_json_key_to_atr_key(key, type_key):
699
+ """For DbDict"""
700
+ if type_key == 'int':
701
+ return int(key)
702
+ if type_key == 'tuple':
703
+ return ast.literal_eval(str(key))
704
+ if type_key == 'bool':
705
+ return True if key == ' True ' else False
706
+ return key
707
+
708
+ cheaker = Cheaker({set: DbSet, list: DbList, dict: DbDict, tuple: DbTuple, datetime.datetime: DbDatetime, datetime.timedelta: DbTimedelta, datetime.date: DbDate, datetime.time: DbTime})
709
+
710
+ if __name__ == "__main__":
711
+ print(1)
712
+ A = DbDict([[0, 1], [1, 4], [2, 3], [3, 2], [4, 4]], _use_db = True)
713
+ B = DbList([1, 4, 3, 2, 4], _use_db = True)
714
+ C = DbSet([1, 4, 3, 2, 4], _use_db = True)
715
+ if A != {0: 1, 1: 4, 2: 3, 3: 2, 4: 4} or B != [1, 4, 3, 2, 4] or C != {1, 2, 3, 4}:
716
+ print(A, type(A))
717
+ print(B, type(B))
718
+ print(C, type(C))
719
+
720
+ print(2)
721
+ a = A | {8: 5}
722
+ b = B + [1]
723
+ c = C - {3}
724
+ if a != {0: 1, 1: 4, 2: 3, 3: 2, 4: 4, 8: 5} or b != [1, 4, 3, 2, 4, 1] or c != {1, 2, 4} or type(a) != dict or type(b) != list or type(c) != set:
725
+ print(a, type(a))
726
+ print(b, type(b))
727
+ print(c, type(c))
728
+
729
+ print(3)
730
+ A |= {8: 5}
731
+ B += [1]
732
+ C -= {3}
733
+ if A != {0: 1, 1: 4, 2: 3, 3: 2, 4: 4, 8: 5} or B != [1, 4, 3, 2, 4, 1] or C != {1, 2, 4}:
734
+ print(A, type(A))
735
+ print(B, type(B))
736
+ print(C, type(C))
737
+
738
+ print(4)
739
+ A = DbDict([[0, 1], [1, 4], [2, 3], [3, 2], [4, 4]], _use_db = True)
740
+ B = DbList([1, 4, 3, 2, 4], _use_db = True)
741
+ C = DbSet([1, 4, 3, 2, 4], _use_db = True)
742
+ A.update({8:5})
743
+ B.append(1)
744
+ C.remove(3)
745
+ if A != {0: 1, 1: 4, 2: 3, 3: 2, 4: 4, 8: 5} or B != [1, 4, 3, 2, 4, 1] or C != {1, 2, 4}:
746
+ print(A, type(A))
747
+ print(B, type(B))
748
+ print(C, type(C))
749
+
750
+ print(5)
751
+ A = DbDict([[0, 1], [1, 4], [2, 3], [3, 2], [4, 4]], _use_db = True)
752
+ B = DbList([1, 4, 3, 2, 4], _use_db = True)
753
+ C = DbSet([1, 4, 3, 2, 4], _use_db = True)
754
+ a = dict(A)
755
+ b = list(B)
756
+ c = set(C)
757
+ a |= {8: 5}
758
+ b += [1]
759
+ c -= {3}
760
+ if A != {0: 1, 1: 4, 2: 3, 3: 2, 4: 4} or B != [1, 4, 3, 2, 4] or C != {1, 2, 3, 4} or a != {0: 1, 1: 4, 2: 3, 3: 2, 4: 4, 8: 5} or b != [1, 4, 3, 2, 4, 1] or c != {1, 2, 4} or a == A or b == B or c == C:
761
+ print(a, type(a))
762
+ print(b, type(b))
763
+ print(c, type(c))
764
+ print(A, type(A))
765
+ print(B, type(B))
766
+ print(C, type(C))
767
+
768
+ print(6)
769
+ A = DbDict([[0, [1, 4, {1}]], [1, {2}], [2, {5:6}], [3, 4]], _use_db = True)
770
+ B = DbList([[1], [4], [3], {2:[5]}, {1, 3, 4}], _use_db = True)
771
+ C = DbSet([(1, 4), (3, 2), 4], _use_db = True)
772
+ A[0][0] = 3
773
+ del A[0][1]
774
+ A[0][1].add(2)
775
+ if A != {0: [3, {1, 2}], 1: {2}, 2: {5: 6}, 3: 4} or B != [[1], [4], [3], {2: [5]}, {1, 3, 4}] or C != {(3, 2), 4, (1, 4)} or type(A) != DbDict or type(B) != DbList or type(C) != DbSet:
776
+ print(A, type(A))
777
+ print(B, type(B))
778
+ print(C, type(C))
779
+ print(7)
780
+ A = DbDict([[0, [1, 4, {1}]], [1, {2}], [2, {5:6}], [3, 4]], _use_db = True)
781
+ B = DbList([[1], [4], [3], {2:[5]}, {1, 3, 4}], _use_db = True)
782
+ a = copy.deepcopy(A)
783
+ b = copy.deepcopy(B)
784
+ a[0][0] = 3
785
+ b[3][1] = 4
786
+ if type(a) != dict or type(b) != list or A != {0: [1, 4, {1}], 1: {2}, 2: {5: 6}, 3: 4} or B != [[1], [4], [3], {2: [5]}, {1, 3, 4}] or a != {0: [3, 4, {1}], 1: {2}, 2: {5: 6}, 3: 4} or b != [[1], [4], [3], {2: [5], 1: 4}, {1, 3, 4}]:
787
+ print(A, type(A))
788
+ print(B, type(B))
789
+ print(a, type(a))
790
+ print(b, type(b))
791
+ print(8)
792
+ A = DbDict({0: [1, 4, {1}], 1: {2}, 2: {5:6}, 3: (7, 8), 4: True, 5: False, (6, 7): [1, 2], '8': [1]}, _use_db = True)
793
+ B = DbList([{2:[5]}, [1], [4], [3], {1, 3, 4}, True, True, (1, 2), (1, 2)], _use_db = True)
794
+ C = DbSet([4, True, '/Hello\n', (1, 2)], _use_db = True)
795
+ #print(C.dumps())
796
+ a = DbClass.loads(A.dumps())
797
+ b = DbClass.loads(B.dumps())
798
+ c = DbClass.loads(C.dumps())
799
+ if A != a:
800
+ print('8.A error:')
801
+ print(A.dumps(), type(A.dumps()))
802
+ print(A, type(A))
803
+ print(a, type(a))
804
+ if B != b:
805
+ print('8.B error:')
806
+ print(B.dumps(), type(B.dumps()))
807
+ print(B, type(B))
808
+ print(b, type(b))
809
+ if C != c:
810
+ print('8.C error:')
811
+ print(C.dumps(), type(C.dumps()))
812
+ print(C, type(C))
813
+ print(c, type(c))
814
+ print(9, 'cheack _first_container')
815
+ temp_func = lambda inp: {id(inp._first_container.container)} | {j for i in inp if hasattr(i, '__iter__') for j in temp_func(i)}
816
+ temp_func_dict = lambda inp: {id(inp._first_container.container)} | {j for key in inp if hasattr(inp[key], '__iter__') for j in temp_func(inp[key])}
817
+ A = DbTuple(([1], 2, 3, datetime.datetime(2024, 10, 4)), _use_db = True)
818
+ A += ((4,),)
819
+ if len(temp_func(A)) > 1:
820
+ print('9.1 error:')
821
+ print(A, type(A), temp_func(A))
822
+ print(id(A), id(A._first_container.container), id(A[0]._first_container.container))
823
+ print(id(A._first_container), id(A[0]._first_container))
824
+
825
+ B = DbList([([1], 2, 3, datetime.datetime(2024, 10, 4))], _use_db=True)
826
+ B[0] += ((4,),)
827
+ if len(temp_func(B)) > 1:
828
+ print('9.2 error:')
829
+ print(B, type(B), temp_func(B))
830
+ print(id(B), id(B._first_container.container), id(B[0]._first_container.container), id(B[0][0]._first_container.container))
831
+ print(id(B._first_container), id(B[0]._first_container), id(B[0][0]._first_container))
832
+
833
+ B = cheaker.create_db_class([[1, (2,(3,),[4],datetime.datetime(2024, 10, 4)), {5, (6,(7,))}, {(8, 3), 5}], (9,(10,),[11])])
834
+ if B != [[1, (2,(3,),[4],datetime.datetime(2024, 10, 4)), {5, (6,(7,))}, {(8, 3), 5}], (9,(10,),[11])]:
835
+ print('9.3.a error:')
836
+ print(B, type(B))
837
+ B += [(12,)]
838
+ B[0].append(13)
839
+ B[-1] = [1, 2]
840
+ B[0][1] += (4,)
841
+ B[0][2] |= {(3, (1,))}
842
+ B[0][2] -= {(3, (1,))}
843
+ B[0][2] |= {(3, (2,))}
844
+ B[0][2] &= {(3, (2,))}
845
+ if len(temp_func(B)) > 1:
846
+ print('9.3.b error:')
847
+ print(B, type(B), temp_func(B))
848
+
849
+ B = cheaker.create_db_class({(1, 2): [3, 4], 5: {6, (7,)}, 8: (9, {10:11})})
850
+ if B != {(1, 2): [3, 4], 5: {6, (7,)}, 8: (9, {10:11})} or type(B) is not DbDict:
851
+ print('9.4.a error:')
852
+ print(B, type(B))
853
+ if len(temp_func_dict(B)) > 1:
854
+ print('9.4.b error:')
855
+ print(B, type(B), temp_func_dict(B))
856
+ B[9] = [(3, 5), {1, 0}, {3: 5}, [2]]
857
+ B |= {8: [1, (5, 8)]}
858
+ B |= {9: [3, 7, (3, 5)]}
859
+ if len(temp_func_dict(B)) > 1:
860
+ print('9.4.c error:')
861
+ print(B, type(B), temp_func_dict(B))
862
+
863
+
864
+ print(10, 'cheack datetime')
865
+ A = DbDatetime(2024, 11, 4, _use_db=True)
866
+ if A != datetime.datetime(2024, 11, 4) or type(A) is not DbDatetime:
867
+ print('10.1.1 error:')
868
+ print(A, type(A))
869
+ A = cheaker.create_db_class(datetime.datetime(2024, 11, 4))
870
+ if A != datetime.datetime(2024, 11, 4) or type(A) is not DbDatetime:
871
+ print('10.1.2 error:')
872
+ print(A, type(A))
873
+ A = DbClass.loads(A.dumps())
874
+ if A != datetime.datetime(2024, 11, 4) or type(A) is not DbDatetime:
875
+ print('10.1.3 error:')
876
+ print(A, type(A))
877
+ B = DbList([A], _use_db=True)
878
+ B = DbClass.loads(B.dumps())
879
+ if B[0] != datetime.datetime(2024, 11, 4) or type(B[0]) is not DbDatetime:
880
+ print('10.1.4 error:')
881
+ print(A, type(A))
882
+ A = DbTimedelta(microseconds=10, _use_db=True)
883
+ if A != datetime.timedelta(microseconds=10) or type(A) is not DbTimedelta:
884
+ print('10.2.1 error:')
885
+ print(A, type(A))
886
+ A = DbClass.loads(A.dumps())
887
+ if A != datetime.timedelta(microseconds=10) or type(A) is not DbTimedelta:
888
+ print('10.2.2 error:')
889
+ print(A, type(A))
890
+ A = DbTimedelta(seconds=10**6, _use_db=True)
891
+ if A != datetime.timedelta(seconds=10**6) or type(A) is not DbTimedelta:
892
+ print('10.2.3 error:')
893
+ print(A, type(A))
894
+ A = DbClass.loads(A.dumps())
895
+ if A != datetime.timedelta(seconds=10**6) or type(A) is not DbTimedelta:
896
+ print('10.2.4 error:')
897
+ print(A, type(A))
898
+ B = DbDatetime(2024, 11, 4, _use_db=True)
899
+ B -= A
900
+ if B != datetime.datetime(2024, 10, 23, 10, 13, 20) or type(B) is not DbDatetime:
901
+ print('10.3.1 error:')
902
+ print(B, type(B))
903
+ A = DbDate(2024, 11, 10, _use_db=True)
904
+ if A != datetime.date(2024, 11, 10) or type(A) is not DbDate:
905
+ print('10.4.1 error:')
906
+ print(A, type(A))
907
+ A = DbClass.loads(A.dumps())
908
+ if A != datetime.date(2024, 11, 10) or type(A) is not DbDate:
909
+ print('10.4.2 error:')
910
+ print(A, type(A))
911
+ A = DbTime(11, 15, 10, _use_db=True)
912
+ if A != datetime.time(11, 15, 10) or type(A) is not DbTime:
913
+ print('10.5.1 error:')
914
+ print(A, type(A))
915
+ A = DbClass.loads(A.dumps())
916
+ if A != datetime.time(11, 15, 10) or type(A) is not DbTime:
917
+ print('10.5.2 error:')
918
+ print(A, type(A))
919
+ print(11, 'time test')
920
+ def test(cls, args):
921
+ import time
922
+ n = 3*10**4
923
+ print(f'test {cls}')
924
+ start = time.time()
925
+ for i in range(n):
926
+ A = cls(args, _use_db = True)
927
+ end = time.time()
928
+ print(f'create: {n/(end - start)} op/sec {(end-start)} in {n} op')
929
+ start = time.time()
930
+ for i in range(n):
931
+ data = A.dumps()
932
+ end = time.time()
933
+ print(f'dumps: {n/(end - start)} op/sec {(end-start)} in {n} op')
934
+ start = time.time()
935
+ for i in range(n):
936
+ A = cls.loads(data)
937
+ end = time.time()
938
+ print(f'loads: {n/(end - start)} op/sec {(end-start)} in {n} op')
939
+ #test(DbDict, {0: [[1, 2], [3, 4], [5, 6]], 1: {1, ((2,), (3,))}, 2: {1: {2: (3, ), 4: (5,)}, 6: {7: (8,)}}})
940
+ test(DbList, [[[1, 2], [3, 4], [5, 6]], {1, ((2,), (3,))}, {1: {2: (3, ), 4: (5,)}, 6: {7: (8,)}}])
941
+
942
+