[MarryDoc] Usage¶
Inherit DocString¶
The inherit()
decorator copies a docstring from a specified object
and attaches it to the function or method it decorates. In the following
example, standard library b2a_hex()
function serves as
the docstring source:
import binascii
import marrydoc
@marrydoc.inherit(binascii.b2a_hex)
def b2a_hex(data, sep=''):
mashed = binascii.b2a_hex(data)
return sep.join(mashed[i:i+2] for i in range(0, len(mashed), 2))
hexlify = b2a_hex
The inherit()
decorator guarentees that the docstrings are always
synchronized and does not require maintenance of the module when the original
docstring changes:
>>> import binascii
>>> import inherit_example
>>>
>>> print binascii.hexlify.__doc__
b2a_hex(data) -> s; Hexadecimal representation of binary data.
This function is also available as "hexlify()".
>>>
>>> print inherit_example.hexlify.__doc__
b2a_hex(data) -> s; Hexadecimal representation of binary data.
This function is also available as "hexlify()".
>>>
>>> binascii.hexlify.__doc__ == inherit_example.hexlify.__doc__
True
Maintain DocString Copies¶
The shortcoming of the inherit()
decorator is that the copied docstring
does not appear in the module and makes module maintenance more difficult.
The copied_from()
decorator defines a one to one relationship between
the source of the docstring and the docstring of the function it decorates:
import binascii import marrydoc @marrydoc.copied_from(binascii.b2a_hex) def b2a_hex(data, sep=''): """b2a_hex(data) -> s; Hexadecimal representation of binary data. This function is also available as "hexlify()".""" mashed = binascii.b2a_hex(data) return sep.join(mashed[i:i+2] for i in range(0, len(mashed), 2)) hexlify = b2a_hex
The defined relationship allows the Command Line Tool to check the module’s docstring:
$ python -m marrydoc copied_from_example.py
copied_from_example.py ... OK
If the docstring source changed, the command line tool updates the
docstring in the module when specifying the --merge
option:
$ python -m marrydoc --merge copied_from_example.py
copied_from_example.py ... UPDATED
Note
During normal import of a module, the copied_from()
decorator
acts as a passthrough and introduces very little overhead.
Maintain DocString With Modifications¶
The based_on()
decorator defines a relationship between the docstring
of the function it decorates and the basis from which it was derived.
The same as copied_from()
and inherit()
, the first argument
to based_on()
is the program construct containing the docstring that
is to be tracked. based_on()
requires a second argument that is a copy
of the source docstring (the source docstring is compared against the copy
and if they are unequal, the two values in combination with the actual
docstring facilitate a three way merge). For example:
import binascii import marrydoc @marrydoc.based_on( binascii.b2a_hex, """b2a_hex(data) -> s; Hexadecimal representation of binary data. This function is also available as "hexlify()".""") def b2a_hex(data, sep=''): """b2a_hex(data) -> s; Hexadecimal representation of binary data. b2a_hex(data, sep) -> s; Separated hexadecimal representation of binary data. This function is also available as "hexlify()".""" mashed = binascii.hexlify(data) return sep.join(mashed[i:i+2] for i in range(0, len(mashed), 2)) hexlify = b2a_hex
The defined relationship to the source in combination with the docstring copy provided as the second argument allow the Command Line Tool to check if the source docstring has changed:
$ python -m marrydoc based_on_example.py
based_on_example.py ... OK
If the source docstring has changed, the Command Line Tool updates
the module’s docstrings by performing a three way merge when specifying
the --merge
option:
$ python -m marrydoc --merge based_on_example.py
based_on_example.py ... UPDATED
Note
The three way merge requires a merge tool of your choosing. Without
configuring, the three way merge attempts usage of kdiff3
. See
the next section for more information on configuring your favorite
merge tool to be used.
During normal import of a module, the based_on()
decorator
acts as a passthrough and introduces very little overhead.
Configure Your Favorite Merge Tool¶
For three way merges, the marrydoc
command line tool uses kdiff3
when
it is installed and in your system path. Otherwise marrydoc
generates
“base”, “left”, and “right” files on your file system for you to merge manually.
To automatically invoke your favorite three way merge tool instead, set the
MARRYDOC_MERGE
environment variable and specify the command line invocation
using Python’s string format substitution syntax.
For example, on Linux:
export MARRYDOC_MERGE="kdiff3 --merge --auto {base} {left} {right} --output {orig}"
Or on Microsoft Windows:
set MARRYDOC_MERGE="kdiff3 --merge --auto {base} {left} {right} --output {orig}"
Warning
The executable name/path must not contain spaces. The current implementation
of marrydoc
splits the string on whitespace and passes the result to a
subprocess command.
Test DocStrings In A Module Collection¶
The main()
function exposes the command line interface
and offers a convenient method to check if the docstrings in a module
are up to date. Add a test case within the module’s regression test to
call the command line interface and to check the returned exit code for
success indication (0).
The --walk
option is useful for checking an entire package hierarchy,
for example:
import os import unittest import marrydoc import mypackage class TestDocStrings(unittest.TestCase): def test_package(self): package_path = os.path.dirname(mypackage.__file__) exitcode = marrydoc.main(['--walk', package_path]) self.assertEqual(exitcode, 0)
Tips and Tricks¶
based_on()
,copied_from()
may also be used to decorate a class to wed its docstring to another. (inherit()
cannot be used to decorate a class because the class docstring is not settable by the time the docorator executes.)The
based_on()
,copied_from()
, andinherit()
decorators may also be used in combination with the@classmethod()
orstaticmethod()
decorators. Themarrydoc
decorator implementations accomodate decorating in either order. For better readability, place the@classmethod()
andstaticmethod()
decorators first (on the outside).When decorating a method using
based_on()
,copied_from()
, orinherit()
, a class may be passed as the first argument to specify the source of the docstring. The docstring of the method by the same name in the specified class then acts as the docstring basis.Ensure your operating system path includes the
Scripts
subdirectory that is part of the normal Python installation. After installation, amarrydoc
“shim” executable exists that subdirectory to invoke the command line tool directly:$ marrydoc --help
The
marrydoc
command line also accepts importable module and package names. Use this form when the module is in the Python system path. This form may be used in combination with the--walk
option to check an entire package, for example:$ marrydoc baseline --walk /usr/local/lib/python3.5/dist-packages/baseline/__about__.py ... OK /usr/local/lib/python3.5/dist-packages/baseline/__init__.py ... OK /usr/local/lib/python3.5/dist-packages/baseline/__main__.py ... OK /usr/local/lib/python3.5/dist-packages/baseline/_baseline.py ... OK /usr/local/lib/python3.5/dist-packages/baseline/_script.py ... OK