"""
This tool will display all dependencies used by this package.
"""
import ast
import logging
from pathlib import Path
from pkglts.local import src_dir
LOGGER = logging.getLogger(__name__)
stdpkgs = set(
line.strip()
for line in open(Path(__file__).parent / "stdpkgs.txt").readlines()
if len(line.strip()) > 0 and not line.startswith("#")
)
[docs]
def iter_ext_imports(body):
for node in body:
if isinstance(node, ast.Import):
for alias in node.names:
yield alias.name
elif isinstance(node, ast.ImportFrom):
if node.level == 0: # only external imports
yield node.module
# elif isinstance(node, ast.FunctionDef):
# for name, level in iter_imports(node.body):
# yield name, level
[docs]
def find_reqs(pth):
"""Find all requirements (imports) used by a script.
Args:
pth (Path): path to file to parse
Returns:
(list): list of package names
"""
pt = ast.parse(pth.read_bytes(), str(pth))
# TODO pb with namespaces
pkgs = set(pkgname.split(".")[0] for pkgname in iter_ext_imports(pt.body))
return pkgs
def _iter_find_reqs(fld):
for pth in fld.glob("*.py"):
if not pth.name.startswith("_"):
for req in find_reqs(pth):
yield req
for subfld in fld.glob("*/"):
if subfld.name[0] not in ["_", "."]:
for req in _iter_find_reqs(subfld):
yield req
[docs]
def action_find_reqs(cfg, **kwds):
"""Find dependencies used by this package."""
LOGGER.info("Find requirements")
this_pkgname = cfg["base"]["pkgname"]
for dname in (src_dir(cfg), "doc", "example", "script", "test"):
dirpth = Path(dname)
if dirpth.exists():
print(f"############\n# {dirpth}\n############")
reqs = set(_iter_find_reqs(dirpth))
reqs -= {this_pkgname}
print("standard", sorted(reqs & stdpkgs))
print("external", sorted(reqs - stdpkgs))
print("")
[docs]
def parser_find_reqs(subparsers):
"""Associate a CLI to this tool.
Notes: The CLI will be a subcommand of pmg.
Args:
subparsers (ArgumentParser): entity to create a subparsers
Returns:
(string): a unique id for this parser
(callable): the action to perform
"""
subparsers.add_parser("reqs", help=action_find_reqs.__doc__)
return "reqs", action_find_reqs