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>
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'}
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])
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
dump
dumps
load
loads
serializer
501    @property
502    def serializer(self):
503        return self._serializer
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
def test_data_factory( test_data_type: TestDataType):
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)