Module moexalgo.utils

Expand source code
import decimal
import json as _json
from datetime import datetime, date, time


class RequiredImport:

    def __init__(self, name):
        self.__name = name

    def __getattr__(self, item):
        raise ImportError(f'Required `{self.__name}`')


try:
    import pandas
except ImportError:
    pandas = RequiredImport('pandas')


def is_interactive():
    """ Возвращает `True` если код исполняется в интерактивном режиме, например в jupiter notebook
    """
    import __main__ as main
    return not hasattr(main, '__file__')


class json:
    """ Расширение JSON енкодера
    """
    loads = _json.loads
    JSONDecodeError = _json.JSONDecodeError

    @staticmethod
    def dumps(*args, **kwargs):
        """

        Parameters
        ----------
        args
        kwargs

        Returns
        -------

        """

        def default(obj):
            """

            Parameters
            ----------
            obj

            Returns
            -------

            """
            if isinstance(obj, decimal.Decimal):
                return float(str(obj))
            elif isinstance(obj, (datetime, date, time)):
                return obj.isoformat()
            raise TypeError

        return _json.dumps(*args, **kwargs, default=default)


def result_deserializer(data: dict, *sections, key=None):
    """

    Parameters
    ----------
    data
    sections
    key

    Returns
    -------

    """
    result = dict()
    sections = sections or ('securities', 'marketdata')
    for section in sections:
        metadata = data[section]['metadata']
        columns = data[section]['columns']
        for values in data[section]['data']:
            item = item_normalizer(metadata, dict(zip(columns, values)))
            if key:
                result.setdefault(section, dict())[key(item)] = item
            else:
                result.setdefault(section, list()).append(item)
    return result


def item_normalizer(metadata, item):
    """

    Parameters
    ----------
    metadata
    item

    Returns
    -------

    """
    conv = {'int32': lambda s: int(s) if s is not None else None,
            'int64': lambda s: int(s) if s is not None else None,
            'double': lambda s: float(s) if s is not None else None,
            'date': lambda s: date.fromisoformat(s.strip()) if s is not None and s != '0000-00-00' else None,
            'datetime': lambda s: datetime.fromisoformat(s.strip()) if s is not None else None,
            'time': lambda s: time.fromisoformat(s.strip()) if s is not None else None}
    return dict((key, conv.get(metadata[key]['type'], str)(value)) for key, value in item.items())

Functions

def is_interactive()

Возвращает True если код исполняется в интерактивном режиме, например в jupiter notebook

Expand source code
def is_interactive():
    """ Возвращает `True` если код исполняется в интерактивном режиме, например в jupiter notebook
    """
    import __main__ as main
    return not hasattr(main, '__file__')
def item_normalizer(metadata, item)

Parameters

metadata
 
item
 

Returns

Expand source code
def item_normalizer(metadata, item):
    """

    Parameters
    ----------
    metadata
    item

    Returns
    -------

    """
    conv = {'int32': lambda s: int(s) if s is not None else None,
            'int64': lambda s: int(s) if s is not None else None,
            'double': lambda s: float(s) if s is not None else None,
            'date': lambda s: date.fromisoformat(s.strip()) if s is not None and s != '0000-00-00' else None,
            'datetime': lambda s: datetime.fromisoformat(s.strip()) if s is not None else None,
            'time': lambda s: time.fromisoformat(s.strip()) if s is not None else None}
    return dict((key, conv.get(metadata[key]['type'], str)(value)) for key, value in item.items())
def result_deserializer(data: dict, *sections, key=None)

Parameters

data
 
sections
 
key
 

Returns

Expand source code
def result_deserializer(data: dict, *sections, key=None):
    """

    Parameters
    ----------
    data
    sections
    key

    Returns
    -------

    """
    result = dict()
    sections = sections or ('securities', 'marketdata')
    for section in sections:
        metadata = data[section]['metadata']
        columns = data[section]['columns']
        for values in data[section]['data']:
            item = item_normalizer(metadata, dict(zip(columns, values)))
            if key:
                result.setdefault(section, dict())[key(item)] = item
            else:
                result.setdefault(section, list()).append(item)
    return result

Classes

class RequiredImport (name)
Expand source code
class RequiredImport:

    def __init__(self, name):
        self.__name = name

    def __getattr__(self, item):
        raise ImportError(f'Required `{self.__name}`')
class json

Расширение JSON енкодера

Expand source code
class json:
    """ Расширение JSON енкодера
    """
    loads = _json.loads
    JSONDecodeError = _json.JSONDecodeError

    @staticmethod
    def dumps(*args, **kwargs):
        """

        Parameters
        ----------
        args
        kwargs

        Returns
        -------

        """

        def default(obj):
            """

            Parameters
            ----------
            obj

            Returns
            -------

            """
            if isinstance(obj, decimal.Decimal):
                return float(str(obj))
            elif isinstance(obj, (datetime, date, time)):
                return obj.isoformat()
            raise TypeError

        return _json.dumps(*args, **kwargs, default=default)

Class variables

var JSONDecodeError

Subclass of ValueError with the following additional properties:

msg: The unformatted error message doc: The JSON document being parsed pos: The start index of doc where parsing failed lineno: The line corresponding to pos colno: The column corresponding to pos

Static methods

def dumps(*args, **kwargs)

Parameters

args
 
kwargs
 

Returns

Expand source code
@staticmethod
def dumps(*args, **kwargs):
    """

    Parameters
    ----------
    args
    kwargs

    Returns
    -------

    """

    def default(obj):
        """

        Parameters
        ----------
        obj

        Returns
        -------

        """
        if isinstance(obj, decimal.Decimal):
            return float(str(obj))
        elif isinstance(obj, (datetime, date, time)):
            return obj.isoformat()
        raise TypeError

    return _json.dumps(*args, **kwargs, default=default)

Methods

def loads(s, *, cls=None, object_hook=None, parse_float=None, parse_int=None, parse_constant=None, object_pairs_hook=None, **kw)

Deserialize s (a str, bytes or bytearray instance containing a JSON document) to a Python object.

object_hook is an optional function that will be called with the result of any object literal decode (a dict). The return value of object_hook will be used instead of the dict. This feature can be used to implement custom decoders (e.g. JSON-RPC class hinting).

object_pairs_hook is an optional function that will be called with the result of any object literal decoded with an ordered list of pairs. The return value of object_pairs_hook will be used instead of the dict. This feature can be used to implement custom decoders. If object_hook is also defined, the object_pairs_hook takes priority.

parse_float, if specified, will be called with the string of every JSON float to be decoded. By default this is equivalent to float(num_str). This can be used to use another datatype or parser for JSON floats (e.g. decimal.Decimal).

parse_int, if specified, will be called with the string of every JSON int to be decoded. By default this is equivalent to int(num_str). This can be used to use another datatype or parser for JSON integers (e.g. float).

parse_constant, if specified, will be called with one of the following strings: -Infinity, Infinity, NaN. This can be used to raise an exception if invalid JSON numbers are encountered.

To use a custom JSONDecoder subclass, specify it with the cls kwarg; otherwise JSONDecoder is used.

Expand source code
def loads(s, *, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    """Deserialize ``s`` (a ``str``, ``bytes`` or ``bytearray`` instance
    containing a JSON document) to a Python object.

    ``object_hook`` is an optional function that will be called with the
    result of any object literal decode (a ``dict``). The return value of
    ``object_hook`` will be used instead of the ``dict``. This feature
    can be used to implement custom decoders (e.g. JSON-RPC class hinting).

    ``object_pairs_hook`` is an optional function that will be called with the
    result of any object literal decoded with an ordered list of pairs.  The
    return value of ``object_pairs_hook`` will be used instead of the ``dict``.
    This feature can be used to implement custom decoders.  If ``object_hook``
    is also defined, the ``object_pairs_hook`` takes priority.

    ``parse_float``, if specified, will be called with the string
    of every JSON float to be decoded. By default this is equivalent to
    float(num_str). This can be used to use another datatype or parser
    for JSON floats (e.g. decimal.Decimal).

    ``parse_int``, if specified, will be called with the string
    of every JSON int to be decoded. By default this is equivalent to
    int(num_str). This can be used to use another datatype or parser
    for JSON integers (e.g. float).

    ``parse_constant``, if specified, will be called with one of the
    following strings: -Infinity, Infinity, NaN.
    This can be used to raise an exception if invalid JSON numbers
    are encountered.

    To use a custom ``JSONDecoder`` subclass, specify it with the ``cls``
    kwarg; otherwise ``JSONDecoder`` is used.
    """
    if isinstance(s, str):
        if s.startswith('\ufeff'):
            raise JSONDecodeError("Unexpected UTF-8 BOM (decode using utf-8-sig)",
                                  s, 0)
    else:
        if not isinstance(s, (bytes, bytearray)):
            raise TypeError(f'the JSON object must be str, bytes or bytearray, '
                            f'not {s.__class__.__name__}')
        s = s.decode(detect_encoding(s), 'surrogatepass')

    if (cls is None and object_hook is None and
            parse_int is None and parse_float is None and
            parse_constant is None and object_pairs_hook is None and not kw):
        return _default_decoder.decode(s)
    if cls is None:
        cls = JSONDecoder
    if object_hook is not None:
        kw['object_hook'] = object_hook
    if object_pairs_hook is not None:
        kw['object_pairs_hook'] = object_pairs_hook
    if parse_float is not None:
        kw['parse_float'] = parse_float
    if parse_int is not None:
        kw['parse_int'] = parse_int
    if parse_constant is not None:
        kw['parse_constant'] = parse_constant
    return cls(**kw).decode(s)