Exemple #1
0
    def test_derived_from_rules(self):
        """Should filter a set of version ids to only those with a dependency
        on changes derived from a rule"""
        with self.cli.isolated_filesystem():
            tree_dir = entry.Tree('12', '1000')

            deps = dependency.Graph()
            deps.add(tree_dir / 111, entry.Annual(12, 1000, 2001))
            deps.add(tree_dir / 222, entry.RuleChanges(222))
            deps.add(tree_dir / 333, entry.RuleChanges(333))
            deps.add(tree_dir / 333, entry.Version(333))
            derived = fill_with_rules.derived_from_rules(
                ['111', '222', '333', '444'], deps, tree_dir)
            self.assertEqual(derived, ['222', '333'])
def process(tree_path, previous, version_id):
    """Build and write a tree by combining the preceding tree with changes
    present in the associated rule"""
    prev_tree = (tree_path / previous).read()
    notice = entry.RuleChanges(version_id).read()
    changes = merge_changes(version_id, notice.get('changes', {}))
    new_tree = compile_regulation(prev_tree, changes)
    (tree_path / version_id).write(new_tree)
def derived_from_rules(version_ids, deps, tree_path):
    """We only want to process trees which are created by parsing rules. To do
    that, we'll filter by those trees which have a dependency on a parsed
    rule"""
    rule_versions = []
    for version_id in version_ids:
        path = str(tree_path / version_id)
        rule_change = str(entry.RuleChanges(version_id))
        if rule_change in deps.dependencies(path):
            rule_versions.append(version_id)
    return rule_versions
def dependencies(tree_path, version_ids, cfr_title, cfr_part):
    """Set up the dependency graph for this regulation. First calculates
    "gaps" -- versions for which there is no existing tree. In this
    calculation, we ignore the first version, as we won't be able to build
    anything for it. Add dependencies for any gaps, tying the output tree to
    the preceding tree, the version info and the parsed rule"""
    existing_ids = set(tree_path)
    gaps = [(prev, curr) for prev, curr in zip(version_ids, version_ids[1:])
            if curr not in existing_ids]

    deps = dependency.Graph()
    for prev, curr in gaps:
        deps.add(tree_path / curr, tree_path / prev)
        deps.add(tree_path / curr, entry.RuleChanges(curr))
        deps.add(tree_path / curr, entry.Version(cfr_title, cfr_part, curr))
    return deps
Exemple #5
0
def parse_rule_changes(document_number):
    """Parse changes present in a single rule.

    DOCUMENT_NUMBER is the identifier associated with a final rule. If a rule
    has been split, use the split identifiers, a.k.a. version ids."""
    rule_entry = entry.RuleChanges(document_number)
    notice_entry = entry.Notice(document_number)

    deps = dependency.Graph()
    deps.add(rule_entry, notice_entry)

    deps.validate_for(rule_entry)
    # We don't check for staleness as we want to always execute when given a
    # specific file to process

    notice_xml = notice_entry.read()
    notice = process_amendments({'cfr_parts': notice_xml.cfr_parts},
                                notice_xml.xml)
    rule_entry.write(notice)
Exemple #6
0
    def test_dependencies(self):
        """Expect nonexistent trees to depend on their predecessor, associated
        rule changes and version files. Shouldn't add dependencies for the
        first version, if missing"""
        with self.cli.isolated_filesystem():
            version_ids = ['111', '222', '333', '444', '555', '666']
            tree_dir = entry.Tree('12', '1000')
            rule_dir = entry.RuleChanges()
            vers_dir = entry.Version('12', '1000')
            # Existing trees
            (tree_dir / '222').write(Node())
            (tree_dir / '555').write(Node())

            deps = fill_with_rules.dependencies(tree_dir, version_ids, '12',
                                                '1000')

            # First is skipped, as we can't build it from a rule
            self.assertNotIn(str(tree_dir / '111'), deps)
            # Second can also be skipped as a tree already exists
            self.assertEqual(deps.dependencies(str(tree_dir / '222')), [])
            # Third relies on the associated versions and the second tree
            self.assertItemsEqual(deps.dependencies(str(tree_dir / '333')), [
                str(tree_dir / '222'),
                str(rule_dir / '333'),
                str(vers_dir / '333')
            ])
            # Fourth relies on the third, even though it's not been built
            self.assertItemsEqual(deps.dependencies(str(tree_dir / '444')), [
                str(tree_dir / '333'),
                str(rule_dir / '444'),
                str(vers_dir / '444')
            ])
            # Fifth can be skipped as the tree already exists
            self.assertEqual(deps.dependencies(str(tree_dir / '555')), [])
            # Six relies on the fifth
            self.assertItemsEqual(deps.dependencies(str(tree_dir / '666')), [
                str(tree_dir / '555'),
                str(rule_dir / '666'),
                str(vers_dir / '666')
            ])