Package: doxxie
doxxiedoxxieis amypyplugin that outputs the true public
API of a mypy-typed Python library.doxxie's output can be checked into
source control andverified with a CI jobto ensure changes to the public API
are intentional and documented.doxxieburrows into the public API of a library and recursively digs out any
types exposed by public attributes and functions until the true public API is
reached.installationInstall from PyPI:$pipinstalldoxxieusageAdddoxxieto the plugins section of yourmypy config
file:[mypy]files=mylib/plugins=doxxieThen run mypy with an environment variable specifying which modules to
include:$DOXXIE_INCLUDES=mylibmypy--no-incrementalA file.public_apiwill be output with the public API ofmylib.Note:The--no-incrementalflag is necessary asdoxxiecannot get
access to mypy's cached typing information.outputdoxxieoutputs a.public_apifile which contains a listing of all the
public variables of the modules specified.exampleSee docs/example for the code shown belowConsider the following Python librarylib:lib/
├── __init__.py
├── api/
│   └── __init__.py
└── _internal/
    └── __init__.py# api/__init__.pyfromlib._internalimportLeakedPrivate,PrivateclassPublic:def__init__(self):self.public_attr:int=5self.public_leak:LeakedPrivate=LeakedPrivate()self._private:Private=Private()defpublic_method(self)->None:passdef_private_method(self)->str:return"hi"# _internal/__init__.pyclassLeakedPrivate:defpublic_method(self)->None:passclassPrivate:passRunningDOXXIE_INCLUDES=pkg.api DOXXIE_EXCLUDES=pkg._internal mypywill
output the following to.public_api:{'lib.Private':{'bases':['builtins.object'],'mro':['lib.Private','builtins.object']},'lib.Private.public_method':{'arg_kinds':[0],'arg_names':['self'],'type':{'arg_types':['lib.Private'],'ret_type':{'.class':'NoneType'}}},'lib._internal.LeakedPrivate':{'bases':['builtins.object'],'mro':['lib._internal.LeakedPrivate','builtins.object']},'lib._internal.LeakedPrivate.public_method':{'arg_kinds':[0],'arg_names':['self'],'type':{'arg_types':['lib._internal.LeakedPrivate'],'ret_type':{'.class':'NoneType'}}},'lib.api.Public':{'bases':['builtins.object'],'mro':['lib.api.Public','builtins.object']},'lib.api.Public.__init__':{'arg_kinds':[0],'arg_names':['self'],'type':{}},'lib.api.Public.public_attr':{'type':'builtins.int'},'lib.api.Public.public_leak':{'type':'lib._internal.LeakedPrivate'},'lib.api.Public.public_method':{'arg_kinds':[0],'arg_names':['self'],'type':{'arg_types':['lib.api.Public'],'ret_type':{'.class':'NoneType'}}}}configurationAll configuration is done via environment variables.DOXXIE_INCLUDES: comma-separated list of modules to include in the public
API. Only items found under the modules provided will be included in the
public API output.example:"mod1,mod2"default:""(nothing will be included by default)DOXXIE_EXCLUDES: comma-separated list of modules to exclude from the public
API. These modules will be ignored initially but items from these modules may
be exposed by the public API and included in the output.example:"mod1.internal,mod1.vendor"default:""DOXXIE_OUTFILE: file to output the resultsexample:"my_public_api"default:".public_api"DOXXIE_DERIVE_OUTFILE: file to output derivation results for each item
included in the public API. This output can be used to show what chain of
attributes led to an item being exposed.example:"public_api_derivation"default: disabledDOXXIE_DEBUG: enable debug loggingexample:"1"default: disabledci jobdoxxiecan be used to help avoid accidental changes to the public API of a
library. To do this, check the.public_apifile generated bydoxxieinto
source control and enforce that changes to it are always committed by using a
CI job.github workflowname:CIon:pull_request:push:branches:-mainjobs:check_api:runs-on:ubuntu-lateststeps:-uses:actions/checkout@v2-uses:actions/setup-python@v2with:python-version:'3.9'-name:install dependenciesrun:pip install mypy doxxie-run:DOXXIE_INCLUDES=doxxie DOXXIE_OUTFILE=.public_api_delta mypy --no-incremental-run:diff .public_api .public_api_delta