Welcome to depfinder documentation!¶
depfinder¶
Installation¶
depfinder
is on pypi. It is tested against Python 2.7 and 3.6-3.8.
pip install depfinder
It is available via conda.
conda install -c conda-forge depfinder
It is also via github.
git clone git@github.com:ericdill/depfinder
cd depfinder
python setup.py install
Using depfinder¶
$ depfinder -h
usage: depfinder [-h] [-y] [-V] [--no-remap] [-v] [-q] [-k KEY] [--conda]
[--pdb]
file_or_directory
Tool for inspecting the dependencies of your python project.
positional arguments:
file_or_directory Valid options are a single python file, a single jupyter
(ipython) notebook or a directory of files that include
python files
optional arguments:
-h, --help show this help message and exit
-y, --yaml Output in syntactically valid yaml when true. Defaults to
False
-V, --version Print out the version of depfinder and exit
--no-remap Do not remap the names of the imported libraries to their
proper conda name
-v, --verbose Enable debug level logging info from depfinder
-q, --quiet Turn off all logging from depfinder
-k KEY, --key KEY Select some or all of the output keys. Valid options are
'required', 'optional', 'builtin', 'relative', 'all'.
Defaults to 'all'
--conda Format output so it can be passed as an argument to conda
install or conda create
--pdb Enable PDB debugging on exception
Ok, great. That’s the help output. Not super helpful. What does the output of depfinder look like when we run it on the source code for depfinder?
$ depfinder depfinder
{'builtin': ['__future__',
'argparse',
'ast',
'collections',
'copy',
'errno',
'json',
'logging',
'os',
'pprint',
're',
'subprocess',
'sys'],
'relative': ['_version', 'main'],
'required': ['pyyaml', 'stdlib-list']}
So, what do these things mean? Well builtin
are modules
that are built in to the standard library. required
are
modules that are not from the standard library or from within the
depfinder
package and relative
are modules
that are imported from one module to another within the
depfinder
source code.
Also see this notebook
Description¶
Find all the unique imports in your library, automatically, because who
likes do it by hand? depfinder
uses the ast (Abstract
Syntax Tree) module (and more ast
docs) to find all
:pyast.Try
{.interpreted-text role=”class”} and
:pyast.ImportFrom
{.interpreted-text role=”class”} nodes. These
:pyast.Import
{.interpreted-text role=”class”} and
:pyast.ImportFrom
{.interpreted-text role=”class”} nodes are then
grouped according to the following categories, in order of decreasing
precedence:
relative : The import is a relative import from within the same library
builtin : The import is built into the standard library, as determined by scraping the official python docs for the builtins with stdlib-list
questionable : The import occurs inside any combination of
ast.Try
(ast.TryExcept
on py27)ast.FunctionDef
orast.AsyncFunctionDef
ast.If
,ast.While
,ast.For
, orast.AsyncFor
.ast.match_case
.
The module may be importable without these imports, but the it will likely not have full functionality.
required : The import occurs at the top level of the module and will get executed when the module is imported. These imports must be accounted for in an environment, or the module will not be importable.
Testing¶
It has dependencies on,
stdlib-list and
pyyaml. I use stdlib-list
to get the
list of libraries built in to the standard library. These requirements
can be installed via pip :
pip install -r requirements.txt
Also install the test-requiements :
pip install -r test-requirements.txt
Then you can run the tests from the root of the git repository :
coverage run run_tests.py
Releasing¶
manual:
create an annotated tag and push it to github.
git tag -a TAG and then
git push –tags`git checkout TAG
python -m build --sdist --wheel . --outdir dist
twine check dist/*
twine upload dist/* --verbose
API¶
- depfinder.main.get_imported_libs(code, filename='', custom_namespaces=None)[source]¶
Given a code snippet, return a list of the imported libraries
- Parameters:
- codestr
The code to parse and look for imports
- Returns:
- ImportCatcher
The ImportCatcher is the object in depfinder that contains all the information regarding which imports were found where. You will most likely be interested in calling the describe() function on this return value.
Examples
>>> depfinder.get_imported_libs('from foo import bar') {'required': {'foo'}, 'questionable': set()} >>> with open('depfinder.py') as f: code = f.read() imports = depfinder.get_imported_libs(code) print(imports.describe()) {'builtin': {'__future__', 'json', 'ast', 'os', 'sys', 'collections'}, 'required': {'stdlib_list'}}
- depfinder.main.iterate_over_library(path_to_source_code, custom_namespaces=None)[source]¶
Helper function to recurse into a library and find imports in .py files.
This allows the user to apply filters on the user-side to exclude imports based on their file names. conda-skeletor makes heavy use of this function
- Parameters:
- path_to_source_codestr
- Yields:
- catcherstuple
Yields tuples of (module_name, full_path_to_module, ImportCatcher)
- depfinder.main.simple_import_search(path_to_source_code, remap=True, ignore=None, custom_namespaces=None)[source]¶
Return all imported modules in all .py files in path_to_source_code
- Parameters:
- path_to_source_codestr
- remapbool, optional
Normalize the import names to be synonymous with their conda/pip names
- ignorelist, optional
String pattern which if matched causes the file to not be inspected
- custom_namespaceslist of str or None
If not None, then resulting package outputs will list everying under these namespaces (e.g., for packages foo.bar and foo.baz, the outputs are foo.bar and foo.baz instead of foo if custom_namespaces=[“foo”]).
- Returns:
- dict
The list of all imported modules, sorted according to the keys listed in the docstring of depfinder.ImportCatcher.describe()
Examples
>>> depfinder.simple_import_search('/path/to/depfinder/source') {'builtin': ['__future__', 'ast', 'collections', 'json', 'os', 'shlex', 'sys', 'tempfile'], 'required': ['depfinder', 'nbformat', 'pytest', 'setuptools', 'sphinx_rtd_theme', 'stdlib_list', 'test_with_code']}
IPython/Jupyter Notebook support¶
depfinder
has support for v4 Jupyter notebooks.
- depfinder.main.notebook_path_to_dependencies(path_to_notebook, remap=True, custom_namespaces=None)[source]¶
Helper function that turns a jupyter notebook into a list of dependencies
- Parameters:
- path_to_notebookstr
- remapbool, optional
Normalize the import names to be synonymous with their conda/pip names
- custom_namespaceslist of str ot None, optional
If not None, then resulting package outputs will list everying under these namespaces (e.g., for packages foo.bar and foo.baz, the outputs are foo.bar and foo.baz instead of foo if custom_namespaces=[“foo”]).
- Returns:
- dict
Dict of dependencies keyed on
‘builtin’ - libraries built in to python
‘required’ - libraries that are found at the top level of your modules
‘questionable’ - libraries that are found inside try/except blocks
‘relative’ - libraries that are relative imports
Examples
>>> depfinder.notebook_path_to_dependencies('depfinder_usage.ipynb') {'builtin': ['os', 'pprint'], 'required': ['depfinder']}