A new Python documentation style
See how to use a Python object at a glance!
These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.
You will need Python 3 to use this module
# vermin output
Minimum required versions: 3.8
Incompatible versions: 2
pip install --upgrade miko
pip install --upgrade git+https://github.com/Animenosekai/miko
You can check if you successfully installed it by printing out its version:
$ miko --version
# output:
2.0
$ python -c "import miko; print(miko.__version__)"
# output:
2.0
This new style aims at bringing an ease of use for both humans and computers.
It also helps me get concise while writing docstrings as I tend to use different styles even within a same file.
Miko defines a new way of documenting your source code.
You will here learn the different sections of your documentation string.
The Miko way of documenting stuff is by using Markdown in your docstrings and following the rules below.
When documenting a callable, you need to start the docstring right after the callable definition.
Example 1: Documenting a callable
def test(a: int, b: int, /, c: int = 4, d=5, e: int = 6, *args, f: str, **kwargs) -> int:
"""
Documenting a function
Parameters
----------
a: int, deprecated
Hey
Returns
-------
int
"""
def inner():
"""
Documenting an inner function
Note: This is a cool function
"""
class Test:
"""Documenting a class"""
def __init__(self) -> None:
"""Documenting a method"""
Example 2: Documenting a variable or constant
When documenting any other variable, you need to add a string right after the variable definition.
CONSTANT = 1
'Documenting a constant'
b: int
"""! DEPRECATED"""
Keep in mind that you need to keep the indentation level of the docstring the same as the definition.
def func():
"""
It needs to start here
Here we continue the documentation string
^^^^
(do not use this space)
"""
pass
After starting the documentation string, you can add a description for your object as a normal string.
There is not much styling or rules to follow since all the content outside any section is considered part of the description.
Example: We are giving a description of the function at the start, but also at the end.
def func():
"""
Hello, this is a description.
Returns
-------
bool
The result of the function.
But this is also part of the description.
"""
There are 3 types of docstring sections to be aware of:
Note
Sometimes also called Block Sections
These are sections which contains a list of named elements :
def func():
"""
Paragraph
---------
element1: options1, options2
element1 description
element2: options1, options2
element2 description
"""
Each element has its name, followed by its options and a description.
Here are the built-in sections you can use:
You can define what are the different parameters/arguments the callable object is taking.
To start explaining the different parameters, you need to use the Parameters
section name, followed by a line-break and at least 3 hyphens.
The parameters can be inferred from a callable signature if provided.
Example
def func(a, b: int, c = ""):
"""
Parameters
----------
a: bool
this is the first argument
b: int | float, default = 1.2
this is the second argument
c: str, optional
this is the third argument
it can have multiple lines
"""
Aliases:
Parameters
,Parameter
,Params
,Parm
,Arguments
,Argument
,Args
,Arg
You can specify options for each parameter.
The options are separated from the parameter name using a colon and a space.
Each option is separated by a comma.
<type>
— Defines the type of the parameter.optional
— Defines a parameter as being optional, without needing to specify its default value. (useful with keyword arguments for instance)default
— Defines a parameter as being optional, by giving it a default value.deprecated
— When a parameter is deprecated.
Types
Types can be defined by giving the element class name or dot notation path.
Example:
str
,translatepy.language.Language
You can specify multiple types using the vertical bar separator.
Example:
int | float
Default
You can define a default value using an equal sign.
Example:
default = 1
,default=True
You can define what are the values returned by a callable object using the Returns
section.
Each returning element is explained with the following rules: the type of the value and a description with a left-padding on a new line.
The return value can be inferred from a callable signature if provided.
Example
def func():
"""
Returns
-------
int
the number returned
str
if it is a string returned
list[int, str]
if it's a list of both
translatepy.Language
using dot notation
"""
Aliases:
Returns
,Return
,Returning
You can inform the users about any exception/error your callable might be raising using the Raising
section.
Like the Returns
section, you need to give the name of the exception and then a description of why it would raise this exception and the special attribute the exception might have on a new line, left-padded.
Example
def func():
"""
Raises
------
ValueError
If there is an error with the value
"""
Aliases:
Raises
,Raise
,Raising
,Exceptions
,Exception
,Errors
,Error
You can inform the users about how the object got modified over time using the Changelog
section.
Like the Returns
section, you need to give the name of the version it got changed on and then a description of how it changed on a new line, left-padded.
Example
def func():
"""
Changelog
---------
2.0
Became deprecated, use `new_func` instead
1.4
New default string
0.6
Raises ImportError instead of RuntimeError
"""
Aliases:
Changelog
,Changes
You can add copyright/authors of the code using the Copyright
section.
Like the Returns
section, you need to give the name of the author and then a description of what they did on a new line, left-padded. The description could include stuff like the year they worked on the code, what they did, etc.
Each element in the options here is the license used to distribute the code.
Example
def func():
"""
Copyright
---------
Animenosekai: MIT License, from = 2021, to = 2023
The initial author
Some other dev: year = 2023
A very cool collaborator
"""
You can specify options for each author.
Each option is separated by a comma.
<license>
— Defines the license for the code.year
— The year the author worked on the code.from
— The year the author started working on the code.to
— The year the author stopped working on the code.
Aliases:
Copyrights
,Copyright
,Authors
,Author
Inline sections can be used inline when there is no need to have more than a line to describe the section.
If it requires multiple lines, you can use a syntax similar to the map parser one, and start the section with at least 3 hyphens and add the lines.
def func():
"""
This is a function
Inline: This is an inline section
Inline
------
This is a multi line inline section
Wow I can write multiple lines here
"""
Here are the built-in inline sections you can use:
It is recommended that you give examples on how to use your object.
You can use the Example
tag to give an example of how to use your object.
def func(a: typing.Union[bool, typing.Any] = False):
"""
Example
-------
>>> func()
"That's wrong"
>>> func(True)
"That's right"
# when using something other than a boolean
>>> func(1)
1 # gives it right back
Example: Another example
Note: This function wouldn't really make sense
"""
Aliases:
Examples
,Example
If you want to notify the user about something, you can use the Note
tag.
Example
def func():
"""
Note: Yup, that's right
...description...
Note: Another note
Note
----
Wow this is a
really long note
"""
Aliases:
Notes
,Note
,See Also
,Information
You can give warnings to the user using the Warning
tag.
Example
def func():
"""
Warning: This is a serious warning
...description...
Warning: Another warning
"""
Aliases:
Warnings
,Warning
You can give important notes to the user using the Important
tag.
Example
def func():
"""
Important: Remember to close the fridge before leaving
"""
Aliases:
Important
,Important Notice
A flag is what describes a boolean value in a docstring
If the flag is present, it will be set to True, otherwise it will be set to False
def func():
"""
This is a function
! FLAG
! YOU'RE COOL
(description)
"""
Note
You can customize the prefix used to recognize a flag using the flag_prefix
parameter when creating the Documentation
object.
Here are the built-in flag sections you can use:
To add a deprecation notice to your object, you can add ! DEPRECATED
in the docstring.
Example: At the very beginning of the docstring
def func():
"""! DEPRECATED
This is a cool function.
Changelog
---------
1.5
Added a deprecation notice, with the intention of the function being removed on the next major version.
"""
Example: With a slight variation
def func():
"""
!DEPRECATED
This is a cool function.
"""
Aliases:
Deprecated
,Deprecation
,Deprecate
,Deprecation Notice
Here are the two main classes exposed by the Python API:
This object is the core implementation of the docstring parser.
Example
from miko import Documentation
parsed = Documentation(
"""
Hello
Note: This is a test
Changelog
---------
1.0
Adding this docstring
"""
)
- The
original
attribute contains the original docstring. - The
description
attribute contains the description of the object.
All the other attributes are the different sections of the docstring.
- The
exported
property renders a dictionary with the different elements of the docstring.
You can also easily extend and customize the docstring parser by subclassing the different elements :
from miko import Documentation, parsers
class MyCoolParser(parsers.map.MapParser):
names = ["New Section", "New Sections"]
class MyCoolDocumentation(Documentation):
new_section: MyCoolParser
parsed = MyCoolDocumentation(
"""
New Section
-----------
This is a new section
"""
)
# You can now use `parsed.new_section`
BaseDocumentation.dumps
The dumps
method, which might look familiar to common serialization libraries, lets you dump the documentation string to the cleanest format possible, using all the information the current Documentation
has.
The optional indent
parameter (which defaults to 4), lets you choose the indentation level of the output.
It returns a string with the output documentation string.
This object gathers information on the given callable and its docstring.
It automatically passes its inspect.Signature
for the parsers to have a better understanding of the object.
It also exposes several attributes and methods to get information on the callable.
This module provides different tools to statically analyze Python code and get information on it.
This module provides different tools to render Markdown documentations out of different elements.
Note
Miko uses GitHub Flavored Markdown (GFM) to render markdown.
Head over to the API Reference to learn more about the different classes and functions exposed by the Python API.
Note
The API reference has been generated using miko
itself.
Miko
also has a CLI, which you can use to get information about a docstring or clean a docstring.
🧃❯ miko --help
usage: miko [-h] [--version] {info,clean,docs,overview} ...
See how to use a Python object at a glance!
positional arguments:
{info,clean,docs,overview}
Actions
info Gathers information on the different elements in the input
clean Cleans the given input
docs Generate the documentation for the files loaded by the entry file
overview Provides documentation for the given module
options:
-h, --help show this help message and exit
--version, -v show program's version number and exit
Both info
and clean
have the same arguments :
usage: miko <action> [-h] [--indent INDENT] [--noself] [--flag-prefix FLAG_PREFIX] [--safe] [--output OUTPUT] [--raw] input
positional arguments:
input The snippet of code or file to get the docstrings from.
options:
-h, --help show this help message and exit
--indent INDENT, -i INDENT
The indentation level for the result
--noself Ignoring the "self" parameter from signatures. (useful for class methods)
--flag-prefix FLAG_PREFIX
The prefix for the docstring flags. (default: "!")
--safe If the annotations and exceptions should be loaded safely (without loading the modules) (default: False)
--output OUTPUT, -o OUTPUT
The file to output the result to. If not provided, `miko` will use STDOUT.
--raw If the input should be treated as a docstring and not source code. (default: False)
The miko info
command provides information on the different elements in the input.
It statically analyzes the source code, gathers information on all elements (classes, functions, modules, variables, etc.), parses their docstrings and outputs a JSON encoded output with all the information.
Note
The info
command also has the --minify
flag which lets you minify the output JSON.
If the --raw
flag is provided, the input will be treated as only being the docstring and not source code, thus only parsing it as a docstring.
Warning
Beware that the output structure is different using --raw
.
The miko clean
command cleans the given input.
It cleans the different docstrings, formats the code using autopep8
and sorts the imports using isort
.
If the --raw
flag is provided, the input will be treated as only being the docstring and not source code, thus only cleaning it.
docs
lets you generate markdown documentation for the given entry file.
It will recursively look for all files imported and generate the documentation for them.
usage: miko docs [-h] [--output OUTPUT] [--ignore [IGNORE ...]] [--include-private] [--safe] entry
positional arguments:
entry The entry file to document. An entry file could be for example the __init__.py of a library.
options:
-h, --help show this help message and exit
--output OUTPUT, -o OUTPUT
The directory to output the result to. If not provided, `miko` will use "./docs"
--ignore [IGNORE ...]
The files to ignore when generating the documentation
--include-private If the private objects should be included in the documentation
--safe If the annotations and exceptions should be loaded safely (without loading the modules) (default: False)
Overview is similar to docs
but only produces Markdown documentation for a single file.
usage: miko overview [-h] [--output OUTPUT] [--include-private] [--safe] module
positional arguments:
module The module to provide documentation for
options:
-h, --help show this help message and exit
--output OUTPUT, -o OUTPUT
The file to output the result to. If not provided, `miko` will use STDOUT
--include-private If the private objects should be included in the documentation
--safe If the annotations and exceptions should be loaded safely (without loading the modules) (default: False)
You can also use the Miko
extension for Visual Studio Code.
It lets you format your files instantly using the command palette.
You can configure the arguments passed to miko
in the VS Code settings (UI or JSON).
Go to https://marketplace.visualstudio.com/items?itemName=Animenosekai.miko-docs to download the published version from the marketplace.
You can also use the .vsix
file to install the extension.
Head to the extension folder and download the .vsix
file.
Then, go to the Extensions' section in VS Code, click on the three dots and select Install from VSIX...
.
This module is currently in development and might contain bugs.
Feel free to use it in production if you feel like it is suitable for your production even if you may encounter issues.
Pull requests are welcome. For major changes, please open a discussion first to discuss what you would like to change.
Please make sure to update the tests as appropriate.
- Anime no Sekai — Initial work — Animenosekai
This project is licensed under the MIT License — see the LICENSE file for details.