Skip to content

Doctools

Provides tools to assist with generating documentation for SSVC decision points.

Writes the following files for each decision point: - a json example that can be used in the decision point documentation

Examples

To generate the documentation for the decision points, use the following command:

python -m ssvc.doctools --overwrite --jsondir ./tmp/json_out`

To regenerate the existing docs, use the following command:

python -m ssvc.doctools --overwrite --jsondir data/json/decision_points

EnsureDirExists

A runtime context that ensures that a directory exists or creates it otherwise.

Example:

with EnsureDirExists(dir):
    assert os.path.exists(dir)
Source code in src/ssvc/doctools.py
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
class EnsureDirExists:
    """
    A runtime context that ensures that a directory exists or creates it otherwise.

    Example:

        with EnsureDirExists(dir):
            assert os.path.exists(dir)
    """

    def __init__(self, dir: str):
        """
        Create a new EnsureDirExists context.

        Args:
            dir (str): The directory to ensure exists.

        Returns:
            EnsureDirExists: The new EnsureDirExists context.
        """
        self.dir = dir

    def __enter__(self):
        os.makedirs(self.dir, exist_ok=True)

    def __exit__(self, exc_type, exc_val, exc_tb):
        pass

__init__(dir)

Create a new EnsureDirExists context.

Parameters:

Name Type Description Default
dir str

The directory to ensure exists.

required

Returns:

Name Type Description
EnsureDirExists

The new EnsureDirExists context.

Source code in src/ssvc/doctools.py
68
69
70
71
72
73
74
75
76
77
78
def __init__(self, dir: str):
    """
    Create a new EnsureDirExists context.

    Args:
        dir (str): The directory to ensure exists.

    Returns:
        EnsureDirExists: The new EnsureDirExists context.
    """
    self.dir = dir

_filename_friendly(name)

Given a string, return a version that is friendly for use in a filename.

Parameters:

Name Type Description Default
name str

The string to make friendly for use in a filename.

required

Returns:

Name Type Description
str str

A version of the string that is friendly for use in a filename.

Source code in src/ssvc/doctools.py
44
45
46
47
48
49
50
51
52
53
54
def _filename_friendly(name: str) -> str:
    """
    Given a string, return a version that is friendly for use in a filename.

    Args:
        name (str): The string to make friendly for use in a filename.

    Returns:
        str: A version of the string that is friendly for use in a filename.
    """
    return name.lower().replace(" ", "_").replace(".", "_")

dump_decision_point(jsondir, dp, overwrite)

Generate the markdown table, json example, and markdown table file for a decision point.

Parameters:

Name Type Description Default
jsondir str

The directory to write the json example to.

required
outdir str

The directory to write the markdown table file to.

required
dp SsvcDecisionPoint

The decision point to generate documentation for.

required
overwrite bool

Whether to overwrite existing files.

required

Returns:

Name Type Description
dict None

A dictionary with the following keys: - include_file: The path to the markdown table file. - symlink: The path to the symlink that points to the markdown table file. - json_file: The path to the json example file.

Source code in src/ssvc/doctools.py
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
def dump_decision_point(jsondir: str, dp: SsvcDecisionPoint, overwrite: bool
) -> None:
    """
    Generate the markdown table, json example, and markdown table file for a decision point.

    Args:
        jsondir (str): The directory to write the json example to.
        outdir (str): The directory to write the markdown table file to.
        dp (SsvcDecisionPoint): The decision point to generate documentation for.
        overwrite (bool): Whether to overwrite existing files.

    Returns:
        dict: A dictionary with the following keys:
            - include_file: The path to the markdown table file.
            - symlink: The path to the symlink that points to the markdown table file.
            - json_file: The path to the json example file.
    """
    # make dp.name safe for use in a filename
    basename = _filename_friendly(dp.name) + f"_{_filename_friendly(dp.version)}"
    # - generate json example
    dump_json(basename, dp, jsondir, overwrite)

dump_json(basename, dp, jsondir, overwrite)

Generate the json example for a decision point.

Parameters:

Name Type Description Default
basename str

The basename of the json example file.

required
dp SsvcDecisionPoint

The decision point to generate documentation for.

required
jsondir str

The directory to write the json example to.

required
overwrite bool

Whether to overwrite existing files.

required

Returns:

Name Type Description
str str

The path to the json example file.

Source code in src/ssvc/doctools.py
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
def dump_json(
    basename: str, dp: SsvcDecisionPoint, jsondir: str, overwrite: bool
) -> str:
    """
    Generate the json example for a decision point.

    Args:
        basename (str): The basename of the json example file.
        dp (SsvcDecisionPoint): The decision point to generate documentation for.
        jsondir (str): The directory to write the json example to.
        overwrite (bool): Whether to overwrite existing files.

    Returns:
        str: The path to the json example file.
    """
    # if namespace is ssvc, it goes in jsondir
    filename = f"{basename}.json"
    parts = [
        jsondir,
    ]
    if dp.namespace != "ssvc":
        parts.append(_filename_friendly(dp.namespace))
    parts.append(filename)

    json_file = os.path.join(*parts)

    if overwrite:
        remove_if_exists(json_file)
    with EnsureDirExists(jsondir):
        try:
            with open(json_file, "x") as f:
                f.write(dp.model_dump_json(indent=2))
                f.write("\n")  # newline at end of file
        except FileExistsError:
            logger.warning(
                f"File {json_file} already exists, use --overwrite to replace"
            )
    return json_file