cengal.data_manipulation.serialization.versions.v_0.serialization
1#!/usr/bin/env python 2# coding=utf-8 3 4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space> 5# 6# Licensed under the Apache License, Version 2.0 (the "License"); 7# you may not use this file except in compliance with the License. 8# You may obtain a copy of the License at 9# 10# http://www.apache.org/licenses/LICENSE-2.0 11# 12# Unless required by applicable law or agreed to in writing, software 13# distributed under the License is distributed on an "AS IS" BASIS, 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15# See the License for the specific language governing permissions and 16# limitations under the License. 17 18from cengal.code_flow_control.gc import DisableGC 19from cengal.modules_management.alternative_import import alt_import 20from cengal.time_management.repeat_for_a_time import Tracer 21from cengal.time_management.cpu_clock_cycles import perf_counter 22import enum 23from functools import lru_cache 24from typing import Set, Union, Optional, Any, Dict, Tuple, List 25 26 27""" 28Module Docstring 29Docstrings: http://www.python.org/dev/peps/pep-0257/ 30""" 31 32__author__ = "ButenkoMS <gtalk@butenkoms.space>" 33__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>" 34__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ] 35__license__ = "Apache License, Version 2.0" 36__version__ = "4.4.1" 37__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>" 38__email__ = "gtalk@butenkoms.space" 39# __status__ = "Prototype" 40__status__ = "Development" 41# __status__ = "Production" 42 43 44class Tags(enum.Enum): 45 tested = 0 46 deep = 1 # can work with nested data structures 47 superficial = 2 # can work with only single-layer of data 48 multi_platform = 3 # serialized data can be deserialized by other languages/interpreters 49 current_platform = 4 # serialized data can be deserialized by current type of python interpreter (only by CPython or only by PyPy for example) 50 multicast = 5 # ? 51 unique = 6 # ? 52 can_use_set = 7 # can serialize set type 53 can_use_bytes = 8 # can serialize bytes type 54 can_use_custom_types = 9 # can serialize custom types 55 can_use_lambda_functions = 10 56 decode_str_as_str = 11 # does not convert strings to bytes 57 decode_bytes_as_bytes = 12 # does not convert bytes to strings 58 decode_str_and_bytes_as_requested = 13 # can chose: convert all str/bytes to str or to convert all str/bytes to bytes. 59 decode_list_and_tuple_as_requested = 14 # can chose: convert all list/tuple to list or to convert all list/tuple to tuple. 60 decode_tuple_as_tuple = 15 # does not conver tuples to list/set 61 decode_list_as_list = 16 # does not convert lists to tuple/set 62 explicit_format_version = 17 # Example: pickle can be of a different versions since python-version depent so it is Not tagged as an explicit_format_version. 63 fast = 17 64 compat = 18 65 compat_with_python_below_3_8 = 19 66 compat_with_python_abowe_3_8 = 20 67 decode_set_as_set = 21 # does not convert sets to tuple/list 68 69 70class DataFormats(enum.Enum): 71 any = 0 # we don't care about the serialized data format 72 json = 1 # serialized data is json 73 binary = 2 # serialized data is binary (not really human-readable) 74 text = 3 # serialized data is human-readable 75 yaml = 4 76 toml = 5 77 messagepack = 6 78 79 80SerializerFeatures = Set[Union[Tags, DataFormats]] 81SerializerFeaturesTuple = Tuple[Union[Tags, DataFormats]] 82 83 84# !!! Keep an order! Add new serializers to the end of the list only !!! 85class Serializers(enum.Enum): 86 json = 0 87 simplejson = 1 88 ujson = 2 89 orjson = 3 90 tnetstring = 4 91 pynetstring = 5 92 msgpack_fast = 6 93 msgpack = 7 94 cbor = 8 95 cbor2 = 9 96 marshal = 10 97 marshal_compat_4 = 11 98 marshal_compat_3 = 12 99 marshal_compat_2 = 13 100 marshal_compat_1 = 14 101 marshal_compat_0 = 15 102 pickle = 16 103 pickle_default = 17 104 pickle_compat_5 = 18 105 pickle_compat_4 = 19 106 pickle_compat_3 = 20 107 pickle_compat_2 = 21 108 pickle_compat_1 = 22 109 cpickle = 23 110 cpickle_default = 24 111 cpickle_compat_5 = 25 112 cpickle_compat_4 = 26 113 cpickle_compat_3 = 27 114 cpickle_compat_2 = 28 115 cpickle_compat_1 = 29 116 cloudpickle = 30 117 cloudpickle_compat_5 = 31 118 cloudpickle_compat_4 = 32 119 cloudpickle_compat_3 = 33 120 cloudpickle_compat_2 = 34 121 cloudpickle_compat_1 = 35 122 msgspec_json = 36 123 msgspec_messagepack = 37 124 msgspec_yaml = 38 125 msgspec_toml = 39 126 127 128import datetime 129import decimal 130import fractions 131import re 132from email.message import Message as emailMessage 133import uuid 134import ipaddress 135from types import CodeType 136none_type = type(None) 137SUPPORTED_TYPES = { 138 Serializers.json: {int, float, bool, none_type, str, list, dict}, 139 Serializers.simplejson: {int, float, bool, none_type, str, list, dict}, 140 Serializers.ujson: {int, float, bool, none_type, str, list, dict}, 141 Serializers.orjson: {int, float, bool, none_type, str, list, dict}, 142 Serializers.tnetstring: {int, float, bool, none_type, str, list, dict}, 143 Serializers.pynetstring: {int, float, bool, none_type, str, list, dict}, 144 Serializers.msgpack: {int, float, bool, none_type, str, bytes, list, dict}, 145 Serializers.msgpack_fast: {int, float, bool, none_type, str, bytes, tuple, dict}, 146 Serializers.cbor: {int, float, bool, none_type, str, list, dict}, 147 Serializers.cbor2: { 148 int, float, bool, none_type, str, list, dict, 149 datetime.datetime, datetime.date, decimal.Decimal, fractions.Fraction, 150 re.Pattern, emailMessage, uuid.UUID, set, 151 ipaddress.IPv4Address, ipaddress.IPv6Address, ipaddress.IPv4Network, ipaddress.IPv6Network, 152 }, 153 Serializers.marshal: { 154 bool, int, float, complex, str, bytes, bytearray, tuple, list, set, frozenset, dict, 155 CodeType, none_type, Ellipsis, StopIteration 156 }, 157 Serializers.pickle: {}, 158 Serializers.cpickle: {}, 159 Serializers.cloudpickle: {}, 160 Serializers.msgspec_messagepack: {int, float, bool, none_type, str, bytes, list, dict}, 161 Serializers.msgspec_json: {int, float, bool, none_type, str, list, dict}, 162 Serializers.msgspec_yaml: { 163 int, float, bool, none_type, str, list, dict, 164 datetime.datetime, datetime.date, 165 }, 166 # Serializers.msgspec_toml: { 167 # int, float, bool, none_type, str, list, dict, 168 # datetime.datetime, datetime.date, datetime.time, 169 # }, 170 Serializers.msgspec_toml: { 171 str, dict, 172 datetime.datetime, datetime.date, datetime.time, 173 }, 174} 175 176 177SERIALIZERS_DESCRIPTION = { 178 Serializers.json: ('json', { 179 Tags.deep, 180 Tags.tested, 181 Tags.superficial, 182 Tags.multi_platform, 183 Tags.current_platform, 184 Tags.decode_str_as_str, 185 Tags.decode_list_as_list, 186 Tags.explicit_format_version, 187 DataFormats.any, 188 DataFormats.json, 189 DataFormats.text, 190 }), 191 Serializers.simplejson: ('simplejson', { 192 Tags.deep, 193 Tags.tested, 194 Tags.superficial, 195 Tags.multi_platform, 196 Tags.current_platform, 197 Tags.can_use_bytes, 198 Tags.decode_str_as_str, 199 Tags.decode_list_as_list, 200 Tags.explicit_format_version, 201 DataFormats.any, 202 DataFormats.json, 203 DataFormats.text, 204 }), 205 Serializers.ujson: ('ujson', { 206 Tags.deep, 207 Tags.superficial, 208 Tags.multi_platform, 209 Tags.current_platform, 210 Tags.can_use_bytes, 211 Tags.decode_str_as_str, 212 Tags.decode_list_as_list, 213 Tags.explicit_format_version, 214 DataFormats.any, 215 DataFormats.json, 216 DataFormats.text, 217 }), 218 Serializers.orjson: ('orjson', { 219 Tags.deep, 220 Tags.superficial, 221 Tags.multi_platform, 222 Tags.current_platform, 223 Tags.can_use_bytes, 224 Tags.decode_str_as_str, 225 Tags.decode_list_as_list, 226 Tags.explicit_format_version, 227 DataFormats.any, 228 DataFormats.json, 229 DataFormats.text, 230 }), 231 Serializers.tnetstring: ('tnetstring', { 232 Tags.superficial, 233 Tags.current_platform, 234 Tags.decode_str_as_str, 235 Tags.explicit_format_version, 236 DataFormats.any, 237 DataFormats.text, 238 }), 239 Serializers.pynetstring: ('pynetstring', { 240 Tags.superficial, 241 Tags.multi_platform, 242 Tags.current_platform, 243 Tags.decode_str_as_str, 244 Tags.explicit_format_version, 245 DataFormats.any, 246 DataFormats.text, 247 }), 248 Serializers.msgpack: ('msgpack', { 249 Tags.tested, 250 Tags.deep, 251 Tags.superficial, 252 Tags.multi_platform, 253 Tags.current_platform, 254 Tags.can_use_bytes, 255 Tags.decode_str_as_str, 256 Tags.decode_bytes_as_bytes, 257 Tags.decode_str_and_bytes_as_requested, 258 Tags.decode_list_and_tuple_as_requested, 259 Tags.decode_list_as_list, 260 Tags.explicit_format_version, 261 DataFormats.any, 262 DataFormats.binary, 263 DataFormats.messagepack, 264 }), 265 Serializers.msgpack_fast: ('msgpack_fast', { 266 Tags.tested, 267 Tags.deep, 268 Tags.superficial, 269 Tags.multi_platform, 270 Tags.current_platform, 271 Tags.can_use_bytes, 272 Tags.decode_str_as_str, 273 Tags.decode_bytes_as_bytes, 274 Tags.decode_str_and_bytes_as_requested, 275 Tags.decode_list_and_tuple_as_requested, 276 Tags.decode_tuple_as_tuple, 277 Tags.explicit_format_version, 278 DataFormats.any, 279 DataFormats.binary, 280 DataFormats.messagepack, 281 }), 282 Serializers.cbor: ('cbor', { 283 Tags.tested, 284 Tags.deep, 285 Tags.superficial, 286 Tags.multi_platform, 287 Tags.current_platform, 288 Tags.can_use_bytes, 289 Tags.decode_str_as_str, 290 Tags.decode_bytes_as_bytes, 291 Tags.decode_list_as_list, 292 Tags.explicit_format_version, 293 DataFormats.any, 294 DataFormats.binary, 295 }), 296 Serializers.cbor2: ('cbor2', { 297 Tags.tested, 298 Tags.deep, 299 Tags.superficial, 300 Tags.multi_platform, 301 Tags.current_platform, 302 Tags.can_use_bytes, 303 Tags.decode_str_as_str, 304 Tags.decode_bytes_as_bytes, 305 Tags.decode_list_as_list, 306 Tags.explicit_format_version, 307 DataFormats.any, 308 DataFormats.binary, 309 }), 310 Serializers.marshal: ('marshal', { 311 Tags.tested, 312 Tags.deep, 313 Tags.superficial, 314 Tags.current_platform, 315 Tags.can_use_bytes, 316 Tags.decode_str_as_str, 317 Tags.decode_bytes_as_bytes, 318 Tags.can_use_set, 319 Tags.decode_tuple_as_tuple, 320 Tags.decode_list_as_list, 321 Tags.explicit_format_version, 322 DataFormats.any, 323 DataFormats.binary, 324 }), 325 Serializers.pickle: ('pickle', { 326 Tags.tested, 327 Tags.deep, 328 Tags.superficial, 329 Tags.current_platform, 330 Tags.can_use_bytes, 331 Tags.can_use_set, 332 Tags.can_use_custom_types, 333 Tags.decode_str_as_str, 334 Tags.decode_bytes_as_bytes, 335 Tags.decode_tuple_as_tuple, 336 Tags.decode_list_as_list, 337 DataFormats.any, 338 DataFormats.binary, 339 }), 340 Serializers.cpickle: ('cPickle', { 341 Tags.deep, 342 Tags.superficial, 343 Tags.current_platform, 344 Tags.can_use_bytes, 345 Tags.can_use_set, 346 Tags.can_use_custom_types, 347 Tags.decode_str_as_str, 348 Tags.decode_bytes_as_bytes, 349 Tags.decode_tuple_as_tuple, 350 Tags.decode_list_as_list, 351 DataFormats.any, 352 DataFormats.binary, 353 }), 354 Serializers.cloudpickle: ('cloudpickle', { 355 Tags.deep, 356 Tags.superficial, 357 Tags.current_platform, 358 Tags.can_use_bytes, 359 Tags.can_use_set, 360 Tags.can_use_custom_types, 361 Tags.can_use_lambda_functions, 362 Tags.decode_str_as_str, 363 Tags.decode_bytes_as_bytes, 364 Tags.decode_tuple_as_tuple, 365 Tags.decode_list_as_list, 366 DataFormats.any, 367 DataFormats.binary, 368 }), 369 Serializers.msgspec_messagepack: ('msgspec_messagepack', { 370 Tags.tested, 371 Tags.deep, 372 Tags.superficial, 373 Tags.multi_platform, 374 Tags.current_platform, 375 Tags.can_use_set, 376 Tags.can_use_bytes, 377 Tags.decode_str_as_str, 378 Tags.decode_bytes_as_bytes, 379 Tags.decode_list_as_list, 380 Tags.explicit_format_version, 381 DataFormats.any, 382 DataFormats.binary, 383 DataFormats.messagepack, 384 }), 385 Serializers.msgspec_json: ('msgspec_json', { 386 Tags.tested, 387 Tags.deep, 388 Tags.superficial, 389 Tags.multi_platform, 390 Tags.current_platform, 391 Tags.can_use_set, 392 Tags.decode_str_as_str, 393 Tags.decode_list_as_list, 394 Tags.explicit_format_version, 395 DataFormats.any, 396 DataFormats.json, 397 DataFormats.text, 398 }), 399 Serializers.msgspec_yaml: ('msgspec_yaml', { 400 Tags.tested, 401 Tags.deep, 402 Tags.superficial, 403 Tags.multi_platform, 404 Tags.current_platform, 405 Tags.can_use_set, 406 Tags.decode_str_as_str, 407 Tags.decode_list_as_list, 408 Tags.explicit_format_version, 409 DataFormats.any, 410 DataFormats.yaml, 411 DataFormats.text, 412 }), 413 Serializers.msgspec_toml: ('msgspec_toml', { 414 Tags.tested, 415 Tags.deep, 416 Tags.superficial, 417 Tags.multi_platform, 418 Tags.current_platform, 419 Tags.can_use_set, 420 Tags.decode_str_as_str, 421 Tags.decode_list_as_list, 422 Tags.explicit_format_version, 423 DataFormats.any, 424 DataFormats.toml, 425 DataFormats.text, 426 }), 427} 428 429 430ujson_dump_skip_parameters = {'skipkeys', 'check_circular', 'allow_nan', 'cls', 'separators', 'default'} 431ujson_dumps_skip_parameters = {'skipkeys', 'check_circular', 'allow_nan', 'cls', 'separators', 'default'} 432ujson_load_skip_parameters = {'cls', 'object_hook', 'parse_float', 'parse_int', 'parse_constant', 'object_pairs_hook'} 433ujson_loads_skip_parameters = {'cls', 'object_hook', 'parse_float', 'parse_int', 'parse_constant', 'object_pairs_hook'} 434 435 436orjson_dump_skip_parameters = {'skipkeys', 'check_circular', 'allow_nan', 'cls', 'separators', 'default'} 437orjson_dumps_skip_parameters = {'skipkeys', 'check_circular', 'allow_nan', 'cls', 'separators', 'default'} 438orjson_load_skip_parameters = {'cls', 'object_hook', 'parse_float', 'parse_int', 'parse_constant', 'object_pairs_hook'} 439orjson_loads_skip_parameters = {'cls', 'object_hook', 'parse_float', 'parse_int', 'parse_constant', 'object_pairs_hook'} 440 441 442EXISTING_SERIALIZERS = set() # type: Set[Serializers] 443with alt_import('json') as json: 444 if json is not None: 445 EXISTING_SERIALIZERS.add(Serializers.json) 446with alt_import('simplejson') as simplejson: 447 if simplejson is not None: 448 EXISTING_SERIALIZERS.add(Serializers.simplejson) 449with alt_import('ujson') as ujson: 450 if ujson is not None: 451 EXISTING_SERIALIZERS.add(Serializers.ujson) 452with alt_import('orjson') as orjson: 453 if orjson is not None: 454 EXISTING_SERIALIZERS.add(Serializers.orjson) 455with alt_import('tnetstring') as tnetstring: 456 if tnetstring is not None: 457 EXISTING_SERIALIZERS.add(Serializers.tnetstring) 458# with alt_import('pynetstring') as pynetstring: 459# if pynetstring is not None: 460# EXISTING_SERIALIZERS.add(Serializers.pynetstring) 461with alt_import('msgpack') as msgpack: 462 if msgpack is not None: 463 EXISTING_SERIALIZERS.add(Serializers.msgpack_fast) 464 EXISTING_SERIALIZERS.add(Serializers.msgpack) 465with alt_import('msgspec') as msgspec: 466 if msgspec is not None: 467 EXISTING_SERIALIZERS.add(Serializers.msgspec_messagepack) 468 EXISTING_SERIALIZERS.add(Serializers.msgspec_json) 469 EXISTING_SERIALIZERS.add(Serializers.msgspec_yaml) 470 EXISTING_SERIALIZERS.add(Serializers.msgspec_toml) 471with alt_import('cbor') as cbor: 472 if cbor is not None: 473 EXISTING_SERIALIZERS.add(Serializers.cbor) 474with alt_import('cbor2') as cbor2: 475 if cbor2 is not None: 476 EXISTING_SERIALIZERS.add(Serializers.cbor2) 477with alt_import('marshal') as marshal: 478 if marshal is not None: 479 EXISTING_SERIALIZERS.add(Serializers.marshal) 480with alt_import('pickle') as pickle: 481 if pickle is not None: 482 EXISTING_SERIALIZERS.add(Serializers.pickle) 483with alt_import('cPickle') as cPickle: 484 if cPickle is not None: 485 EXISTING_SERIALIZERS.add(Serializers.cpickle) 486with alt_import('cloudpickle') as cloudpickle: 487 if cloudpickle is not None: 488 EXISTING_SERIALIZERS.add(Serializers.cloudpickle) 489 490 491class Serializer: 492 def __init__(self, serializer: Union[None, Serializers]): 493 self.dump = None 494 self.dumps = None 495 self.load = None 496 self.loads = None 497 self._serializer = None 498 self.serializer = serializer 499 500 @property 501 def serializer(self): 502 return self._serializer 503 504 @serializer.setter 505 def serializer(self, serializer: Serializers): 506 self._serializer = serializer 507 if self._serializer is None: 508 self.dump = None 509 self.dumps = None 510 self.load = None 511 self.loads = None 512 else: 513 serializer_name, serializer_tags = SERIALIZERS_DESCRIPTION[self._serializer] 514 self.dump = getattr(self, '_{}__dump'.format(serializer_name)) 515 self.dumps = getattr(self, '_{}__dumps'.format(serializer_name)) 516 self.load = getattr(self, '_{}__load'.format(serializer_name)) 517 self.loads = getattr(self, '_{}__loads'.format(serializer_name)) 518 519 # json 520 @staticmethod 521 def _json__dump(*args, **kwargs): 522 json.dump(*args, **kwargs) 523 524 @staticmethod 525 def _json__dumps(*args, **kwargs): 526 return json.dumps(*args, **kwargs) 527 528 @staticmethod 529 def _json__load(*args, **kwargs): 530 return json.load(*args, **kwargs) 531 532 @staticmethod 533 def _json__loads(*args, **kwargs): 534 return json.loads(*args, **kwargs) 535 536 # simplejson 537 @staticmethod 538 def _simplejson__dump(*args, **kwargs): 539 simplejson.dump(*args, **kwargs) 540 541 @staticmethod 542 def _simplejson__dumps(*args, **kwargs): 543 return simplejson.dumps(*args, **kwargs) 544 545 @staticmethod 546 def _simplejson__load(*args, **kwargs): 547 return simplejson.load(*args, **kwargs) 548 549 @staticmethod 550 def _simplejson__loads(*args, **kwargs): 551 return simplejson.loads(*args, **kwargs) 552 553 # ujson 554 @staticmethod 555 def _ujson__dump(*args, **kwargs): 556 for unnecessary_parameter in ujson_dump_skip_parameters: 557 kwargs.pop(unnecessary_parameter, None) 558 ujson.dump(*args, **kwargs) 559 560 @staticmethod 561 def _ujson__dumps(*args, **kwargs): 562 for unnecessary_parameter in ujson_dumps_skip_parameters: 563 kwargs.pop(unnecessary_parameter, None) 564 return ujson.dumps(*args, **kwargs) 565 566 @staticmethod 567 def _ujson__load(*args, **kwargs): 568 for unnecessary_parameter in ujson_load_skip_parameters: 569 kwargs.pop(unnecessary_parameter, None) 570 return ujson.load(*args, **kwargs) 571 572 @staticmethod 573 def _ujson__loads(*args, **kwargs): 574 for unnecessary_parameter in ujson_loads_skip_parameters: 575 kwargs.pop(unnecessary_parameter, None) 576 return ujson.loads(*args, **kwargs) 577 578 # orjson 579 @staticmethod 580 def _orjson__dump(*args, **kwargs): 581 for unnecessary_parameter in orjson_dump_skip_parameters: 582 kwargs.pop(unnecessary_parameter, None) 583 kwargs['option'] = orjson.OPT_NON_STR_KEYS 584 orjson.dump(*args, **kwargs) 585 586 @staticmethod 587 def _orjson__dumps(*args, **kwargs): 588 for unnecessary_parameter in orjson_dumps_skip_parameters: 589 kwargs.pop(unnecessary_parameter, None) 590 kwargs['option'] = orjson.OPT_NON_STR_KEYS 591 return orjson.dumps(*args, **kwargs).decode('utf-8') 592 593 @staticmethod 594 def _orjson__load(*args, **kwargs): 595 for unnecessary_parameter in orjson_load_skip_parameters: 596 kwargs.pop(unnecessary_parameter, None) 597 return orjson.load(*args, **kwargs) 598 599 @staticmethod 600 def _orjson__loads(*args, **kwargs): 601 for unnecessary_parameter in orjson_loads_skip_parameters: 602 kwargs.pop(unnecessary_parameter, None) 603 return orjson.loads(*args, **kwargs) 604 605 # tnetstring 606 @staticmethod 607 def _tnetstring__dump(*args, **kwargs): 608 tnetstring.dump(*args, **kwargs) 609 610 @staticmethod 611 def _tnetstring__dumps(*args, **kwargs): 612 return tnetstring.dumps(*args, **kwargs) 613 614 @staticmethod 615 def _tnetstring__load(*args, **kwargs): 616 return tnetstring.load(*args, **kwargs) 617 618 @staticmethod 619 def _tnetstring__loads(*args, **kwargs): 620 return tnetstring.loads(*args, **kwargs) 621 622 # msgpack 623 @staticmethod 624 def _msgpack__dump(*args, **kwargs): 625 result_kwargs = { 626 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated. 627 'use_bin_type': True, 628 } 629 result_kwargs.update(kwargs) 630 msgpack.dump(*args, **result_kwargs) 631 632 @staticmethod 633 def _msgpack__dumps(*args, **kwargs): 634 result_kwargs = { 635 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated. 636 'use_bin_type': True, 637 } 638 result_kwargs.update(kwargs) 639 return msgpack.dumps(*args, **result_kwargs) 640 641 @staticmethod 642 def _msgpack__load(*args, **kwargs): 643 result_kwargs = { 644 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated, Use raw=False instead. 645 'raw': False, 646 'use_list': True, 647 'strict_map_key': False, 648 } 649 result_kwargs.update(kwargs) 650 with DisableGC(): 651 result = msgpack.load(*args, **result_kwargs) 652 653 return result 654 655 @staticmethod 656 def _msgpack__loads(*args, **kwargs): 657 result_kwargs = { 658 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated, Use raw=False instead. 659 'raw': False, 660 'use_list': True, 661 'strict_map_key': False, 662 } 663 result_kwargs.update(kwargs) 664 with DisableGC(): 665 result = msgpack.loads(*args, **result_kwargs) 666 667 return result 668 669 # msgpack_fast 670 @staticmethod 671 def _msgpack_fast__dump(*args, **kwargs): 672 result_kwargs = { 673 'encoding': 'utf-8', 674 'use_bin_type': True 675 } 676 result_kwargs.update(kwargs) 677 msgpack.dump(*args, **result_kwargs) 678 679 @staticmethod 680 def _msgpack_fast__dumps(*args, **kwargs): 681 result_kwargs = { 682 'encoding': 'utf-8', 683 'use_bin_type': True 684 } 685 result_kwargs.update(kwargs) 686 return msgpack.dumps(*args, **result_kwargs) 687 688 @staticmethod 689 def _msgpack_fast__load(*args, **kwargs): 690 result_kwargs = { 691 'encoding': 'utf-8', 692 'raw': False, 693 'use_list': False 694 } 695 result_kwargs.update(kwargs) 696 with DisableGC(): 697 result = msgpack.load(*args, **result_kwargs) 698 699 return result 700 701 @staticmethod 702 def _msgpack_fast__loads(*args, **kwargs): 703 result_kwargs = { 704 'encoding': 'utf-8', 705 'raw': False, 706 'use_list': False 707 } 708 result_kwargs.update(kwargs) 709 with DisableGC(): 710 result = msgpack.loads(*args, **result_kwargs) 711 712 return result 713 714 # msgspec_messagepack 715 @staticmethod 716 def _msgspec_messagepack__dump(obj, fp, *args, **kwargs): 717 fp.write(msgspec.msgpack.encode(obj, *args, **kwargs)) 718 719 @staticmethod 720 def _msgspec_messagepack__dumps(*args, **kwargs): 721 return msgspec.msgpack.encode(*args, **kwargs) 722 723 @staticmethod 724 def _msgspec_messagepack__load(fp, *args, **kwargs): 725 with DisableGC(): 726 result = msgspec.msgpack.decode(fp.read(), *args, **kwargs) 727 728 return result 729 730 @staticmethod 731 def _msgspec_messagepack__loads(*args, **kwargs): 732 with DisableGC(): 733 result = msgspec.msgpack.decode(*args, **kwargs) 734 735 return result 736 737 # msgspec_json 738 @staticmethod 739 def _msgspec_json__dump(obj, fp, *args, **kwargs): 740 fp.write(msgspec.json.encode(obj, *args, **kwargs)) 741 742 @staticmethod 743 def _msgspec_json__dumps(*args, **kwargs): 744 return msgspec.json.encode(*args, **kwargs) 745 746 @staticmethod 747 def _msgspec_json__load(fp, *args, **kwargs): 748 with DisableGC(): 749 result = msgspec.json.decode(fp.read(), *args, **kwargs) 750 751 return result 752 753 @staticmethod 754 def _msgspec_json__loads(*args, **kwargs): 755 with DisableGC(): 756 result = msgspec.json.decode(*args, **kwargs) 757 758 return result 759 760 # msgspec_yaml 761 @staticmethod 762 def _msgspec_yaml__dump(obj, fp, *args, **kwargs): 763 fp.write(msgspec.yaml.encode(obj, *args, **kwargs)) 764 765 @staticmethod 766 def _msgspec_yaml__dumps(*args, **kwargs): 767 return msgspec.yaml.encode(*args, **kwargs) 768 769 @staticmethod 770 def _msgspec_yaml__load(fp, *args, **kwargs): 771 with DisableGC(): 772 result = msgspec.yaml.decode(fp.read(), *args, **kwargs) 773 774 return result 775 776 @staticmethod 777 def _msgspec_yaml__loads(*args, **kwargs): 778 with DisableGC(): 779 result = msgspec.yaml.decode(*args, **kwargs) 780 781 return result 782 783 # msgspec_toml 784 @staticmethod 785 def _msgspec_toml__dump(obj, fp, *args, **kwargs): 786 fp.write(msgspec.toml.encode(obj, *args, **kwargs)) 787 788 @staticmethod 789 def _msgspec_toml__dumps(*args, **kwargs): 790 return msgspec.toml.encode(*args, **kwargs) 791 792 @staticmethod 793 def _msgspec_toml__load(fp, *args, **kwargs): 794 with DisableGC(): 795 result = msgspec.toml.decode(fp.read(), *args, **kwargs) 796 797 return result 798 799 @staticmethod 800 def _msgspec_toml__loads(*args, **kwargs): 801 with DisableGC(): 802 result = msgspec.toml.decode(*args, **kwargs) 803 804 return result 805 806 # cbor 807 @staticmethod 808 def _cbor__dump(*args, **kwargs): 809 cbor.dump(*args, **kwargs) 810 811 @staticmethod 812 def _cbor__dumps(*args, **kwargs): 813 return cbor.dumps(*args, **kwargs) 814 815 @staticmethod 816 def _cbor__load(*args, **kwargs): 817 cbor.load(*args, **kwargs) 818 819 @staticmethod 820 def _cbor__loads(*args, **kwargs): 821 return cbor.loads(*args, **kwargs) 822 823 # cbor2 824 @staticmethod 825 def _cbor2__dump(*args, **kwargs): 826 cbor2.dump(*args, **kwargs) 827 828 @staticmethod 829 def _cbor2__dumps(*args, **kwargs): 830 return cbor2.dumps(*args, **kwargs) 831 832 @staticmethod 833 def _cbor2__load(*args, **kwargs): 834 cbor2.load(*args, **kwargs) 835 836 @staticmethod 837 def _cbor2__loads(*args, **kwargs): 838 return cbor2.loads(*args, **kwargs) 839 840 # marshal 841 @staticmethod 842 def _marshal__dump(*args, **kwargs): 843 if len(args) == 2: 844 result_args = args 845 else: 846 result_args = (args[0], args[1], 4) 847 marshal.dump(*result_args, **kwargs) 848 849 @staticmethod 850 def _marshal__dumps(*args, **kwargs): 851 if len(args) == 1: 852 result_args = args 853 else: 854 result_args = (args[0], 4) 855 return marshal.dumps(*result_args, **kwargs) 856 857 @staticmethod 858 def _marshal__load(*args, **kwargs): 859 return marshal.load(*args, **kwargs) 860 861 @staticmethod 862 def _marshal__loads(*args, **kwargs): 863 return marshal.loads(*args, **kwargs) 864 865 # pickle 866 @staticmethod 867 def _pickle__dump(*args, **kwargs): 868 result_kwargs = {'protocol': -1} 869 result_kwargs.update(kwargs) 870 pickle.dump(*args, **result_kwargs) 871 872 @staticmethod 873 def _pickle__dumps(*args, **kwargs): 874 result_kwargs = {'protocol': -1} 875 result_kwargs.update(kwargs) 876 return pickle.dumps(*args, **result_kwargs) 877 878 @staticmethod 879 def _pickle__load(*args, **kwargs): 880 return pickle.load(*args, **kwargs) 881 882 @staticmethod 883 def _pickle__loads(*args, **kwargs): 884 return pickle.loads(*args, **kwargs) 885 886 # cPickle 887 @staticmethod 888 def _cpickle__dump(*args, **kwargs): 889 result_kwargs = {'protocol': -1} 890 result_kwargs.update(kwargs) 891 cPickle.dump(*args, **result_kwargs) 892 893 @staticmethod 894 def _cpickle__dumps(*args, **kwargs): 895 result_kwargs = {'protocol': -1} 896 result_kwargs.update(kwargs) 897 return cPickle.dumps(*args, **result_kwargs) 898 899 @staticmethod 900 def _cpickle__load(*args, **kwargs): 901 return cPickle.load(*args, **kwargs) 902 903 @staticmethod 904 def _cpickle__loads(*args, **kwargs): 905 return cPickle.loads(*args, **kwargs) 906 907 # cloudpickle 908 @staticmethod 909 def _cloudpickle__dump(*args, **kwargs): 910 result_kwargs = {'protocol': -1} 911 result_kwargs.update(kwargs) 912 cloudpickle.dump(*args, **result_kwargs) 913 914 @staticmethod 915 def _cloudpickle__dumps(*args, **kwargs): 916 result_kwargs = {'protocol': -1} 917 result_kwargs.update(kwargs) 918 return cloudpickle.dumps(*args, **result_kwargs) 919 920 @staticmethod 921 def _cloudpickle__load(*args, **kwargs): 922 return cloudpickle.load(*args, **kwargs) 923 924 @staticmethod 925 def _cloudpickle__loads(*args, **kwargs): 926 return cloudpickle.loads(*args, **kwargs) 927 928 929def get_an_appropriate_serializers(desired_features: SerializerFeatures) -> Set[Serializers]: 930 appropriate_serializers = set() 931 for serializer_type in EXISTING_SERIALIZERS: 932 serializer_features = SERIALIZERS_DESCRIPTION[serializer_type][1] 933 if desired_features.issubset(serializer_features): 934 appropriate_serializers.add(serializer_type) 935 return appropriate_serializers 936 937 938SerializerPerformance = float 939SerializerFootprint = int 940 941 942def serializer_benchmark(serializer_type: Serializers, test_data: Optional[Any], test_time: float = 1.0 943 ) -> Tuple[SerializerPerformance, SerializerFootprint]: 944 serializer = Serializer(serializer_type) 945 measurements: List[float] = list() 946 tr = Tracer(test_time) 947 while tr.iter(): 948 start_time = perf_counter() 949 serializer.loads(serializer.dumps(test_data)) 950 measurements.append(perf_counter() - start_time) 951 952 best_measurement: float = min(measurements) 953 best_performance: Optional[float] = (1 / best_measurement) if best_measurement else None 954 data_dump = serializer.dumps(test_data) 955 return tr.iter_per_time_unit, best_performance, len(data_dump) 956 957 958def get_most_efficient_serializers(desired_features: SerializerFeatures, 959 test_data: Optional[Any], 960 test_time: float = 1.0 961 ) -> Tuple[Set[Serializers], 962 Set[Tuple[Serializers, SerializerPerformance, SerializerFootprint]]]: 963 # TODO: сделать класс, который бы подбирал количество итераций под нужное время выдержки в секундах (float) 964 # это необходимо для того чтобы правильно протестировать производительность под PyPy 965 # в дальнейшем этот функционал стоит перенести в модуль performance_test_lib 966 # TODO: make some caching algorithm. Lru can not be used since it requires all function parameters be hashable and both desired_features and test_data are not 967 968 appropriate_serializers = get_an_appropriate_serializers(desired_features) 969 970 benchmark_results = dict() # type: Dict[float, Set[Serializers]] 971 serializers_data = set() # type: Set[Tuple[Serializers, SerializerPerformance, SerializerFootprint]] 972 for serializer_type in appropriate_serializers: 973 with DisableGC(): 974 performance, best_performance, dump_size = serializer_benchmark(serializer_type, test_data, test_time) 975 976 if best_performance not in benchmark_results: 977 benchmark_results[best_performance] = set() 978 979 benchmark_results[best_performance].add(serializer_type) 980 serializers_data.add((serializer_type, best_performance, dump_size)) 981 982 best_performance = max(benchmark_results) 983 best_serializers = benchmark_results[best_performance] 984 return best_serializers, serializers_data 985 986 987def best_serializer(desired_features: SerializerFeatures, 988 test_data: Optional[Any], 989 test_time: float = 1.0 990 ) -> Serializer: 991 result = get_most_efficient_serializers( 992 desired_features, 993 test_data, 994 test_time) 995 best_serializers, _ = result 996 return Serializer(best_serializers.pop()) 997 998 999class TestDataType(enum.Enum): 1000 small = 0 1001 deep_small = 1 1002 large = 2 1003 deep_large = 3 1004 1005 1006def test_data_factory(test_data_type: TestDataType): 1007 if TestDataType.small == test_data_type: 1008 return { 1009 1: 'Hello', 1010 2: ('W', 0), 1011 3: [ 1012 'r', 1013 1, 1014 { 1015 'd': '.', 1016 'd'*2: { 1017 43: [0]*2, 1018 15: { 1019 'world': 42 1020 } 1021 } 1022 } 1023 ]*2, 1024 'To all!': '!!1' 1025 } 1026 elif TestDataType.deep_small == test_data_type: 1027 return { 1028 1: 'Hello', 1029 2: ('W', 0), 1030 3: [ 1031 'r', 1032 1, 1033 { 1034 'd': '.', 1035 'd'*2: { 1036 43: [0]*1000, 1037 15: { 1038 'world': 42 1039 } 1040 } 1041 } 1042 ]*20, 1043 'To all!': '!!1' 1044 } 1045 elif TestDataType.large == test_data_type: 1046 return { 1047 1: 'Hello'*100, 1048 2: ('W', 0), 1049 3: [ 1050 'r', 1051 1, 1052 { 1053 'd': '.', 1054 'd'*100: { 1055 43: [0]*2, 1056 15: { 1057 'world'*100: 42 1058 } 1059 } 1060 } 1061 ]*2, 1062 'To all!': '!!1'*100 1063 } 1064 elif TestDataType.deep_large == test_data_type: 1065 return { 1066 1: 'Hello'*100, 1067 2: ('W', 0), 1068 3: [ 1069 'r', 1070 1, 1071 { 1072 'd': '.', 1073 'd'*100: { 1074 43: [0]*1000, 1075 15: { 1076 'world'*100: 42 1077 } 1078 } 1079 } 1080 ]*20, 1081 'To all!': '!!1'*100 1082 } 1083 1084 1085@lru_cache(maxsize=100) 1086def best_serializer_for_standard_data(desired_features_tuple: SerializerFeaturesTuple, 1087 test_data_type: Optional[TestDataType] = None, 1088 test_time: float = 1.0 1089 ) -> Serializer: 1090 test_data_type = TestDataType.small if test_data_type is None else test_data_type 1091 return best_serializer(set(desired_features_tuple), test_data_factory(test_data_type), test_time)
class
Tags(enum.Enum):
45class Tags(enum.Enum): 46 tested = 0 47 deep = 1 # can work with nested data structures 48 superficial = 2 # can work with only single-layer of data 49 multi_platform = 3 # serialized data can be deserialized by other languages/interpreters 50 current_platform = 4 # serialized data can be deserialized by current type of python interpreter (only by CPython or only by PyPy for example) 51 multicast = 5 # ? 52 unique = 6 # ? 53 can_use_set = 7 # can serialize set type 54 can_use_bytes = 8 # can serialize bytes type 55 can_use_custom_types = 9 # can serialize custom types 56 can_use_lambda_functions = 10 57 decode_str_as_str = 11 # does not convert strings to bytes 58 decode_bytes_as_bytes = 12 # does not convert bytes to strings 59 decode_str_and_bytes_as_requested = 13 # can chose: convert all str/bytes to str or to convert all str/bytes to bytes. 60 decode_list_and_tuple_as_requested = 14 # can chose: convert all list/tuple to list or to convert all list/tuple to tuple. 61 decode_tuple_as_tuple = 15 # does not conver tuples to list/set 62 decode_list_as_list = 16 # does not convert lists to tuple/set 63 explicit_format_version = 17 # Example: pickle can be of a different versions since python-version depent so it is Not tagged as an explicit_format_version. 64 fast = 17 65 compat = 18 66 compat_with_python_below_3_8 = 19 67 compat_with_python_abowe_3_8 = 20 68 decode_set_as_set = 21 # does not convert sets to tuple/list
An enumeration.
tested =
<Tags.tested: 0>
deep =
<Tags.deep: 1>
superficial =
<Tags.superficial: 2>
multi_platform =
<Tags.multi_platform: 3>
current_platform =
<Tags.current_platform: 4>
multicast =
<Tags.multicast: 5>
unique =
<Tags.unique: 6>
can_use_set =
<Tags.can_use_set: 7>
can_use_bytes =
<Tags.can_use_bytes: 8>
can_use_custom_types =
<Tags.can_use_custom_types: 9>
can_use_lambda_functions =
<Tags.can_use_lambda_functions: 10>
decode_str_as_str =
<Tags.decode_str_as_str: 11>
decode_bytes_as_bytes =
<Tags.decode_bytes_as_bytes: 12>
decode_str_and_bytes_as_requested =
<Tags.decode_str_and_bytes_as_requested: 13>
decode_list_and_tuple_as_requested =
<Tags.decode_list_and_tuple_as_requested: 14>
decode_tuple_as_tuple =
<Tags.decode_tuple_as_tuple: 15>
decode_list_as_list =
<Tags.decode_list_as_list: 16>
explicit_format_version =
<Tags.explicit_format_version: 17>
fast =
<Tags.explicit_format_version: 17>
compat =
<Tags.compat: 18>
compat_with_python_below_3_8 =
<Tags.compat_with_python_below_3_8: 19>
compat_with_python_abowe_3_8 =
<Tags.compat_with_python_abowe_3_8: 20>
decode_set_as_set =
<Tags.decode_set_as_set: 21>
Inherited Members
- enum.Enum
- name
- value
class
DataFormats(enum.Enum):
71class DataFormats(enum.Enum): 72 any = 0 # we don't care about the serialized data format 73 json = 1 # serialized data is json 74 binary = 2 # serialized data is binary (not really human-readable) 75 text = 3 # serialized data is human-readable 76 yaml = 4 77 toml = 5 78 messagepack = 6
An enumeration.
any =
<DataFormats.any: 0>
json =
<DataFormats.json: 1>
binary =
<DataFormats.binary: 2>
text =
<DataFormats.text: 3>
yaml =
<DataFormats.yaml: 4>
toml =
<DataFormats.toml: 5>
messagepack =
<DataFormats.messagepack: 6>
Inherited Members
- enum.Enum
- name
- value
SerializerFeatures =
typing.Set[typing.Union[Tags, DataFormats]]
SerializerFeaturesTuple =
typing.Tuple[typing.Union[Tags, DataFormats]]
class
Serializers(enum.Enum):
86class Serializers(enum.Enum): 87 json = 0 88 simplejson = 1 89 ujson = 2 90 orjson = 3 91 tnetstring = 4 92 pynetstring = 5 93 msgpack_fast = 6 94 msgpack = 7 95 cbor = 8 96 cbor2 = 9 97 marshal = 10 98 marshal_compat_4 = 11 99 marshal_compat_3 = 12 100 marshal_compat_2 = 13 101 marshal_compat_1 = 14 102 marshal_compat_0 = 15 103 pickle = 16 104 pickle_default = 17 105 pickle_compat_5 = 18 106 pickle_compat_4 = 19 107 pickle_compat_3 = 20 108 pickle_compat_2 = 21 109 pickle_compat_1 = 22 110 cpickle = 23 111 cpickle_default = 24 112 cpickle_compat_5 = 25 113 cpickle_compat_4 = 26 114 cpickle_compat_3 = 27 115 cpickle_compat_2 = 28 116 cpickle_compat_1 = 29 117 cloudpickle = 30 118 cloudpickle_compat_5 = 31 119 cloudpickle_compat_4 = 32 120 cloudpickle_compat_3 = 33 121 cloudpickle_compat_2 = 34 122 cloudpickle_compat_1 = 35 123 msgspec_json = 36 124 msgspec_messagepack = 37 125 msgspec_yaml = 38 126 msgspec_toml = 39
An enumeration.
json =
<Serializers.json: 0>
simplejson =
<Serializers.simplejson: 1>
ujson =
<Serializers.ujson: 2>
orjson =
<Serializers.orjson: 3>
tnetstring =
<Serializers.tnetstring: 4>
pynetstring =
<Serializers.pynetstring: 5>
msgpack_fast =
<Serializers.msgpack_fast: 6>
msgpack =
<Serializers.msgpack: 7>
cbor =
<Serializers.cbor: 8>
cbor2 =
<Serializers.cbor2: 9>
marshal =
<Serializers.marshal: 10>
marshal_compat_4 =
<Serializers.marshal_compat_4: 11>
marshal_compat_3 =
<Serializers.marshal_compat_3: 12>
marshal_compat_2 =
<Serializers.marshal_compat_2: 13>
marshal_compat_1 =
<Serializers.marshal_compat_1: 14>
marshal_compat_0 =
<Serializers.marshal_compat_0: 15>
pickle =
<Serializers.pickle: 16>
pickle_default =
<Serializers.pickle_default: 17>
pickle_compat_5 =
<Serializers.pickle_compat_5: 18>
pickle_compat_4 =
<Serializers.pickle_compat_4: 19>
pickle_compat_3 =
<Serializers.pickle_compat_3: 20>
pickle_compat_2 =
<Serializers.pickle_compat_2: 21>
pickle_compat_1 =
<Serializers.pickle_compat_1: 22>
cpickle =
<Serializers.cpickle: 23>
cpickle_default =
<Serializers.cpickle_default: 24>
cpickle_compat_5 =
<Serializers.cpickle_compat_5: 25>
cpickle_compat_4 =
<Serializers.cpickle_compat_4: 26>
cpickle_compat_3 =
<Serializers.cpickle_compat_3: 27>
cpickle_compat_2 =
<Serializers.cpickle_compat_2: 28>
cpickle_compat_1 =
<Serializers.cpickle_compat_1: 29>
cloudpickle =
<Serializers.cloudpickle: 30>
cloudpickle_compat_5 =
<Serializers.cloudpickle_compat_5: 31>
cloudpickle_compat_4 =
<Serializers.cloudpickle_compat_4: 32>
cloudpickle_compat_3 =
<Serializers.cloudpickle_compat_3: 33>
cloudpickle_compat_2 =
<Serializers.cloudpickle_compat_2: 34>
cloudpickle_compat_1 =
<Serializers.cloudpickle_compat_1: 35>
msgspec_json =
<Serializers.msgspec_json: 36>
msgspec_messagepack =
<Serializers.msgspec_messagepack: 37>
msgspec_yaml =
<Serializers.msgspec_yaml: 38>
msgspec_toml =
<Serializers.msgspec_toml: 39>
Inherited Members
- enum.Enum
- name
- value
none_type =
<class 'NoneType'>
SUPPORTED_TYPES =
{<Serializers.json: 0>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.simplejson: 1>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.ujson: 2>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.orjson: 3>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.tnetstring: 4>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.pynetstring: 5>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.msgpack: 7>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'bytes'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.msgpack_fast: 6>: {<class 'int'>, <class 'NoneType'>, <class 'str'>, <class 'bytes'>, <class 'tuple'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.cbor: 8>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.cbor2: 9>: {<class 'NoneType'>, <class 'str'>, <class 'datetime.date'>, <class 'ipaddress.IPv4Address'>, <class 'fractions.Fraction'>, <class 'ipaddress.IPv6Network'>, <class 'uuid.UUID'>, <class 'set'>, <class 'bool'>, <class 'float'>, <class 'int'>, <class 'decimal.Decimal'>, <class 'ipaddress.IPv6Address'>, <class 'ipaddress.IPv4Network'>, <class 'list'>, <class 'datetime.datetime'>, <class 're.Pattern'>, <class 'dict'>, <class 'email.message.Message'>}, <Serializers.marshal: 10>: {<class 'int'>, <class 'complex'>, <class 'list'>, <class 'frozenset'>, <class 'NoneType'>, Ellipsis, <class 'str'>, <class 'bytes'>, <class 'tuple'>, <class 'code'>, <class 'dict'>, <class 'float'>, <class 'set'>, <class 'bool'>, <class 'bytearray'>, <class 'StopIteration'>}, <Serializers.pickle: 16>: {}, <Serializers.cpickle: 23>: {}, <Serializers.cloudpickle: 30>: {}, <Serializers.msgspec_messagepack: 37>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'bytes'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.msgspec_json: 36>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.msgspec_yaml: 38>: {<class 'int'>, <class 'NoneType'>, <class 'list'>, <class 'str'>, <class 'datetime.date'>, <class 'datetime.datetime'>, <class 'dict'>, <class 'float'>, <class 'bool'>}, <Serializers.msgspec_toml: 39>: {<class 'datetime.date'>, <class 'str'>, <class 'datetime.datetime'>, <class 'dict'>, <class 'datetime.time'>}}
SERIALIZERS_DESCRIPTION =
{<Serializers.json: 0>: ('json', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <Tags.tested: 0>, <DataFormats.json: 1>, <Tags.explicit_format_version: 17>, <Tags.decode_list_as_list: 16>, <DataFormats.text: 3>, <Tags.decode_str_as_str: 11>}), <Serializers.simplejson: 1>: ('simplejson', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <Tags.tested: 0>, <DataFormats.json: 1>, <Tags.decode_str_as_str: 11>, <Tags.explicit_format_version: 17>, <Tags.decode_list_as_list: 16>, <DataFormats.text: 3>, <Tags.can_use_bytes: 8>}), <Serializers.ujson: 2>: ('ujson', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <DataFormats.json: 1>, <Tags.decode_str_as_str: 11>, <Tags.explicit_format_version: 17>, <Tags.decode_list_as_list: 16>, <DataFormats.text: 3>, <Tags.can_use_bytes: 8>}), <Serializers.orjson: 3>: ('orjson', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <DataFormats.json: 1>, <Tags.decode_str_as_str: 11>, <Tags.explicit_format_version: 17>, <Tags.decode_list_as_list: 16>, <DataFormats.text: 3>, <Tags.can_use_bytes: 8>}), <Serializers.tnetstring: 4>: ('tnetstring', {<Tags.superficial: 2>, <Tags.current_platform: 4>, <DataFormats.any: 0>, <Tags.explicit_format_version: 17>, <DataFormats.text: 3>, <Tags.decode_str_as_str: 11>}), <Serializers.pynetstring: 5>: ('pynetstring', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <DataFormats.any: 0>, <Tags.explicit_format_version: 17>, <DataFormats.text: 3>, <Tags.decode_str_as_str: 11>}), <Serializers.msgpack: 7>: ('msgpack', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <Tags.decode_bytes_as_bytes: 12>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.decode_str_as_str: 11>, <Tags.decode_list_and_tuple_as_requested: 14>, <DataFormats.binary: 2>, <Tags.explicit_format_version: 17>, <Tags.decode_list_as_list: 16>, <DataFormats.messagepack: 6>, <Tags.decode_str_and_bytes_as_requested: 13>, <Tags.can_use_bytes: 8>}), <Serializers.msgpack_fast: 6>: ('msgpack_fast', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <Tags.decode_bytes_as_bytes: 12>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.decode_tuple_as_tuple: 15>, <Tags.decode_str_as_str: 11>, <Tags.decode_list_and_tuple_as_requested: 14>, <DataFormats.binary: 2>, <Tags.explicit_format_version: 17>, <DataFormats.messagepack: 6>, <Tags.decode_str_and_bytes_as_requested: 13>, <Tags.can_use_bytes: 8>}), <Serializers.cbor: 8>: ('cbor', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <Tags.decode_bytes_as_bytes: 12>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.decode_str_as_str: 11>, <DataFormats.binary: 2>, <Tags.explicit_format_version: 17>, <Tags.decode_list_as_list: 16>, <Tags.can_use_bytes: 8>}), <Serializers.cbor2: 9>: ('cbor2', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <Tags.decode_bytes_as_bytes: 12>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.decode_str_as_str: 11>, <DataFormats.binary: 2>, <Tags.explicit_format_version: 17>, <Tags.decode_list_as_list: 16>, <Tags.can_use_bytes: 8>}), <Serializers.marshal: 10>: ('marshal', {<Tags.superficial: 2>, <Tags.decode_bytes_as_bytes: 12>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.decode_tuple_as_tuple: 15>, <Tags.decode_str_as_str: 11>, <DataFormats.binary: 2>, <Tags.explicit_format_version: 17>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <Tags.can_use_bytes: 8>}), <Serializers.pickle: 16>: ('pickle', {<Tags.superficial: 2>, <Tags.decode_bytes_as_bytes: 12>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.decode_tuple_as_tuple: 15>, <Tags.decode_str_as_str: 11>, <DataFormats.binary: 2>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <Tags.can_use_bytes: 8>, <Tags.can_use_custom_types: 9>}), <Serializers.cpickle: 23>: ('cPickle', {<Tags.superficial: 2>, <Tags.decode_bytes_as_bytes: 12>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <Tags.decode_tuple_as_tuple: 15>, <Tags.decode_str_as_str: 11>, <DataFormats.binary: 2>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <Tags.can_use_bytes: 8>, <Tags.can_use_custom_types: 9>}), <Serializers.cloudpickle: 30>: ('cloudpickle', {<Tags.superficial: 2>, <Tags.can_use_lambda_functions: 10>, <Tags.current_platform: 4>, <Tags.deep: 1>, <Tags.decode_bytes_as_bytes: 12>, <DataFormats.any: 0>, <Tags.decode_tuple_as_tuple: 15>, <Tags.decode_str_as_str: 11>, <DataFormats.binary: 2>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <Tags.can_use_bytes: 8>, <Tags.can_use_custom_types: 9>}), <Serializers.msgspec_messagepack: 37>: ('msgspec_messagepack', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <Tags.decode_bytes_as_bytes: 12>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.decode_str_as_str: 11>, <DataFormats.binary: 2>, <Tags.explicit_format_version: 17>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <DataFormats.messagepack: 6>, <Tags.can_use_bytes: 8>}), <Serializers.msgspec_json: 36>: ('msgspec_json', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <Tags.tested: 0>, <DataFormats.json: 1>, <Tags.explicit_format_version: 17>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <DataFormats.text: 3>, <Tags.decode_str_as_str: 11>}), <Serializers.msgspec_yaml: 38>: ('msgspec_yaml', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.yaml: 4>, <DataFormats.any: 0>, <Tags.tested: 0>, <Tags.explicit_format_version: 17>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <DataFormats.text: 3>, <Tags.decode_str_as_str: 11>}), <Serializers.msgspec_toml: 39>: ('msgspec_toml', {<Tags.multi_platform: 3>, <Tags.superficial: 2>, <Tags.current_platform: 4>, <Tags.deep: 1>, <DataFormats.any: 0>, <Tags.tested: 0>, <DataFormats.toml: 5>, <Tags.explicit_format_version: 17>, <Tags.can_use_set: 7>, <Tags.decode_list_as_list: 16>, <DataFormats.text: 3>, <Tags.decode_str_as_str: 11>})}
ujson_dump_skip_parameters =
{'allow_nan', 'cls', 'check_circular', 'default', 'separators', 'skipkeys'}
ujson_dumps_skip_parameters =
{'allow_nan', 'cls', 'check_circular', 'default', 'separators', 'skipkeys'}
ujson_load_skip_parameters =
{'object_pairs_hook', 'cls', 'object_hook', 'parse_int', 'parse_constant', 'parse_float'}
ujson_loads_skip_parameters =
{'object_pairs_hook', 'cls', 'object_hook', 'parse_int', 'parse_constant', 'parse_float'}
orjson_dump_skip_parameters =
{'allow_nan', 'cls', 'check_circular', 'default', 'separators', 'skipkeys'}
orjson_dumps_skip_parameters =
{'allow_nan', 'cls', 'check_circular', 'default', 'separators', 'skipkeys'}
orjson_load_skip_parameters =
{'object_pairs_hook', 'cls', 'object_hook', 'parse_int', 'parse_constant', 'parse_float'}
orjson_loads_skip_parameters =
{'object_pairs_hook', 'cls', 'object_hook', 'parse_int', 'parse_constant', 'parse_float'}
EXISTING_SERIALIZERS =
{<Serializers.cbor: 8>, <Serializers.cbor2: 9>, <Serializers.msgpack: 7>, <Serializers.msgspec_toml: 39>, <Serializers.msgpack_fast: 6>, <Serializers.msgspec_messagepack: 37>, <Serializers.marshal: 10>, <Serializers.cloudpickle: 30>, <Serializers.json: 0>, <Serializers.msgspec_yaml: 38>, <Serializers.simplejson: 1>, <Serializers.ujson: 2>, <Serializers.pickle: 16>, <Serializers.orjson: 3>, <Serializers.msgspec_json: 36>}
class
Serializer:
492class Serializer: 493 def __init__(self, serializer: Union[None, Serializers]): 494 self.dump = None 495 self.dumps = None 496 self.load = None 497 self.loads = None 498 self._serializer = None 499 self.serializer = serializer 500 501 @property 502 def serializer(self): 503 return self._serializer 504 505 @serializer.setter 506 def serializer(self, serializer: Serializers): 507 self._serializer = serializer 508 if self._serializer is None: 509 self.dump = None 510 self.dumps = None 511 self.load = None 512 self.loads = None 513 else: 514 serializer_name, serializer_tags = SERIALIZERS_DESCRIPTION[self._serializer] 515 self.dump = getattr(self, '_{}__dump'.format(serializer_name)) 516 self.dumps = getattr(self, '_{}__dumps'.format(serializer_name)) 517 self.load = getattr(self, '_{}__load'.format(serializer_name)) 518 self.loads = getattr(self, '_{}__loads'.format(serializer_name)) 519 520 # json 521 @staticmethod 522 def _json__dump(*args, **kwargs): 523 json.dump(*args, **kwargs) 524 525 @staticmethod 526 def _json__dumps(*args, **kwargs): 527 return json.dumps(*args, **kwargs) 528 529 @staticmethod 530 def _json__load(*args, **kwargs): 531 return json.load(*args, **kwargs) 532 533 @staticmethod 534 def _json__loads(*args, **kwargs): 535 return json.loads(*args, **kwargs) 536 537 # simplejson 538 @staticmethod 539 def _simplejson__dump(*args, **kwargs): 540 simplejson.dump(*args, **kwargs) 541 542 @staticmethod 543 def _simplejson__dumps(*args, **kwargs): 544 return simplejson.dumps(*args, **kwargs) 545 546 @staticmethod 547 def _simplejson__load(*args, **kwargs): 548 return simplejson.load(*args, **kwargs) 549 550 @staticmethod 551 def _simplejson__loads(*args, **kwargs): 552 return simplejson.loads(*args, **kwargs) 553 554 # ujson 555 @staticmethod 556 def _ujson__dump(*args, **kwargs): 557 for unnecessary_parameter in ujson_dump_skip_parameters: 558 kwargs.pop(unnecessary_parameter, None) 559 ujson.dump(*args, **kwargs) 560 561 @staticmethod 562 def _ujson__dumps(*args, **kwargs): 563 for unnecessary_parameter in ujson_dumps_skip_parameters: 564 kwargs.pop(unnecessary_parameter, None) 565 return ujson.dumps(*args, **kwargs) 566 567 @staticmethod 568 def _ujson__load(*args, **kwargs): 569 for unnecessary_parameter in ujson_load_skip_parameters: 570 kwargs.pop(unnecessary_parameter, None) 571 return ujson.load(*args, **kwargs) 572 573 @staticmethod 574 def _ujson__loads(*args, **kwargs): 575 for unnecessary_parameter in ujson_loads_skip_parameters: 576 kwargs.pop(unnecessary_parameter, None) 577 return ujson.loads(*args, **kwargs) 578 579 # orjson 580 @staticmethod 581 def _orjson__dump(*args, **kwargs): 582 for unnecessary_parameter in orjson_dump_skip_parameters: 583 kwargs.pop(unnecessary_parameter, None) 584 kwargs['option'] = orjson.OPT_NON_STR_KEYS 585 orjson.dump(*args, **kwargs) 586 587 @staticmethod 588 def _orjson__dumps(*args, **kwargs): 589 for unnecessary_parameter in orjson_dumps_skip_parameters: 590 kwargs.pop(unnecessary_parameter, None) 591 kwargs['option'] = orjson.OPT_NON_STR_KEYS 592 return orjson.dumps(*args, **kwargs).decode('utf-8') 593 594 @staticmethod 595 def _orjson__load(*args, **kwargs): 596 for unnecessary_parameter in orjson_load_skip_parameters: 597 kwargs.pop(unnecessary_parameter, None) 598 return orjson.load(*args, **kwargs) 599 600 @staticmethod 601 def _orjson__loads(*args, **kwargs): 602 for unnecessary_parameter in orjson_loads_skip_parameters: 603 kwargs.pop(unnecessary_parameter, None) 604 return orjson.loads(*args, **kwargs) 605 606 # tnetstring 607 @staticmethod 608 def _tnetstring__dump(*args, **kwargs): 609 tnetstring.dump(*args, **kwargs) 610 611 @staticmethod 612 def _tnetstring__dumps(*args, **kwargs): 613 return tnetstring.dumps(*args, **kwargs) 614 615 @staticmethod 616 def _tnetstring__load(*args, **kwargs): 617 return tnetstring.load(*args, **kwargs) 618 619 @staticmethod 620 def _tnetstring__loads(*args, **kwargs): 621 return tnetstring.loads(*args, **kwargs) 622 623 # msgpack 624 @staticmethod 625 def _msgpack__dump(*args, **kwargs): 626 result_kwargs = { 627 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated. 628 'use_bin_type': True, 629 } 630 result_kwargs.update(kwargs) 631 msgpack.dump(*args, **result_kwargs) 632 633 @staticmethod 634 def _msgpack__dumps(*args, **kwargs): 635 result_kwargs = { 636 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated. 637 'use_bin_type': True, 638 } 639 result_kwargs.update(kwargs) 640 return msgpack.dumps(*args, **result_kwargs) 641 642 @staticmethod 643 def _msgpack__load(*args, **kwargs): 644 result_kwargs = { 645 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated, Use raw=False instead. 646 'raw': False, 647 'use_list': True, 648 'strict_map_key': False, 649 } 650 result_kwargs.update(kwargs) 651 with DisableGC(): 652 result = msgpack.load(*args, **result_kwargs) 653 654 return result 655 656 @staticmethod 657 def _msgpack__loads(*args, **kwargs): 658 result_kwargs = { 659 # 'encoding': 'utf-8', # PendingDeprecationWarning: encoding is deprecated, Use raw=False instead. 660 'raw': False, 661 'use_list': True, 662 'strict_map_key': False, 663 } 664 result_kwargs.update(kwargs) 665 with DisableGC(): 666 result = msgpack.loads(*args, **result_kwargs) 667 668 return result 669 670 # msgpack_fast 671 @staticmethod 672 def _msgpack_fast__dump(*args, **kwargs): 673 result_kwargs = { 674 'encoding': 'utf-8', 675 'use_bin_type': True 676 } 677 result_kwargs.update(kwargs) 678 msgpack.dump(*args, **result_kwargs) 679 680 @staticmethod 681 def _msgpack_fast__dumps(*args, **kwargs): 682 result_kwargs = { 683 'encoding': 'utf-8', 684 'use_bin_type': True 685 } 686 result_kwargs.update(kwargs) 687 return msgpack.dumps(*args, **result_kwargs) 688 689 @staticmethod 690 def _msgpack_fast__load(*args, **kwargs): 691 result_kwargs = { 692 'encoding': 'utf-8', 693 'raw': False, 694 'use_list': False 695 } 696 result_kwargs.update(kwargs) 697 with DisableGC(): 698 result = msgpack.load(*args, **result_kwargs) 699 700 return result 701 702 @staticmethod 703 def _msgpack_fast__loads(*args, **kwargs): 704 result_kwargs = { 705 'encoding': 'utf-8', 706 'raw': False, 707 'use_list': False 708 } 709 result_kwargs.update(kwargs) 710 with DisableGC(): 711 result = msgpack.loads(*args, **result_kwargs) 712 713 return result 714 715 # msgspec_messagepack 716 @staticmethod 717 def _msgspec_messagepack__dump(obj, fp, *args, **kwargs): 718 fp.write(msgspec.msgpack.encode(obj, *args, **kwargs)) 719 720 @staticmethod 721 def _msgspec_messagepack__dumps(*args, **kwargs): 722 return msgspec.msgpack.encode(*args, **kwargs) 723 724 @staticmethod 725 def _msgspec_messagepack__load(fp, *args, **kwargs): 726 with DisableGC(): 727 result = msgspec.msgpack.decode(fp.read(), *args, **kwargs) 728 729 return result 730 731 @staticmethod 732 def _msgspec_messagepack__loads(*args, **kwargs): 733 with DisableGC(): 734 result = msgspec.msgpack.decode(*args, **kwargs) 735 736 return result 737 738 # msgspec_json 739 @staticmethod 740 def _msgspec_json__dump(obj, fp, *args, **kwargs): 741 fp.write(msgspec.json.encode(obj, *args, **kwargs)) 742 743 @staticmethod 744 def _msgspec_json__dumps(*args, **kwargs): 745 return msgspec.json.encode(*args, **kwargs) 746 747 @staticmethod 748 def _msgspec_json__load(fp, *args, **kwargs): 749 with DisableGC(): 750 result = msgspec.json.decode(fp.read(), *args, **kwargs) 751 752 return result 753 754 @staticmethod 755 def _msgspec_json__loads(*args, **kwargs): 756 with DisableGC(): 757 result = msgspec.json.decode(*args, **kwargs) 758 759 return result 760 761 # msgspec_yaml 762 @staticmethod 763 def _msgspec_yaml__dump(obj, fp, *args, **kwargs): 764 fp.write(msgspec.yaml.encode(obj, *args, **kwargs)) 765 766 @staticmethod 767 def _msgspec_yaml__dumps(*args, **kwargs): 768 return msgspec.yaml.encode(*args, **kwargs) 769 770 @staticmethod 771 def _msgspec_yaml__load(fp, *args, **kwargs): 772 with DisableGC(): 773 result = msgspec.yaml.decode(fp.read(), *args, **kwargs) 774 775 return result 776 777 @staticmethod 778 def _msgspec_yaml__loads(*args, **kwargs): 779 with DisableGC(): 780 result = msgspec.yaml.decode(*args, **kwargs) 781 782 return result 783 784 # msgspec_toml 785 @staticmethod 786 def _msgspec_toml__dump(obj, fp, *args, **kwargs): 787 fp.write(msgspec.toml.encode(obj, *args, **kwargs)) 788 789 @staticmethod 790 def _msgspec_toml__dumps(*args, **kwargs): 791 return msgspec.toml.encode(*args, **kwargs) 792 793 @staticmethod 794 def _msgspec_toml__load(fp, *args, **kwargs): 795 with DisableGC(): 796 result = msgspec.toml.decode(fp.read(), *args, **kwargs) 797 798 return result 799 800 @staticmethod 801 def _msgspec_toml__loads(*args, **kwargs): 802 with DisableGC(): 803 result = msgspec.toml.decode(*args, **kwargs) 804 805 return result 806 807 # cbor 808 @staticmethod 809 def _cbor__dump(*args, **kwargs): 810 cbor.dump(*args, **kwargs) 811 812 @staticmethod 813 def _cbor__dumps(*args, **kwargs): 814 return cbor.dumps(*args, **kwargs) 815 816 @staticmethod 817 def _cbor__load(*args, **kwargs): 818 cbor.load(*args, **kwargs) 819 820 @staticmethod 821 def _cbor__loads(*args, **kwargs): 822 return cbor.loads(*args, **kwargs) 823 824 # cbor2 825 @staticmethod 826 def _cbor2__dump(*args, **kwargs): 827 cbor2.dump(*args, **kwargs) 828 829 @staticmethod 830 def _cbor2__dumps(*args, **kwargs): 831 return cbor2.dumps(*args, **kwargs) 832 833 @staticmethod 834 def _cbor2__load(*args, **kwargs): 835 cbor2.load(*args, **kwargs) 836 837 @staticmethod 838 def _cbor2__loads(*args, **kwargs): 839 return cbor2.loads(*args, **kwargs) 840 841 # marshal 842 @staticmethod 843 def _marshal__dump(*args, **kwargs): 844 if len(args) == 2: 845 result_args = args 846 else: 847 result_args = (args[0], args[1], 4) 848 marshal.dump(*result_args, **kwargs) 849 850 @staticmethod 851 def _marshal__dumps(*args, **kwargs): 852 if len(args) == 1: 853 result_args = args 854 else: 855 result_args = (args[0], 4) 856 return marshal.dumps(*result_args, **kwargs) 857 858 @staticmethod 859 def _marshal__load(*args, **kwargs): 860 return marshal.load(*args, **kwargs) 861 862 @staticmethod 863 def _marshal__loads(*args, **kwargs): 864 return marshal.loads(*args, **kwargs) 865 866 # pickle 867 @staticmethod 868 def _pickle__dump(*args, **kwargs): 869 result_kwargs = {'protocol': -1} 870 result_kwargs.update(kwargs) 871 pickle.dump(*args, **result_kwargs) 872 873 @staticmethod 874 def _pickle__dumps(*args, **kwargs): 875 result_kwargs = {'protocol': -1} 876 result_kwargs.update(kwargs) 877 return pickle.dumps(*args, **result_kwargs) 878 879 @staticmethod 880 def _pickle__load(*args, **kwargs): 881 return pickle.load(*args, **kwargs) 882 883 @staticmethod 884 def _pickle__loads(*args, **kwargs): 885 return pickle.loads(*args, **kwargs) 886 887 # cPickle 888 @staticmethod 889 def _cpickle__dump(*args, **kwargs): 890 result_kwargs = {'protocol': -1} 891 result_kwargs.update(kwargs) 892 cPickle.dump(*args, **result_kwargs) 893 894 @staticmethod 895 def _cpickle__dumps(*args, **kwargs): 896 result_kwargs = {'protocol': -1} 897 result_kwargs.update(kwargs) 898 return cPickle.dumps(*args, **result_kwargs) 899 900 @staticmethod 901 def _cpickle__load(*args, **kwargs): 902 return cPickle.load(*args, **kwargs) 903 904 @staticmethod 905 def _cpickle__loads(*args, **kwargs): 906 return cPickle.loads(*args, **kwargs) 907 908 # cloudpickle 909 @staticmethod 910 def _cloudpickle__dump(*args, **kwargs): 911 result_kwargs = {'protocol': -1} 912 result_kwargs.update(kwargs) 913 cloudpickle.dump(*args, **result_kwargs) 914 915 @staticmethod 916 def _cloudpickle__dumps(*args, **kwargs): 917 result_kwargs = {'protocol': -1} 918 result_kwargs.update(kwargs) 919 return cloudpickle.dumps(*args, **result_kwargs) 920 921 @staticmethod 922 def _cloudpickle__load(*args, **kwargs): 923 return cloudpickle.load(*args, **kwargs) 924 925 @staticmethod 926 def _cloudpickle__loads(*args, **kwargs): 927 return cloudpickle.loads(*args, **kwargs)
Serializer( serializer: typing.Union[NoneType, Serializers])
def
get_an_appropriate_serializers( desired_features: typing.Set[typing.Union[Tags, DataFormats]]) -> Set[Serializers]:
930def get_an_appropriate_serializers(desired_features: SerializerFeatures) -> Set[Serializers]: 931 appropriate_serializers = set() 932 for serializer_type in EXISTING_SERIALIZERS: 933 serializer_features = SERIALIZERS_DESCRIPTION[serializer_type][1] 934 if desired_features.issubset(serializer_features): 935 appropriate_serializers.add(serializer_type) 936 return appropriate_serializers
SerializerPerformance =
<class 'float'>
SerializerFootprint =
<class 'int'>
def
serializer_benchmark( serializer_type: Serializers, test_data: typing.Union[typing.Any, NoneType], test_time: float = 1.0) -> Tuple[float, int]:
943def serializer_benchmark(serializer_type: Serializers, test_data: Optional[Any], test_time: float = 1.0 944 ) -> Tuple[SerializerPerformance, SerializerFootprint]: 945 serializer = Serializer(serializer_type) 946 measurements: List[float] = list() 947 tr = Tracer(test_time) 948 while tr.iter(): 949 start_time = perf_counter() 950 serializer.loads(serializer.dumps(test_data)) 951 measurements.append(perf_counter() - start_time) 952 953 best_measurement: float = min(measurements) 954 best_performance: Optional[float] = (1 / best_measurement) if best_measurement else None 955 data_dump = serializer.dumps(test_data) 956 return tr.iter_per_time_unit, best_performance, len(data_dump)
def
get_most_efficient_serializers( desired_features: typing.Set[typing.Union[Tags, DataFormats]], test_data: typing.Union[typing.Any, NoneType], test_time: float = 1.0) -> Tuple[Set[Serializers], Set[Tuple[Serializers, float, int]]]:
959def get_most_efficient_serializers(desired_features: SerializerFeatures, 960 test_data: Optional[Any], 961 test_time: float = 1.0 962 ) -> Tuple[Set[Serializers], 963 Set[Tuple[Serializers, SerializerPerformance, SerializerFootprint]]]: 964 # TODO: сделать класс, который бы подбирал количество итераций под нужное время выдержки в секундах (float) 965 # это необходимо для того чтобы правильно протестировать производительность под PyPy 966 # в дальнейшем этот функционал стоит перенести в модуль performance_test_lib 967 # TODO: make some caching algorithm. Lru can not be used since it requires all function parameters be hashable and both desired_features and test_data are not 968 969 appropriate_serializers = get_an_appropriate_serializers(desired_features) 970 971 benchmark_results = dict() # type: Dict[float, Set[Serializers]] 972 serializers_data = set() # type: Set[Tuple[Serializers, SerializerPerformance, SerializerFootprint]] 973 for serializer_type in appropriate_serializers: 974 with DisableGC(): 975 performance, best_performance, dump_size = serializer_benchmark(serializer_type, test_data, test_time) 976 977 if best_performance not in benchmark_results: 978 benchmark_results[best_performance] = set() 979 980 benchmark_results[best_performance].add(serializer_type) 981 serializers_data.add((serializer_type, best_performance, dump_size)) 982 983 best_performance = max(benchmark_results) 984 best_serializers = benchmark_results[best_performance] 985 return best_serializers, serializers_data
def
best_serializer( desired_features: typing.Set[typing.Union[Tags, DataFormats]], test_data: typing.Union[typing.Any, NoneType], test_time: float = 1.0) -> Serializer:
988def best_serializer(desired_features: SerializerFeatures, 989 test_data: Optional[Any], 990 test_time: float = 1.0 991 ) -> Serializer: 992 result = get_most_efficient_serializers( 993 desired_features, 994 test_data, 995 test_time) 996 best_serializers, _ = result 997 return Serializer(best_serializers.pop())
class
TestDataType(enum.Enum):
1000class TestDataType(enum.Enum): 1001 small = 0 1002 deep_small = 1 1003 large = 2 1004 deep_large = 3
An enumeration.
small =
<TestDataType.small: 0>
deep_small =
<TestDataType.deep_small: 1>
large =
<TestDataType.large: 2>
deep_large =
<TestDataType.deep_large: 3>
Inherited Members
- enum.Enum
- name
- value
1007def test_data_factory(test_data_type: TestDataType): 1008 if TestDataType.small == test_data_type: 1009 return { 1010 1: 'Hello', 1011 2: ('W', 0), 1012 3: [ 1013 'r', 1014 1, 1015 { 1016 'd': '.', 1017 'd'*2: { 1018 43: [0]*2, 1019 15: { 1020 'world': 42 1021 } 1022 } 1023 } 1024 ]*2, 1025 'To all!': '!!1' 1026 } 1027 elif TestDataType.deep_small == test_data_type: 1028 return { 1029 1: 'Hello', 1030 2: ('W', 0), 1031 3: [ 1032 'r', 1033 1, 1034 { 1035 'd': '.', 1036 'd'*2: { 1037 43: [0]*1000, 1038 15: { 1039 'world': 42 1040 } 1041 } 1042 } 1043 ]*20, 1044 'To all!': '!!1' 1045 } 1046 elif TestDataType.large == test_data_type: 1047 return { 1048 1: 'Hello'*100, 1049 2: ('W', 0), 1050 3: [ 1051 'r', 1052 1, 1053 { 1054 'd': '.', 1055 'd'*100: { 1056 43: [0]*2, 1057 15: { 1058 'world'*100: 42 1059 } 1060 } 1061 } 1062 ]*2, 1063 'To all!': '!!1'*100 1064 } 1065 elif TestDataType.deep_large == test_data_type: 1066 return { 1067 1: 'Hello'*100, 1068 2: ('W', 0), 1069 3: [ 1070 'r', 1071 1, 1072 { 1073 'd': '.', 1074 'd'*100: { 1075 43: [0]*1000, 1076 15: { 1077 'world'*100: 42 1078 } 1079 } 1080 } 1081 ]*20, 1082 'To all!': '!!1'*100 1083 }
@lru_cache(maxsize=100)
def
best_serializer_for_standard_data( desired_features_tuple: typing.Tuple[typing.Union[Tags, DataFormats]], test_data_type: typing.Union[TestDataType, NoneType] = None, test_time: float = 1.0) -> Serializer:
1086@lru_cache(maxsize=100) 1087def best_serializer_for_standard_data(desired_features_tuple: SerializerFeaturesTuple, 1088 test_data_type: Optional[TestDataType] = None, 1089 test_time: float = 1.0 1090 ) -> Serializer: 1091 test_data_type = TestDataType.small if test_data_type is None else test_data_type 1092 return best_serializer(set(desired_features_tuple), test_data_factory(test_data_type), test_time)