Python script delivery workflow

Documentation

README file

Inline documentation

  • Use Google docstrings format.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    """Module for Google style docstrings example.

    This module demonstrates documentation as specified by the `Google Python
    Style Guide`_. Docstrings may extend over multiple lines. Sections are created
    with a section header and a colon followed by a block of indented text.

    Example:
    Examples can be given using either the ``Example`` or ``Examples``
    sections. Sections support any reStructuredText formatting, including
    literal blocks::

    $ python example_google.py

    Section breaks are created by resuming unindented text. Section breaks
    are also implicitly created anytime a new section starts.

    Attributes:
    module_level_variable1 (int): Module level variables may be documented in
    either the ``Attributes`` section of the module docstring, or in an
    inline docstring immediately following the variable.

    Either form is acceptable, but the two should not be mixed. Choose
    one convention to document module level variables and be consistent
    with it.

    Todo:
    * For module TODOs
    """
    module_level_variable1 = 12345
    module_level_variable2 = 98765

    def function_with_types_in_docstring(param1, param2):
    """Example function with types documented in the docstring.

    `PEP 484`_ type annotations are supported. If attribute, parameter, and
    return types are annotated according to `PEP 484`_, they do not need to be
    included in the docstring:

    Args:
    param1 (int): The first parameter.
    param2 (str): The second parameter.

    Returns:
    bool: The return value. True for success, False otherwise.

    .. _PEP 484:
    https://www.python.org/dev/peps/pep-0484/
    """
    return param1 == param2

Generate code doc

  • Install pdoc3.
    1
    python -m pip install pdoc3
  • Run pdoc.
    1
    python -m pdoc --html --output-dir .doc src_file.py

Convert to docx

  • Install Pandoc.

  • Header with metadata on *.md: it must be in YML format:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    ---
    title: "Main Title"
    subtitle: "Sub Title"
    author: [Angeles Broullón]
    date: "2020-10-13"
    keywords: [Markdown]
    ...

    <!-- \newpage -->
  • Convert the document

    1
    2
    3
    4
    5
    # no template
    pandoc README.md -o output-readme.docx
    # with template, you must generate one first
    pandoc -o custom-reference.docx --print-default-data-file reference.docx
    pandoc -t docx README.md --reference-doc=template.docx -o output-template.docx

    You may check other templates in Pandoc Latex Template

  • Hack for been able to add newpage breaks

    • You will need a lua script (pagebreak.lua) into the pandoc folder, so you can use <!-- \newpage --> in your document to split into pages without further issues.
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      --- Return a block element causing a page break in the given format.
      local function newpage(format)
      if format == 'docx' then
      local pagebreak = '<w:p><w:r><w:br w:type="page"/></w:r></w:p>'
      return pandoc.RawBlock('openxml', pagebreak)
      elseif format:match 'html.*' then
      return pandoc.RawBlock('html', '<div style=""></div>')
      elseif format:match 'tex$' then
      return pandoc.RawBlock('tex', '\\newpage{}')
      elseif format:match 'epub' then
      local pagebreak = '<p style="page-break-after: always;"> </p>'
      return pandoc.RawBlock('html', pagebreak)
      else
      -- fall back to insert a form feed character
      return pandoc.Para{pandoc.Str '\f'}
      end
      end

      -- Filter function called on each RawBlock element.
      function RawBlock (el)
      -- check that the block is TeX or LaTeX and contains only \newpage or
      -- \pagebreak.
      if el.text:match '\\newpage' then
      -- use format-specific pagebreak marker. FORMAT is set by pandoc to
      -- the targeted output format.
      return newpage(FORMAT)
      end
      -- otherwise, leave the block unchanged
      return nil
      end
    • Call pandoc with extra parameter
      1
      2
      3
      pandoc -t docx README.md --reference-doc=custom-reference.docx \
      -o output-template.docx --highlight-style=breezedark \
      --lua-filter=pagebreak.lua

Minify code

  • Install pyminifer.
    1
    python -m pip install pyminifer
  • Reduce the size, remove documentation
    1
    pyminifier -o "dist/min.py" "MY_FILE.py"

General script

  • You may generate a bash file for this matter
    1
    2
    3
    4
    python -m pdoc --html --output-dir .doc src_file.py
    pandoc -t docx README.md --reference-doc=custom-reference.docx \
    -o output-template.docx --highlight-style=breezedark
    python -m pyminifier -o "dist/min.py" "MY_FILE.py"

Extra: .docx to .md

  • You may reverse the operation, extrating all the images.
    1
    pandoc -o "output.md" --extractMedia="/." "inputFile.md"