Skip to content

Commit

Permalink
Merge pull request #210 from michaelnt/strict_children
Browse files Browse the repository at this point in the history
Warn if an item doesn't have a link from every child document
  • Loading branch information
jacebrowning committed Dec 13, 2016
2 parents 3f6ebb6 + 69503d2 commit 52773d2
Show file tree
Hide file tree
Showing 6 changed files with 31 additions and 2 deletions.
2 changes: 2 additions & 0 deletions doorstop/cli/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ def main(args=None): # pylint: disable=R0915
help="do not validate external file references")
parser.add_argument('-C', '--no-child-check', action='store_true',
help="do not validate child (reverse) links")
parser.add_argument('-Z', '--strict-child-check', action='store_true',
help="require child (reverse) links from every document")
parser.add_argument('-S', '--no-suspect-check', action='store_true',
help="do not check for suspect links")
parser.add_argument('-W', '--no-review-check', action='store_true',
Expand Down
2 changes: 2 additions & 0 deletions doorstop/cli/utilities.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ def configure_settings(args):
settings.CHECK_REF = args.no_ref_check is False
if args.no_child_check is not None:
settings.CHECK_CHILD_LINKS = args.no_child_check is False
if args.strict_child_check is not None:
settings.CHECK_CHILD_LINKS_STRICT = args.strict_child_check is True
if args.no_suspect_check is not None:
settings.CHECK_SUSPECT_LINKS = args.no_suspect_check is False
if args.no_review_check is not None:
Expand Down
1 change: 1 addition & 0 deletions doorstop/core/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ def __init__(self, path, root=os.getcwd(), **kwargs):
self._data['parent'] = None # the root document does not have a parent
self._items = []
self._itered = False
self.children = []

def __repr__(self):
return "Document('{}')".format(self.path)
Expand Down
15 changes: 13 additions & 2 deletions doorstop/core/item.py
Original file line number Diff line number Diff line change
Expand Up @@ -560,7 +560,8 @@ def get_issues(self, skip=None, **kwargs):

# Check links against both document and tree
if self.document and self.tree:
yield from self._get_issues_both(self.document, self.tree, skip)
yield from self._get_issues_both(self.document, self.tree,
skip)

# Check review status
if not self.reviewed:
Expand Down Expand Up @@ -662,9 +663,11 @@ def _get_issues_both(self, document, tree, skip):

# Verify an item is being linked to (child links)
if settings.CHECK_CHILD_LINKS and self.normative:
find_all = settings.CHECK_CHILD_LINKS_STRICT or False
items, documents = self._find_child_objects(document=document,
tree=tree,
find_all=False)
find_all=find_all)

if not items:
for document in documents:
if document.prefix in skip:
Expand All @@ -673,6 +676,14 @@ def _get_issues_both(self, document, tree, skip):
continue
msg = "no links from child document: {}".format(document)
yield DoorstopWarning(msg)
elif settings.CHECK_CHILD_LINKS_STRICT:
prefix = [item.prefix for item in items]
for child in document.children:
if child in skip:
continue
if child not in prefix:
msg = 'no links from document: {}'.format(child)
yield DoorstopWarning(msg)

@requires_tree
def find_ref(self):
Expand Down
12 changes: 12 additions & 0 deletions doorstop/core/tree.py
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,9 @@ def _place(self, document):
log.info("parent options: {}".format(prefixes))
raise DoorstopError(msg)

for document in self:
children = self._get_prefix_of_children(document)
document.children = children
# attributes #############################################################

@property
Expand Down Expand Up @@ -477,6 +480,15 @@ def by_uid(row):
# Sort rows
return sorted(rows, key=by_uid)

def _get_prefix_of_children(self, document):
"""Return the prefixes of the children of this document."""
for child in self.children:
if child.document == document:
children = [c.document.prefix for c in child.children]
return children
children = [c.document.prefix for c in self.children]
return children

def _iter_rows(self, item, mapping, parent=True, child=True, row=None): # pylint: disable=R0913
"""Generate all traceability row slices.
Expand Down
1 change: 1 addition & 0 deletions doorstop/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
CHECK_LEVELS = True # validate document levels during validation
CHECK_REF = True # validate external file references
CHECK_CHILD_LINKS = True # validate reverse links
CHECK_CHILD_LINKS_STRICT = False # require child (reverse) links from every document
CHECK_SUSPECT_LINKS = True # check stamps on links
CHECK_REVIEW_STATUS = True # check stamps on items
WARN_ALL = False # display info-level issues as warnings
Expand Down

0 comments on commit 52773d2

Please sign in to comment.