tutagx / tutagx / model / split.py

"""
Does not define any models, but provides a mixin to split model data into
multiple files for serialization.
"""
import os
import logging
from tutagx.meta.collect_types import reachable_types
from tutagx.meta.collect_objects import collect_instances
from tutagx.meta import to_yaml, from_yaml, validate

log = logging.getLogger(__name__)


class DataSplitting:
    """
    Mixin providing loading/saving at given paths, splitting the data into
    multiple files based on object types.
    Requires a call to DataSpliting.prepare(inheriting_cls) before any
    loading (ideally, right after the class definition).
    """

    @staticmethod
    def prepare(cls):
        cls.__reachable = reachable_types(cls)

    @classmethod
    def load_from_path(my_cls, dirpath, namespace=None):
        log.debug('Loading %s from %r', my_cls.__name__, dirpath)
        reader = from_yaml.YAMLReader()
        v = reader.validator
        for cls in my_cls.__reachable:
            if cls.is_value_type:
                continue
            path = os.path.join(dirpath, cls.__name__ + '.yaml')
            log.debug('File for %r objects: %r', cls, path)
            with open(path) as f:
                result, errors = reader.load_many(cls, f)
            if cls is my_cls and not v.context.errors:
                assert len(result) == 1
                return_val = result[0]
        validate.add_errors_for_undefined(v.context)
        if v.context.errors:
            return None, v.context.errors
        # Avoid errors; see tutagx.toolutil.load_with_namespace
        validate.add_errors_for_unreachable(
                my_cls, v.context, return_val, errors
        )
        return return_val, v.context.errors

    def save_to_path(self, dirpath):
        log.debug('Saving %s in %r', type(self).__name__, dirpath)
        collected = collect_instances(self)
        writer = to_yaml.YAMLWriter()
        for cls in type(self).__reachable:
            objs = collected[cls]
            if cls.is_value_type:
                continue
            path = os.path.join(dirpath, cls.__name__ + '.yaml')
            log.debug('File for %r objects: %r', cls, path)
            with open(path, 'w') as f:
                writer.dump_many(objs, f)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.