module documentation

**Dycco** is another Python port of [Docco][docco], the quick-and-dirty, hundred-line-long, literate-programming-style documentation generator. This particular version has been updated to work with Python 3 (as of 2026). This version allows output to a markdown file or to an asciidoc3 file, as well as adding a option to sanitize internal HTML (which is handy if your code includes html fragments). Dycco reads Python source files and produces annotated source documentation in HTML format. Comments and docstrings are formatted with [Markdown][markdown] or with [AsciiDoc3][asciidoc3] and presented as annotations alongside the source code, which is syntax-highlighted by [Pygments][pygments]. This page is the result of running Dycco against its [own source file][dycco]. Dycco differs from Nick Fitzgerald's [Pycco][pycco] ([new version][newpycco]), the first Python port of [Docco][docco], in that it only knows how to generate documenation on Python source code and it uses that specialization to more accurately parse documentation. It does so using a two-pass parsing stage, first walking the *Abstract Syntax Tree* of the code to gather up docstrings, then examining the code line-by-line to extract comments. Dycco's HTML and CSS are taken straight from [Docco][docco], but, like Pycco, Dycco uses [Mustache][mustache] templates rendered by [Pystache][pystache]. The first version of Dycco's templates and CSS were taken straight from [Pycco][pycco], then updated to match the latest changes to [Docco][docco]'s. [docco]: https://ashkenas.com/docco/ [markdown]: https://daringfireball.net/projects/markdown/ [pygments]: https://pygments.org/ [dycco]: https://github.com/mccutchen/dycco [pycco]: https://github.com/pycco-docs/pycco [mustache]: https://github.com/peterldowns/python-mustache [pystache]: https://github.com/defunkt/pystache [asciidoc3]: https://asciidoc3.org/ [newpycco]: https://github.com/rojalator/pycco

Class DocStringVisitor A `NodeVisitor` subclass that walks an Abstract Syntax Tree (AST) and gathers up and notes the positions of any docstrings it finds.
Function document Generates documentation for the Python files at the given `input_paths` by parsing each file into pairs of documentation and source code and rendering those pairs into an HTML file.
Function make_output_path Creates an appropriate output path for the given source file and output directory. The output file name will be the name of the source file without its original extension but with `html`, `md` or `adoc` as a new one.
Function make_sections Creates the special `sections` datastructure used to hold parsed documentation and code.
Function parse Parse the given source code in two passes. The first pass walks the *Abstract Syntax Tree* of the code, gathering up and noting the location of any docstrings. The second pass processes the code line by line, grouping the code into sections based on docstrings and comments.
Function parse_code Parse the given `src` line by line to gather source code and comments into the appropriate places in `sections`. Any line numbers in `skip_lines` are skipped. **Note:** Modifies `sections` in place.
Function parse_docstrings Parse the given `src` to find any docstrings, add them to the appropriate place in `sections`, and return a `set` of line numbers where the docstrings are. **Note:** Modifies `sections` in place.
Function preprocess_code Preprocess the given code, which should be a `list` of strings, by joining them together and running them through the Pygments syntax highlighter unless `raw` is True, when we just return the text
Function preprocess_docs Preprocess the given `docs`, which should be a `list` of strings, by joining them together and running them through Markdown or asciidoc3, unless `raw` is True, in which case we just return the text
Function render Renders the given sections, which should be the result of calling `parse` on a source code file, into HTML.
Function should_filter Test the given line to see if it should be included. Excludes shebang lines, for now.
Constant COMMENT_PATTERN Undocumented
Constant DYCCO_CSS Undocumented
Constant DYCCO_RESOURCES Undocumented
Constant DYCCO_ROOT Undocumented
Constant DYCCO_TEMPLATE Undocumented
Variable ascii_location Undocumented
Variable ascii_module Undocumented
def document(input_paths, output_dir, use_ascii: bool = False, escape_html: bool = False, single_file: bool = False):

Generates documentation for the Python files at the given `input_paths` by parsing each file into pairs of documentation and source code and rendering those pairs into an HTML file. The `input_paths` param can be a `list` of paths or a single `str` path. Usually, markdown() is called, but if `use_ascii` is true, we'll use asciidoc3 (`__main__.py` looks for the `-a / --asciidoc3` flag for this). By default, it's set to False to retain the old behaviour of just using markdown. If escape_html is True, we use Python's `html.escape()` to prevent any embedded html in the comments from disrupting the output. Again, it's False by default to maintain the old behaviour. `single_file` means that we just want to produce a file with either `.md` or `.adoc` extension, in single-column format, with code blocks demarcated using markdown or asciidoc3 indicators. This is handy if, for example, you haven't got the Python asciidoc3 but have got asciidoctor available: you can pass it the file for processing.

def make_output_path(filename, output_dir, extension: str = 'html') -> str:

Creates an appropriate output path for the given source file and output directory. The output file name will be the name of the source file without its original extension but with `html`, `md` or `adoc` as a new one.

def make_sections() -> defaultdict:

Creates the special `sections` datastructure used to hold parsed documentation and code.

def parse(src: str) -> defaultdict:

Parse the given source code in two passes. The first pass walks the *Abstract Syntax Tree* of the code, gathering up and noting the location of any docstrings. The second pass processes the code line by line, grouping the code into sections based on docstrings and comments. The data structure returned is a special `dict` whose keys are the line numbers where sections start, which map to `dict`s containing the docs and code associated with those sections. The docs and code are stored as lists, which will be joined in post processing by `render()`. It will look a little like this: { 1: {docs: [..., ...], code: [..., ...] }, 9: {docs: [..., ...], code: [..., ...] } } The docs for each section can come from docstrings (the first pass) or from comments (the second pass). The line numbers start at zero, for simplicity's sake.

def parse_code(src: str, sections: defaultdict, skip_lines: set):

Parse the given `src` line by line to gather source code and comments into the appropriate places in `sections`. Any line numbers in `skip_lines` are skipped. **Note:** Modifies `sections` in place.

def parse_docstrings(src: str, sections: defaultdict) -> set:

Parse the given `src` to find any docstrings, add them to the appropriate place in `sections`, and return a `set` of line numbers where the docstrings are. **Note:** Modifies `sections` in place.

def preprocess_code(code: list, use_ascii: bool = False, raw: bool = False, language_name: str = 'python') -> str:

Preprocess the given code, which should be a `list` of strings, by joining them together and running them through the Pygments syntax highlighter unless `raw` is True, when we just return the text Although we are strictly python, it's possible that this might get called by other routines as it's quite handy, so allow the language to be specified in `language_name`. Behaviour if `language_name` is blank is undefined (for asciidoc3).

def preprocess_docs(docs: list, use_ascii: bool, escape_html: bool, raw: bool = False) -> str:

Preprocess the given `docs`, which should be a `list` of strings, by joining them together and running them through Markdown or asciidoc3, unless `raw` is True, in which case we just return the text

def render(title: str, sections: defaultdict, use_ascii: bool = False, escape_html: bool = False, single_file: bool = False) -> str:

Renders the given sections, which should be the result of calling `parse` on a source code file, into HTML. If `single_file` is True, we don't actually run things through Pygments, Markdown or Asciidoc3, but just output a single file with a suitable extension

def should_filter(line: str, num: int) -> bool:

Test the given line to see if it should be included. Excludes shebang lines, for now.

COMMENT_PATTERN: str =

Undocumented

Value
'^\\s*#'
DYCCO_CSS =

Undocumented

Value
os.path.join(DYCCO_RESOURCES, 'dycco.css')
DYCCO_RESOURCES =

Undocumented

Value
os.path.join(DYCCO_ROOT, 'resources')
DYCCO_ROOT =

Undocumented

Value
os.path.dirname(__file__)
DYCCO_TEMPLATE =

Undocumented

Value
os.path.join(DYCCO_RESOURCES, 'template.html')
ascii_location =

Undocumented

ascii_module =

Undocumented