Skip to content

cli

Module that contains the command line application.

discarded_stdout() ¤

Discard standard output.

Yields:

Name Type Description
Nothing None

We only yield to act as a context manager.

Source code in src/pytkdocs/cli.py
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
@contextmanager
def discarded_stdout() -> Iterator[None]:
    """Discard standard output.

    Yields:
        Nothing: We only yield to act as a context manager.
    """
    # Discard things printed at import time to avoid corrupting our JSON output
    # See https://github.com/pawamoy/pytkdocs/issues/24
    old_stdout = sys.stdout
    sys.stdout = StringIO()

    yield

    # Flush imported modules' output, and restore true sys.stdout
    sys.stdout.flush()
    sys.stdout = old_stdout

extract_docstring_parsing_errors(errors, obj) ¤

Recursion helper.

Update the errors dictionary by side-effect. Recurse on the object's children.

Parameters:

Name Type Description Default
errors dict

The dictionary to update.

required
obj Object

The object.

required
Source code in src/pytkdocs/cli.py
131
132
133
134
135
136
137
138
139
140
141
142
143
def extract_docstring_parsing_errors(errors: dict, obj: Object) -> None:
    """Recursion helper.

    Update the `errors` dictionary by side-effect. Recurse on the object's children.

    Arguments:
        errors: The dictionary to update.
        obj: The object.
    """
    if hasattr(obj, "docstring_errors") and obj.docstring_errors:
        errors[obj.path] = obj.docstring_errors
    for child in obj.children:
        extract_docstring_parsing_errors(errors, child)

extract_errors(obj) ¤

Extract the docstring parsing errors of each object, recursively, into a flat dictionary.

Parameters:

Name Type Description Default
obj Object

An object from pytkdocs.objects.

required

Returns:

Type Description
dict

A flat dictionary. Keys are the objects' names.

Source code in src/pytkdocs/cli.py
146
147
148
149
150
151
152
153
154
155
156
157
def extract_errors(obj: Object) -> dict:
    """Extract the docstring parsing errors of each object, recursively, into a flat dictionary.

    Arguments:
        obj: An object from `pytkdocs.objects`.

    Returns:
        A flat dictionary. Keys are the objects' names.
    """
    parsing_errors: dict[str, list[str]] = {}
    extract_docstring_parsing_errors(parsing_errors, obj)
    return parsing_errors

get_parser() ¤

Return the program argument parser.

Returns:

Type Description
ArgumentParser

The argument parser for the program.

Source code in src/pytkdocs/cli.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
def get_parser() -> argparse.ArgumentParser:
    """Return the program argument parser.

    Returns:
        The argument parser for the program.
    """
    parser = argparse.ArgumentParser(prog="pytkdocs")
    parser.add_argument(
        "-1",
        "--line-by-line",
        action="store_true",
        dest="line_by_line",
        help="Process each line read on stdin, one by one.",
    )
    parser.add_argument("-V", "--version", action="version", version=f"%(prog)s {debug.get_version()}")
    parser.add_argument("--debug-info", action=_DebugInfo, help="Print debug information.")
    return parser

main(args=None) ¤

Run the main program.

This function is executed when you type pytkdocs or python -m pytkdocs.

Parameters:

Name Type Description Default
args list[str] | None

Arguments passed from the command line.

None

Returns:

Type Description
int

An exit code.

Source code in src/pytkdocs/cli.py
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
def main(args: list[str] | None = None) -> int:
    """Run the main program.

    This function is executed when you type `pytkdocs` or `python -m pytkdocs`.

    Parameters:
        args: Arguments passed from the command line.

    Returns:
        An exit code.
    """
    parser = get_parser()
    parsed_args: argparse.Namespace = parser.parse_args(args)

    if parsed_args.line_by_line:
        for line in sys.stdin:
            with discarded_stdout():
                try:
                    output = json.dumps(process_json(line))
                except Exception as error:  # noqa: BLE001
                    # Don't fail on error. We must handle the next inputs.
                    # Instead, print error as JSON.
                    output = json.dumps({"error": str(error), "traceback": traceback.format_exc()})
            print(output)
    else:
        with discarded_stdout():
            output = json.dumps(process_json(sys.stdin.read()))
        print(output)

    return 0

process_config(config) ¤

Process a loading configuration.

The config argument is a dictionary looking like this:

{
    "objects": [
        {"path": "python.dotted.path.to.the.object1"},
        {"path": "python.dotted.path.to.the.object2"},
    ]
}

The result is a dictionary looking like this:

{
    "loading_errors": [
        "message1",
        "message2",
    ],
    "parsing_errors": {
        "path.to.object1": [
            "message1",
            "message2",
        ],
        "path.to.object2": [
            "message1",
            "message2",
        ],
    },
    "objects": [
        {
            "path": "path.to.object1",
            # other attributes, see the documentation for `pytkdocs.objects` or `pytkdocs.serializer`
        },
        {
            "path": "path.to.object2",
            # other attributes, see the documentation for `pytkdocs.objects` or `pytkdocs.serializer`
        },
    ],
}

Parameters:

Name Type Description Default
config dict

The configuration.

required

Returns:

Type Description
dict

The collected documentation along with the errors that occurred.

Source code in src/pytkdocs/cli.py
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 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
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
def process_config(config: dict) -> dict:
    """Process a loading configuration.

    The `config` argument is a dictionary looking like this:

    ```python
    {
        "objects": [
            {"path": "python.dotted.path.to.the.object1"},
            {"path": "python.dotted.path.to.the.object2"},
        ]
    }
    ```

    The result is a dictionary looking like this:

    ```python
    {
        "loading_errors": [
            "message1",
            "message2",
        ],
        "parsing_errors": {
            "path.to.object1": [
                "message1",
                "message2",
            ],
            "path.to.object2": [
                "message1",
                "message2",
            ],
        },
        "objects": [
            {
                "path": "path.to.object1",
                # other attributes, see the documentation for `pytkdocs.objects` or `pytkdocs.serializer`
            },
            {
                "path": "path.to.object2",
                # other attributes, see the documentation for `pytkdocs.objects` or `pytkdocs.serializer`
            },
        ],
    }
    ```

    Arguments:
        config: The configuration.

    Returns:
        The collected documentation along with the errors that occurred.
    """
    collected = []
    loading_errors = []
    parsing_errors = {}

    for obj_config in config["objects"]:
        path = obj_config.pop("path")
        members = obj_config.pop("members", set())

        if isinstance(members, list):
            members = set(members)
        loader = Loader(**obj_config)

        obj = loader.get_object_documentation(path, members)

        loading_errors.extend(loader.errors)
        parsing_errors.update(extract_errors(obj))

        serialized_obj = serialize_object(obj)
        collected.append(serialized_obj)

    return {"loading_errors": loading_errors, "parsing_errors": parsing_errors, "objects": collected}

process_json(json_input) ¤

Process JSON input.

Simply load the JSON as a Python dictionary, then pass it to process_config.

Parameters:

Name Type Description Default
json_input str

The JSON to load.

required

Returns:

Type Description
dict

The result of the call to process_config.

Source code in src/pytkdocs/cli.py
117
118
119
120
121
122
123
124
125
126
127
128
def process_json(json_input: str) -> dict:
    """Process JSON input.

    Simply load the JSON as a Python dictionary, then pass it to [`process_config`][pytkdocs.cli.process_config].

    Arguments:
        json_input: The JSON to load.

    Returns:
        The result of the call to [`process_config`][pytkdocs.cli.process_config].
    """
    return process_config(json.loads(json_input))