Example #1
0
def generate_model(root_class=ROOT_CLASS):
    """
    Generate a data-structure that represents the current configuration
    model.

    Changes to output may require regenerating the persisted version
    on-disk.

    This should switch to Pyrsistent's introspection API once it exists:
    https://github.com/tobgu/pyrsistent/issues/47
    """
    classes_result = {}
    result = {u"root": fqpn(root_class),
              u"classes": classes_result}
    classes = {root_class}
    while classes:
        klass = classes.pop()
        klass_name = fqpn(klass)
        if klass_name in classes_result:
            continue
        if issubclass(klass, (PRecord, PClass)):
            to_model = _precord_model
        elif issubclass(klass, CheckedPMap):
            to_model = _pmap_model
        elif issubclass(klass, (CheckedPSet, CheckedPVector)):
            to_model = _psequence_model
        else:
            to_model = lambda klass: (None, set())
        record, further_classes = to_model(klass)
        classes_result[klass_name] = record
        classes |= further_classes
    return result
Example #2
0
def generate_model(root_class=ROOT_CLASS):
    """
    Generate a data-structure that represents the current configuration
    model.

    Changes to output may require regenerating the persisted version
    on-disk.

    This should switch to Pyrsistent's introspection API once it exists:
    https://github.com/tobgu/pyrsistent/issues/47
    """
    classes_result = {}
    result = {u"root": fqpn(root_class), u"classes": classes_result}
    classes = {root_class}
    while classes:
        klass = classes.pop()
        klass_name = fqpn(klass)
        if klass_name in classes_result:
            continue
        if issubclass(klass, (PRecord, PClass)):
            to_model = _precord_model
        elif issubclass(klass, CheckedPMap):
            to_model = _pmap_model
        elif issubclass(klass, (CheckedPSet, CheckedPVector)):
            to_model = _psequence_model
        else:
            to_model = lambda klass: (None, set())
        record, further_classes = to_model(klass)
        classes_result[klass_name] = record
        classes |= further_classes
    return result
Example #3
0
def _pmap_model(klass):
    """
    Serialize a ``PMap`` model to something JSON-encodable.

    :param klass: A ``PMap`` subclass.
    :return: Tuple of (model dictionary, further classes to process).
    """
    record = {
        u"category": u"map",
        u"fields": {
            u"key": sorted(
                fqpn(cls) for cls in klass._checked_key_types),
            u"value": sorted(
                fqpn(cls) for cls in klass._checked_value_types)}}
    further_classes = set()
    for cls in klass._checked_key_types + klass._checked_value_types:
        further_classes.add(cls)
    return record, further_classes
Example #4
0
def _pmap_model(klass):
    """
    Serialize a ``PMap`` model to something JSON-encodable.

    :param klass: A ``PMap`` subclass.
    :return: Tuple of (model dictionary, further classes to process).
    """
    record = {
        u"category": u"map",
        u"fields": {
            u"key": sorted(fqpn(cls) for cls in klass._checked_key_types),
            u"value": sorted(fqpn(cls) for cls in klass._checked_value_types)
        }
    }
    further_classes = set()
    for cls in klass._checked_key_types + klass._checked_value_types:
        further_classes.add(cls)
    return record, further_classes
Example #5
0
    def assert_catches_changes(self, original_class, changed_class):
        """
        Assert that ``generate_model`` changes its output when the underlying
        class has changed.

        :param original_class: Class in initial state.
        :param changed_class: Class in changed state.
        """
        original_model = generate_model(original_class)
        changed_model = generate_model(changed_class)
        # Make sure result is JSON serializable:
        dumps(original_model)
        dumps(changed_model)
        self.assertEqual(
            # If not the calling test is buggy, since it's catching wrong
            # thing, a mere name change:
            (fqpn(original_class) == fqpn(changed_class),
             # Changes result in a difference:
             original_model != changed_model,
             # No changes result in same output:
             original_model == generate_model(original_class),
             changed_model == generate_model(changed_class)),
            (True, True, True, True))
Example #6
0
    def assert_catches_changes(self, original_class, changed_class):
        """
        Assert that ``generate_model`` changes its output when the underlying
        class has changed.

        :param original_class: Class in initial state.
        :param changed_class: Class in changed state.
        """
        original_model = generate_model(original_class)
        changed_model = generate_model(changed_class)
        # Make sure result is JSON serializable:
        dumps(original_model)
        dumps(changed_model)
        self.assertEqual(
            # If not the calling test is buggy, since it's catching wrong
            # thing, a mere name change:
            (fqpn(original_class) == fqpn(changed_class),
             # Changes result in a difference:
             original_model != changed_model,
             # No changes result in same output:
             original_model == generate_model(original_class),
             changed_model == generate_model(changed_class)),
            (True, True, True, True))
Example #7
0
def _psequence_model(klass):
    """
    Serialize a ``PVector`` or ``PSet`` model to something
    JSON-encodable.

    :param klass: A ``PVector`` or ``PSet`` subclass.
    :return: Tuple of (model dictionary, further classes to process).
    """
    category = u"set" if issubclass(klass, CheckedPSet) else u"list"
    record = {
        u"category": category,
        u"type": sorted(fqpn(cls) for cls in klass._checked_types),
    }
    further_classes = set(klass._checked_types)
    return record, further_classes
Example #8
0
def _psequence_model(klass):
    """
    Serialize a ``PVector`` or ``PSet`` model to something
    JSON-encodable.

    :param klass: A ``PVector`` or ``PSet`` subclass.
    :return: Tuple of (model dictionary, further classes to process).
    """
    category = u"set" if issubclass(klass, CheckedPSet) else u"list"
    record = {
        u"category": category,
        u"type": sorted(fqpn(cls) for cls in klass._checked_types),
    }
    further_classes = set(klass._checked_types)
    return record, further_classes
Example #9
0
def _precord_model(klass):
    """
    Serialize a ``PRecord`` or ``PClass`` model to something
    JSON-encodable.

    :param klass: A ``PRecord`` or ``PClass`` subclass.
    :return: Tuple of (model dictionary, further classes to process).
    """
    further_classes = set()
    if issubclass(klass, PRecord):
        attr_name = "_precord_fields"
    else:
        attr_name = "_pclass_fields"
    record = {u"category": u"record", u"fields": {}}
    for name, field_info in getattr(klass, attr_name).items():
        record[u"fields"][name] = sorted(fqpn(cls) for cls in field_info.type)
        for cls in field_info.type:
            further_classes.add(cls)
    return record, further_classes
Example #10
0
def _precord_model(klass):
    """
    Serialize a ``PRecord`` or ``PClass`` model to something
    JSON-encodable.

    :param klass: A ``PRecord`` or ``PClass`` subclass.
    :return: Tuple of (model dictionary, further classes to process).
    """
    further_classes = set()
    if issubclass(klass, PRecord):
        attr_name = "_precord_fields"
    else:
        attr_name = "_pclass_fields"
    record = {u"category": u"record",
              u"fields": {}}
    for name, field_info in getattr(klass, attr_name).items():
        record[u"fields"][name] = sorted(
            fqpn(cls) for cls in field_info.type)
        for cls in field_info.type:
            further_classes.add(cls)
    return record, further_classes