Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: simplify imports #64

Merged
merged 1 commit into from
Jan 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 20 additions & 26 deletions serializable/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,23 +17,23 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) Paul Horton. All Rights Reserved.

import enum
import inspect
import json
import re
from copy import copy
from decimal import Decimal
from enum import Enum, EnumMeta, unique
from inspect import getfullargspec, getmembers, isclass
from io import StringIO, TextIOBase
from json import JSONEncoder
from json import JSONEncoder, dumps as json_dumps
from logging import NullHandler, getLogger
from re import compile as re_compile, search as re_search
from typing import (
TYPE_CHECKING,
Any,
Callable,
Dict,
Iterable,
List,
Literal,
Optional,
Protocol,
Set,
Tuple,
Type,
Expand All @@ -49,12 +49,6 @@
from .formatters import BaseNameFormatter, CurrentFormatter
from .helpers import BaseHelper

if TYPE_CHECKING: # pragma: no cover
from typing import Literal, Protocol
else:
from abc import ABC
Protocol = ABC

# `Intersection` is still not implemented, so it is interim replaced by Union for any support
# see section "Intersection" in https://peps.python.org/pep-0483/
# see https://github.com/python/typing/issues/213
Expand Down Expand Up @@ -84,11 +78,11 @@ class ViewType:

_F = TypeVar('_F', bound=Callable[..., Any])
_T = TypeVar('_T')
_E = TypeVar('_E', bound=enum.Enum)
_E = TypeVar('_E', bound=Enum)


@enum.unique
class SerializationType(str, enum.Enum):
@unique
class SerializationType(str, Enum):
"""
Enum to define the different formats supported for serialization and deserialization.
"""
Expand All @@ -103,8 +97,8 @@ class SerializationType(str, enum.Enum):
)


@enum.unique
class XmlArraySerializationType(enum.Enum):
@unique
class XmlArraySerializationType(Enum):
"""
Enum to differentiate how array-type properties (think Iterables) are serialized.

Expand Down Expand Up @@ -183,7 +177,7 @@ def view(self) -> Optional[Type[ViewType]]:

def default(self, o: Any) -> Any:
# Enum
if isinstance(o, enum.Enum):
if isinstance(o, Enum):
return o.value

# Iterables
Expand Down Expand Up @@ -260,7 +254,7 @@ def as_json(self: Any, view_: Optional[Type[ViewType]] = None) -> str:
``serializable``.
"""
_logger.debug('Dumping %s to JSON with view: %s...', self, view_)
return json.dumps(self, cls=_SerializableJsonEncoder, view_=view_)
return json_dumps(self, cls=_SerializableJsonEncoder, view_=view_)

@classmethod
def from_json(cls: Type[_T], data: Dict[str, Any]) -> Optional[_T]:
Expand Down Expand Up @@ -517,7 +511,7 @@ def from_xml(cls: Type[_T], data: Union[TextIOBase, Element],
_namespaces = dict([node for _, node in
SafeElementTree.iterparse(StringIO(SafeElementTree.tostring(data, 'unicode')),
events=['start-ns'])])
default_namespace = (re.compile(r'^\{(.*?)\}.').search(data.tag) or (None, _namespaces.get('')))[1]
default_namespace = (re_compile(r'^\{(.*?)\}.').search(data.tag) or (None, _namespaces.get('')))[1]

if default_namespace is None:
def strip_default_namespace(s: str) -> str:
Expand Down Expand Up @@ -678,7 +672,7 @@ class ObjectMetadataLibrary:
_klass_property_types: Dict[str, type] = {}
_klass_property_views: Dict[str, Set[Type[ViewType]]] = {}
_klass_property_xml_sequence: Dict[str, int] = {}
custom_enum_klasses: Set[Type[enum.Enum]] = set()
custom_enum_klasses: Set[Type[Enum]] = set()
klass_mappings: Dict[str, 'ObjectMetadataLibrary.SerializableClass'] = {}
klass_property_mappings: Dict[str, Dict[str, 'ObjectMetadataLibrary.SerializableProperty']] = {}

Expand Down Expand Up @@ -847,7 +841,7 @@ def get_none_value(self, view_: Optional[Type[ViewType]] = None) -> Any:

def is_helper_type(self) -> bool:
ct = self.custom_type
return inspect.isclass(ct) and issubclass(ct, BaseHelper)
return isclass(ct) and issubclass(ct, BaseHelper)

def is_primitive_type(self) -> bool:
return self.concrete_type in self._PRIMITIVE_TYPES
Expand All @@ -868,7 +862,7 @@ def _parse_type(self, type_: Any) -> None:
self._is_optional = True
type_to_parse = type_to_parse[9:-1]

match = re.search(r"^(?P<array_type>[\w.]+)\[['\"]?(?P<array_of>\w+)['\"]?]$", type_to_parse)
match = re_search(r"^(?P<array_type>[\w.]+)\[['\"]?(?P<array_of>\w+)['\"]?]$", type_to_parse)
if match:
results = match.groupdict()
if results.get('array_type', None) in self._SORTED_CONTAINERS_TYPES:
Expand Down Expand Up @@ -956,7 +950,7 @@ def _parse_type(self, type_: Any) -> None:
self._concrete_type = self.type_

# Handle Enums
if issubclass(type(self.concrete_type), enum.EnumMeta):
if issubclass(type(self.concrete_type), EnumMeta):
self._is_enum = True

# Ensure marked as not deferred
Expand Down Expand Up @@ -1033,9 +1027,9 @@ def register_klass(cls, klass: Type[_T], custom_name: Optional[str],
qualified_class_name = f'{klass.__module__}.{klass.__qualname__}'
cls.klass_property_mappings.update({qualified_class_name: {}})
_logger.debug('Registering Class %s with custom name %s', qualified_class_name, custom_name)
for name, o in inspect.getmembers(klass, ObjectMetadataLibrary.is_property):
for name, o in getmembers(klass, ObjectMetadataLibrary.is_property):
qualified_property_name = f'{qualified_class_name}.{name}'
prop_arg_specs = inspect.getfullargspec(o.fget)
prop_arg_specs = getfullargspec(o.fget)

cls.klass_property_mappings[qualified_class_name].update({
name: ObjectMetadataLibrary.SerializableProperty(
Expand Down
10 changes: 5 additions & 5 deletions serializable/formatters.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) Paul Horton. All Rights Reserved.

import re
from abc import ABC, abstractmethod
from re import compile as re_compile
from typing import Type


Expand Down Expand Up @@ -49,8 +49,8 @@ def encode_handle_python_builtins_and_keywords(cls, name: str) -> str:


class CamelCasePropertyNameFormatter(BaseNameFormatter):
_ENCODE_PATTERN = re.compile(r'_([a-z])')
_DECODE_PATTERN = re.compile(r'(?<!^)(?=[A-Z])')
_ENCODE_PATTERN = re_compile(r'_([a-z])')
_DECODE_PATTERN = re_compile(r'(?<!^)(?=[A-Z])')

@classmethod
def encode(cls, property_name: str) -> str:
Expand All @@ -67,7 +67,7 @@ def decode(cls, property_name: str) -> str:


class KebabCasePropertyNameFormatter(BaseNameFormatter):
_ENCODE_PATTERN = re.compile(r'(_)')
_ENCODE_PATTERN = re_compile(r'(_)')

@classmethod
def encode(cls, property_name: str) -> str:
Expand All @@ -81,7 +81,7 @@ def decode(cls, property_name: str) -> str:


class SnakeCasePropertyNameFormatter(BaseNameFormatter):
_ENCODE_PATTERN = re.compile(r'(.)([A-Z][a-z]+)')
_ENCODE_PATTERN = re_compile(r'(.)([A-Z][a-z]+)')

@classmethod
def encode(cls, property_name: str) -> str:
Expand Down
4 changes: 2 additions & 2 deletions serializable/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
# SPDX-License-Identifier: Apache-2.0
# Copyright (c) Paul Horton. All Rights Reserved.

import re
from datetime import date, datetime
from logging import getLogger
from re import sub as re_sub
from typing import TYPE_CHECKING, Any, Optional, Type, TypeVar, Union

if TYPE_CHECKING: # pragma: no cover
Expand Down Expand Up @@ -191,7 +191,7 @@ def deserialize(cls, o: Any) -> datetime:
o = str(o)[1:]

# Ensure any milliseconds are 6 digits
o = re.sub(r'\.(\d{1,6})', lambda v: f'.{int(v.group()[1:]):06}', str(o))
o = re_sub(r'\.(\d{1,6})', lambda v: f'.{int(v.group()[1:]):06}', str(o))

if str(o).endswith('Z'):
# Replace ZULU time with 00:00 offset
Expand Down