示例#1
0
    def test_mass_inference(self):
        """generate many more paths and infer them right away"""
        stree = StringFormatNodeTree.new('root', self.path_rule_data)
        itree = InferenceStringFormatNodeTree.new('root', self.path_rule_data)

        # the delegate only has information about the root path and the project name,
        # everything else will be inferred
        delegate = InferenceStringFormatNodeTreeDelegate([self.base_data().clone()])

        # MASS TEST
        ###########
        # In this test we only have two substitutions, the projects root and the code. All other formats
        # are just names, which should be resolved as well.
        # Make sure we can substitute as many paths as possible, thus we add some more information
        count = 0
        data = self.complete_data()

        assert 'asset' not in delegate.parsed_data(), "precondition failed"
        # we need this predicate, as we may have ambiguity in the tree (at least with our limited dataset)
        predicate = InferenceStringFormatNodeTree.leaf_nodes_only
        for nlist in stree.iterate_formatted_nodes(data):
            count += 1
            matches = list(itree.iterate_matches(nlist.to_string(), delegate=delegate, predicate=predicate))
            assert len(matches) == 1, "should have exactly one full match from a previously generated path"
        # end for each nodelist
        assert count, "should have processed quite some paths"

        # quick diff - there should be no differences (which are not overcome by converting from one type to another)
        validator = KeyValueStoreSchemaValidator()
        for key, value in data.items():
            ValidatedKeyValueStoreSchema(key, value, validator=validator)
        # end for each key, value
        assert type(delegate.parsed_data()['resource']['version']) is int
        assert len(validator) and len(validator.validate_provider(KeyValueStoreProvider(delegate.parsed_data()))) == 0
示例#2
0
    def test_inference(self):
        """test basic functionality"""
        stree = StringFormatNodeTree.new('root', self.path_rule_data)
        data = self.base_data()

        root_path = stree.root_node().apply_format(data).format_result
        # start simple, just back-substitute the root
        itree = InferenceStringFormatNodeTree.new('root', self.path_rule_data)

        # NO DATASET, ORIGINAL PATH
        ############################
        # without a data-delgate, we shouldn't be able to find the correct root, but should get a match
        # anyway as we substitute root/project, which is similar to /mnt/projects
        delegate = InferenceStringFormatNodeTreeDelegate()
        matches = list(itree.iterate_matches(root_path, delegate=delegate))
        assert len(matches) == 0, "Should have exactly no match"

        # NO DATASET, TRUNCATED PATH
        ############################
        # if we don't have the leading slash (which is somewhat special to the system), we have matches
        # as it will match the first two nodes as individual parts of the path
        assert root_path.startswith(StringFormatNode.default_child_separator)
        truncated_root_path = root_path[len(StringFormatNode.default_child_separator):]

        matches = list(itree.iterate_matches(truncated_root_path, delegate=delegate))
        assert len(matches) == 1
        assert len(matches[0]) == 2, "should have found root and project node"

        # obviously, these values are wrong, but its expected in this case as we didn't provide substitution data
        tokens = self.fs_root.split('/')
        assert len(tokens) == 3  # first index is empty string
        pdata = delegate.parsed_data()['project']
        assert pdata['root_path']['fs_absolute'] == tokens[1]
        assert pdata['code'] == tokens[2]

        # additionally, add some made-up piece that will result in a partial match only
        appendix = StringFormatNode.default_child_separator + data.project.code
        truncated_root_path += appendix
        matches = list(itree.iterate_matches(truncated_root_path, delegate=delegate))
        assert len(matches) == 0, "shouldn't have a full match anymore"
        partial_matches = list(itree.iterate_partial_matches(truncated_root_path, delegate=delegate))

        assert len(partial_matches) == 1, "Should have one partial match"
        assert partial_matches[0][0] == data.project.code, "The unconsumed portion was unexpected"

        # SINGLE DATASET, ORIGINAL PATH
        ###############################
        # try resolution with a single dataset
        delegate = InferenceStringFormatNodeTreeDelegate([data])
        # make sure we can also handle the project (yes, we should get this path from the stree iterator, but
        # this path is quite stable in our case, so I take the risk)
        root_path = root_path + appendix
        matches = list(itree.iterate_matches(root_path, delegate=delegate))

        assert len(matches) == 1, "Should have exactly one list"
        assert len(matches[0]) == 2, "Should have found two nodes"

        pdata = delegate.parsed_data()
        assert len(pdata) == 1, "expected just the 'project' key, found %i keys" % len(pdata)
        pdata = pdata['project']
        assert len(pdata) == 2, "expected the root path and project code only"
        assert len(pdata['root_path']) == 1, "expected fs_root' only"
        assert pdata['root_path']['fs_absolute'] == self.fs_root
        assert pdata['code'] == data.project.code

        # predicate and prune
        assert len(list(itree.iterate_matches(root_path, delegate=delegate, predicate=lambda nlist: False))) == 0
        # we get the root only
        assert len(list(itree.iterate_matches(root_path, delegate=delegate, prune=lambda nlist: False))) == 1
示例#3
0
    def test_extension(self):
        """Show how to extend the system
        @todo set the version and have an easy way to reformat the node list with the changes"""
        # [name-handling-extension]
        class DynamicNode(StringFormatNode):

            """A node dynamically returning types based on the data type"""

            def _child_type(self, child_key, data):
                """Extract the child's type and return the actual type to use for the child"""
                if isinstance(data, dict):
                    meta = data.get(self.attr_metadata)
                    if meta:
                        types = meta.get(self.attr_type, dict())
                        if 'Version' in types:
                            return VersionNode
                        # end handle version
                    # end have meta data
                # end have a dict input
                return super(DynamicNode, self)._child_type(child_key, data)
        # end class DynamicNode

        class VersionNode(DynamicNode):

            """A version node """
            _schema_ = (('version', 0),)

            def _obtain_meta_data_for(self, key):
                """@return meta data either from the parsed source, or from meta data"""
                if key in self.format_data():
                    return self.format_data()
                return super(VersionNode, self)._obtain_meta_data_for(key)

            # -------------------------
            # @name Interface
            # @{

            def set_version(self, version):
                """Set our version to the given value
                @note this is just the type-checked variant of self.version, which is supported due to our
                ValidatedElementNode heritage"""
                if not isinstance(version, int):
                    raise ValueError("invalid value type")
                self.version = version
            # -- End Interface -- @}
        # end class VersionNode

        stree = StringFormatNodeTree.new('root', self.rule_data('simple_version.yaml'), element_node_type=DynamicNode)
        assert isinstance(stree.root_node(), StringFormatNode)
        is_version_node = lambda node: type(node) is VersionNode
        count = 0
        stree.root_node().children()
        version = 15
        data = dict(version=version)
        # substitute the simple version data in
        iterator = stree.iterate_formatted_nodes(data, predicate=lambda nlist: nlist.find_first_if(is_version_node))
        for node_list in iterator:
            count += 1
            version_node = node_list.find_first_if(is_version_node)

            assert version_node.version == version
            version_string = version_node.format_result

            # Currently we have to do it manually
            version_data = version_node.format_data()
            version_data['version'] = version + 1

            assert version_string != version_node.apply_format(DictObject(version_data)).format_result
        # end for each node-list
        assert count