Skip to content

cli

Module that contains the command line application.

discarded_stdout() ¤

Discard standard output.

Yields:

Type Description
Nothing

We only yield to act as a context manager.

Source code in pytkdocs/cli.py
@contextmanager
def discarded_stdout():
    """
    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 pytkdocs/cli.py
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:  # noqa: WPS421 (hasattr)
        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 pytkdocs/cli.py
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 pytkdocs/cli.py
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.",
    )
    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 Optional[List[str]]

Arguments passed from the command line.

None

Returns:

Type Description
int

An exit code.

Source code in pytkdocs/cli.py
def main(args: Optional[List[str]] = None) -> int:
    """
    Run the main program.

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

    Arguments:
        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: W0703 (we purposely catch everything)
                    # 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)  # noqa: WPS421 (we need to print at some point)
    else:
        with discarded_stdout():
            output = json.dumps(process_json(sys.stdin.read()))
        print(output)  # noqa: WPS421 (we need to print at some point)

    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 pytkdocs/cli.py
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 pytkdocs/cli.py
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))
Back to top