Scripting Interface

Being written in Python, Doorstop allows you to leverage the full power of Python to write scripts to manipulate requirements, run custom queries across all documents, and even inject your own validation rules.


For ad hoc introspection, let Doorstop build your tree of documents in your preferred Python REPL or notebook session:

>>> import doorstop
>>> tree =
>>> tree
<Tree REQ <- [ TUT <- [ HLT ], LLT ]>
>>> len(tree.documents)
>>> document = tree.find_document('REQ')
>>> document
>>> sum(1 for item in document if

Generic Scripting

For reusable workflows, create a Python script that acts on your tree of documents:

#!/usr/bin/env python

import doorstop

tree =
document = tree.find_document('REQ')
count = sum(1 for item in document if

print(f"{count} active items in {document}")

Validation Hooks

To extend the default set of validations that can be performed, Doorstop provides a "hook" mechanism to simplify scripts that need to operate on multiple documents or items.

For this use case, create a script to call in place of the default command-line interface:

#!/usr/bin/env python

import sys
from doorstop import build, DoorstopInfo, DoorstopWarning, DoorstopError

def main():
    tree = build()
    success = tree.validate(document_hook=check_document, item_hook=check_item)
    sys.exit(0 if success else 1)

def check_document(document):
    if sum(1 for i in document if i.normative) < 10:
        yield DoorstopInfo("fewer than 10 normative items")

def check_item(item):
    if not item.get('type'):
        yield DoorstopWarning("no type specified")
    if item.derived and not item.get('rationale'):
        yield DoorstopError("derived but no rationale")

if __name__ == '__main__':

Both document_hook and item_hook are optional, but if provided these callbacks will be passed each corresponding instance. Each callback should yield instances of Doorstop's exception classes based on severity of the issue.