Esempio n. 1
0
def _imports(graph: mapry.Graph, py: mapry.Py) -> str:
    """
    Generate the import statements.

    :param graph: mapry definition of the object graph
    :param py: Python settings
    :return: generated code
    """
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-statements
    stdlib_block = {'import collections', 'import typing'}

    if mapry.needs_type(a_type=graph, query=mapry.Duration):
        stdlib_block.add('import datetime')

    if (mapry.needs_type(a_type=graph, query=mapry.Class)
            or mapry.needs_type(a_type=graph, query=mapry.Embed)):
        stdlib_block.add('import collections')

    first_party_block = {'import {}'.format(py.module_name)}

    # yapf: disable
    return '\n\n'.join([
        '\n'.join(sorted(stdlib_block)),
        '\n'.join(sorted(first_party_block))
    ])
Esempio n. 2
0
    def test_value_needs_type(self) -> None:
        type_definition = mapry.Path()

        self.assertTrue(
            mapry.needs_type(a_type=type_definition, query=mapry.Path))

        self.assertFalse(
            mapry.needs_type(a_type=type_definition, query=mapry.Date))
Esempio n. 3
0
    def test_embed_needs_type(self) -> None:
        embed = mapry.Embed(name='some_embed', description='', ref='')

        embed.properties = {
            'some_property':
            dummy_property(name='some_property',
                           a_type=mapry.Path(),
                           composite=embed)
        }

        self.assertTrue(mapry.needs_type(a_type=embed, query=mapry.Path))
        self.assertFalse(mapry.needs_type(a_type=embed, query=mapry.Date))
Esempio n. 4
0
    def test_class_needs_type(self) -> None:
        cls = mapry.Class(name='some_class', plural='', description='', ref='')
        cls.name = 'some_class'
        cls.properties = {
            'some_property':
            dummy_property(name='some_property',
                           a_type=mapry.Path(),
                           composite=cls)
        }

        self.assertTrue(mapry.needs_type(a_type=cls, query=mapry.Path))
        self.assertFalse(mapry.needs_type(a_type=cls, query=mapry.Date))
Esempio n. 5
0
def generate(graph: mapry.Graph, py: mapry.Py) -> str:
    """
    Generate the source file to parse an object graph from a JSONable object.

    :param graph: mapry definition of the object graph
    :param py: Python settings
    :return: content of the source file
    """
    blocks = [
        mapry.py.generate.WARNING,
        mapry.py.generate.docstring("serializes to JSONable objects."),
        _imports(graph=graph, py=py)
    ]

    if mapry.needs_type(a_type=graph, query=mapry.Duration):
        blocks.append(_duration_to_string())

    nongraph_composites = []  # type: List[Union[mapry.Class, mapry.Embed]]
    nongraph_composites.extend(graph.classes.values())
    nongraph_composites.extend(graph.embeds.values())

    for class_or_embed in nongraph_composites:
        blocks.append(
            _serialize_class_or_embed(class_or_embed=class_or_embed, py=py))

    blocks.append(_serialize_graph(graph=graph, py=py))

    blocks.append(mapry.py.generate.WARNING)

    return '\n\n\n'.join(blocks) + '\n'
Esempio n. 6
0
def generate(graph: mapry.Graph, go: mapry.Go) -> str:
    """
    Generate the source file to test serializing to a JSONable.

    :param graph: mapry definition of the object graph
    :param go: Go settings
    :return: content of the source file
    """
    blocks = [
        'package {}'.format(go.package),
        mapry.go.generate.WARNING,
    ]

    has_body = False

    import_decl = _imports(graph=graph)
    if len(import_decl) > 0:
        blocks.append(import_decl)
        has_body = True

    if mapry.needs_type(a_type=graph, query=mapry.Duration):
        blocks.append(_example_duration_to_string())
        has_body = True

    # Include the footer only if there was something after the header
    if has_body:
        blocks.append(mapry.go.generate.WARNING)

    return mapry.indention.reindent(text='\n\n'.join(blocks) + '\n',
                                    indention='\t')
Esempio n. 7
0
def generate(graph: mapry.Graph, go: mapry.Go) -> str:
    """
    Generate the source file to serialize an object graph to a JSONable object.

    :param graph: mapry definition of the object graph
    :param go: Go settings
    :return: content of the source file
    """
    blocks = [
        'package {}'.format(go.package),
        mapry.go.generate.WARNING,
    ]

    import_block = _imports(graph=graph)
    if len(import_block) > 0:
        blocks.append(import_block)

    if mapry.needs_type(a_type=graph, query=mapry.Duration):
        blocks.append(_duration_to_string())

    nongraph_composites = []  # type: List[Union[mapry.Class, mapry.Embed]]
    nongraph_composites.extend(graph.classes.values())
    nongraph_composites.extend(graph.embeds.values())

    for class_or_embed in nongraph_composites:
        blocks.append(
            _serialize_class_or_embed(class_or_embed=class_or_embed, go=go))

    blocks.append(_serialize_graph(graph=graph, go=go))

    blocks.append(mapry.go.generate.WARNING)

    return mapry.indention.reindent(text='\n\n'.join(blocks) + '\n',
                                    indention='\t')
Esempio n. 8
0
def _imports(graph: mapry.Graph, py: mapry.Py) -> str:
    """
    Generate the import statements.

    :param graph: mapry definition of the object graph
    :param py: Python settings
    :return: generated code
    """
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-statements
    stdlib_block = {'import typing'}

    if mapry.needs_type(a_type=graph, query=mapry.Path):
        if py.path_as == 'str':
            pass
        elif py.path_as == "pathlib.Path":
            stdlib_block.add("import pathlib")
        else:
            raise NotImplementedError("Unhandled path_as: {!r}".format(
                py.path_as))

    if mapry.needs_type(a_type=graph, query=mapry.TimeZone):
        if py.timezone_as == 'str':
            pass

        elif py.timezone_as == 'pytz.timezone':
            stdlib_block.add('import datetime')

        else:
            raise NotImplementedError('Unhandled timezone_as: {}'.format(
                py.timezone_as))

    # yapf: disable
    if any(mapry.needs_type(a_type=graph, query=query)
           for query in (mapry.Date, mapry.Time, mapry.Datetime,
                         mapry.Duration)):
        # yapf: enable
        stdlib_block.add('import datetime')

    if len(graph.classes) > 0:
        # Needed for the initialization of class registries
        stdlib_block.add('import collections')

    return '\n'.join(sorted(stdlib_block))
Esempio n. 9
0
def _imports(graph: mapry.Graph) -> str:
    """
    Generate the import declaration.

    :param graph: mapry definition of the object graph
    :return: generated code
    """
    import_set = set()  # type: Set[str]

    if mapry.needs_type(a_type=graph, query=mapry.Duration):
        import_set.add('fmt')

    return mapry.go.generate.import_declarations(import_set)
Esempio n. 10
0
def _imports(graph: mapry.Graph) -> str:
    """
    Generate the import declaration(s).

    :param graph: mapry definition of the object graph
    :return: generated code
    """
    import_set = set()  # type: Set[str]

    # yapf: disable
    if any(mapry.needs_type(a_type=graph, query=query)
           for query in (mapry.Date, mapry.Time, mapry.Datetime,
                         mapry.Duration, mapry.TimeZone)):
        # yapf: enable
        import_set.add('time')

    return mapry.go.generate.import_declarations(import_set=import_set)
Esempio n. 11
0
    def test_graph_needs_type(self) -> None:
        # Property of an object graph
        graph = mapry.Graph()
        graph.properties = {
            "some_property":
            dummy_property(name='some_property',
                           a_type=mapry.Path(),
                           composite=graph)
        }

        self.assertTrue(mapry.needs_type(a_type=graph, query=mapry.Path))
        self.assertFalse(mapry.needs_type(a_type=graph, query=mapry.Date))

        # Recursively needs type by a property of a class
        cls = mapry.Class(name='some_class', plural='', description='', ref='')
        cls.properties = {
            'some_property':
            dummy_property(name='some_property',
                           a_type=mapry.Path(),
                           composite=cls)
        }

        graph = mapry.Graph()
        graph.classes = {cls.name: cls}
        self.assertTrue(mapry.needs_type(a_type=graph, query=mapry.Path))
        self.assertFalse(mapry.needs_type(a_type=graph, query=mapry.Date))

        # Recursively needs type by a property of an embeddable structure
        embed = mapry.Embed(name='some_embed', description='', ref='')
        embed.properties = {
            'some_property':
            dummy_property(name='some_property',
                           a_type=mapry.Path(),
                           composite=embed)
        }

        graph = mapry.Graph()
        graph.embeds = {embed.name: embed}
        self.assertTrue(mapry.needs_type(a_type=graph, query=mapry.Path))
        self.assertFalse(mapry.needs_type(a_type=graph, query=mapry.Date))
Esempio n. 12
0
def _includes(graph: mapry.Graph, cpp: mapry.Cpp) -> str:
    """
    Generate the include directives.

    :param graph: mapry definition of the object graph
    :param cpp: C++ settings
    :return: generated code
    """
    # pylint: disable=too-many-branches
    # pylint: disable=too-many-statements
    stl_block = set()  # type: Set[str]
    third_party_block = set()  # type: Set[str]

    if mapry.needs_type(a_type=graph, query=mapry.Integer):
        stl_block.add("#include <cstdint>")

    if mapry.needs_type(a_type=graph, query=mapry.String):
        stl_block.add("#include <string>")

    if mapry.needs_type(a_type=graph, query=mapry.Path):
        if cpp.path_as == 'std::filesystem::path':
            stl_block.add("#include <filesystem>")
        elif cpp.path_as == "boost::filesystem::path":
            third_party_block.add("#include <boost/filesystem/path.hpp>")
        else:
            raise NotImplementedError(
                "Unhandled cpp.path_as: {!r}".format(cpp.path_as))

    date_time_types = [mapry.Date, mapry.Time, mapry.Datetime]
    if cpp.datetime_library == 'ctime':
        for query_type in date_time_types:
            if mapry.needs_type(a_type=graph, query=query_type):
                stl_block.add("#include <ctime>")

        if mapry.needs_type(a_type=graph, query=mapry.TimeZone):
            stl_block.add("#include <string>")

    elif cpp.datetime_library == 'date.h':
        if any(mapry.needs_type(a_type=graph, query=query_type)
               for query_type in [mapry.Date, mapry.Time, mapry.Datetime]):
            third_party_block.add("#include <date/date.h>")

        if mapry.needs_type(a_type=graph, query=mapry.Time):
            stl_block.add("#include <chrono>")

        if mapry.needs_type(a_type=graph, query=mapry.TimeZone):
            third_party_block.add("#include <date/tz.h>")

    else:
        raise NotImplementedError(
            "Unhandled cpp.datetime_library: {!r}".format(cpp.datetime_library))

    if mapry.needs_type(a_type=graph, query=mapry.Duration):
        stl_block.add("#include <chrono>")

    if mapry.needs_type(a_type=graph, query=mapry.Array):
        stl_block.add("#include <vector>")

    if mapry.needs_type(a_type=graph, query=mapry.Map):
        stl_block.add("#include <map>")

    if graph.classes:
        stl_block.add("#include <map>")
        stl_block.add("#include <string>")
        stl_block.add("#include <memory>")

    # Check for optional fields
    # yapf: disable
    has_optional = (
            any(prop.optional for prop in graph.properties.values()) or
            any(prop.optional for cls in graph.classes.values()
                for prop in cls.properties.values()) or
            any(prop.optional for embed in graph.embeds.values()
                for prop in embed.properties.values()))
    # yapf: enable

    if has_optional:
        if cpp.optional_as == "boost::optional":
            third_party_block.add("#include <boost/optional.hpp>")
        elif cpp.optional_as == "std::optional":
            stl_block.add("#include <optional>")
        elif cpp.optional_as == "std::experimental::optional":
            third_party_block.add("#include <optional.hpp>")
        else:
            raise NotImplementedError(
                "Unhandled cpp.optional_as: {!r}".format(cpp.optional_as))

    block_strs = []  # type: List[str]

    if len(third_party_block) > 0:
        block_strs.append('\n'.join(sorted(third_party_block)))

    if len(stl_block) > 0:
        block_strs.append('\n'.join(sorted(stl_block)))

    return '\n\n'.join(block_strs)
Esempio n. 13
0
    def test_map_needs_type(self) -> None:
        a_map = mapry.Map(values=mapry.Path())

        self.assertTrue(mapry.needs_type(a_type=a_map, query=mapry.Path))
        self.assertFalse(mapry.needs_type(a_type=a_map, query=mapry.Date))
Esempio n. 14
0
    def test_array_needs_type(self) -> None:
        array = mapry.Array(values=mapry.Path(), minimum_size=None)

        self.assertTrue(mapry.needs_type(a_type=array, query=mapry.Path))
        self.assertFalse(mapry.needs_type(a_type=array, query=mapry.Date))
Esempio n. 15
0
def _includes(
        graph: mapry.Graph, cpp: mapry.Cpp, types_header_path: str,
        parse_header_path: str) -> str:
    """
    Generate the include directives of the header file.

    :param graph: definition of the object graph
    :param cpp: C++ settings
    :param types_header_path:
        path to the header file that defines the types of the object graph
    :param parse_header_path:
        path to the header file that defines the general parsing structures
    :return: generated code
    """
    # pylint: disable=too-many-branches
    stl_block = set()  # type: Set[str]

    third_party_block = {"#include <json/json.h>  // jsoncpp"}

    # yapf: disable
    first_party_block = {
        '#include "{}"'.format(pth)
        for pth in [types_header_path, parse_header_path]}
    # yapf: enable

    if mapry.needs_type(a_type=graph, query=mapry.String):
        stl_block.add("#include <string>")

    if mapry.needs_type(a_type=graph, query=mapry.Path):
        if cpp.path_as == 'std::filesystem::path':
            stl_block.add("#include <filesystem>")
        elif cpp.path_as == "boost::filesystem::path":
            third_party_block.add("#include <boost/filesystem/path.hpp>")
        else:
            raise NotImplementedError(
                "Unhandled schema.cpp.path_as: {!r}".format(cpp.path_as))

    if graph.classes:
        stl_block.add("#include <map>")
        stl_block.add("#include <string>")

    # Check for optional fields
    has_optional = False
    for prop in graph.properties.values():
        if prop.optional:
            has_optional = True
            break

    if not has_optional:
        for cls in graph.classes.values():
            for prop in cls.properties.values():
                if prop.optional:
                    has_optional = True
                    break

    if not has_optional:
        for embed in graph.embeds.values():
            for prop in embed.properties.values():
                if prop.optional:
                    has_optional = True
                    break

    if has_optional:
        if cpp.optional_as == "boost::optional":
            third_party_block.add("#include <boost/optional.hpp>")
        elif cpp.optional_as == "std::optional":
            stl_block.add("#include <optional>")
        elif cpp.optional_as == "std::experimental::optional":
            third_party_block.add("#include <optional.hpp>")
        else:
            raise NotImplementedError(
                "Unhandled schema.cpp.optional_as: {!r}".format(
                    cpp.optional_as))

    block_strs = [
        '\n'.join(sorted(third_party_block)), '\n'.join(sorted(stl_block)),
        '\n'.join(sorted(first_party_block))
    ]

    assert all(block_str == block_str.strip() for block_str in block_strs), \
        "No empty blocks in include blocks."

    return '\n\n'.join(block_strs)