Source code for yatel.typeconv

#!/usr/bin/env python
# -*- coding: utf-8 -*-

# "THE WISKEY-WARE LICENSE":
# <utn_kdd@googlegroups.com> wrote this file. As long as you retain this notice
# you can do whatever you want with this stuff. If we meet some day, and you
# think this stuff is worth it, you can buy us a WISKEY in return.


# =============================================================================
# DOCS
# =============================================================================

"""Contains functions to convert various support types of Yatel to more easily
serializable types.

"""

# =============================================================================
# IMPORTS
# =============================================================================

import decimal
import datetime
import types

import numpy as np

from yatel import dom

# =============================================================================
# CONSTANTS
# =============================================================================

#: Constant to retrieve  value as is.
LITERAL_TYPE = "literal"

CONTAINER_TYPES = (tuple, set, list, frozenset, types.GeneratorType)

#: Dictionary of yatel domain object model.
HASHED_TYPES = tuple([dict] + dom.YatelDOM.__subclasses__())

#: This dictionary maps types to it's most simple representation.
TO_SIMPLE_TYPES = {
    datetime.datetime: lambda x: x.isoformat(),
    datetime.time: lambda x: x.isoformat(),
    datetime.date: lambda x: x.isoformat(),
    bool: lambda x: x,
    int: lambda x: x,
    long: lambda x: x,
    float: lambda x: x,
    str: unicode,
    unicode: lambda x: x,
    decimal.Decimal: lambda x: unicode(x),
    types.NoneType: lambda x: None,
    complex: lambda x: unicode(x)
}

#: This dictionary maps types to python types.
TO_PYTHON_TYPES = {
    datetime.datetime:
        lambda x: datetime.datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%f"),
    datetime.time:
        lambda x: datetime.datetime.strptime(x, "%H:%M:%S.%f").time(),
    datetime.date:
        lambda x: datetime.datetime.strptime(x, "%Y-%m-%d").date(),
    bool:
        lambda x: x.lower() == "true" if isinstance(x, basestring) else bool(x),
    long: long,
    int: int,
    float: float,
    str: unicode,
    unicode: unicode,
    decimal.Decimal: decimal.Decimal,
    type(None): lambda x: None,
    complex: complex
}

#: This dictionary maps data types to their name.
TYPES_TO_NAMES = dict(
    (k, k.__name__)
    for k in TO_SIMPLE_TYPES.keys() +
    list(CONTAINER_TYPES) +
    list(HASHED_TYPES) + [type]
)
TYPES_TO_NAMES[str] = unicode.__name__

#: This dictionary maps names to data type.
NAMES_TO_TYPES = dict((v, k) for k, v in TYPES_TO_NAMES.items())


# =============================================================================
# FUNCTIONS
# =============================================================================

[docs]def np2py(obj): """Converts a numpy number to it´s closest respresentation of Python traditional objects. """ # http://stackoverflow.com/questions/9452775/converting-numpy-dtypes-to-native-python-types if isinstance(obj, np.ndarray): return [np2py(e) for e in obj] elif isinstance(obj, np.number): obj = np.asscalar(obj) if type(obj) in TO_SIMPLE_TYPES: return obj elif isinstance(obj, np.longdouble): return float(obj) elif "float" in pytype.__name__: return float(obj) elif "complex" in pytype.__name__: return complex(obj) elif isinstance(obj, np.bool_): return bool(obj) return str(obj)
[docs]def simplifier(obj): """Translates obj given to a Python dictionary. Returns ------- dictionary: dict a dictionary representation of obj. """ # numpy simplifier if isinstance(obj, (np.generic, np.ndarray)): obj = np2py(obj) typename = TYPES_TO_NAMES[type(obj)] value = "" if isinstance(obj, CONTAINER_TYPES): value = map(simplifier, obj) elif isinstance(obj, HASHED_TYPES): value = dict((k, simplifier(v)) for k, v in obj.items()) elif type(obj) == type: value = TYPES_TO_NAMES[obj] else: value = TO_SIMPLE_TYPES[type(obj)](obj) return {"type": typename, "value": value}
[docs]def parse(obj): """Parses an objects type and value, according to the dictionary maps. """ typename = obj["type"] value = obj["value"] if typename == LITERAL_TYPE: return value otype = NAMES_TO_TYPES[typename] if otype in CONTAINER_TYPES: value = map(parse, value) elif otype in HASHED_TYPES: data = dict((k, parse(v)) for k, v in value.items()) value = otype(**data) elif otype == type: value = NAMES_TO_TYPES[value] else: value = TO_PYTHON_TYPES[otype](value) return value # ============================================================================= # MAIN # =============================================================================
if __name__ == "__main__": print(__doc__)