From ef8de111b649703dd132aab47539558c1f801f0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lars=20Gr=C3=BCter?= Date: Mon, 7 Oct 2024 14:42:04 +0200 Subject: [PATCH] Refactor StaticInspector to TypesDatabase Reflects the current implementation why more. --- src/docstub/_analysis.py | 10 +++++----- src/docstub/_cli.py | 10 +++++----- src/docstub/_docstrings.py | 17 ++++++++--------- src/docstub/_stubs.py | 14 +++++++------- tests/test_analysis.py | 8 ++++---- 5 files changed, 29 insertions(+), 30 deletions(-) diff --git a/src/docstub/_analysis.py b/src/docstub/_analysis.py index 4fc471a..d4340ac 100644 --- a/src/docstub/_analysis.py +++ b/src/docstub/_analysis.py @@ -346,8 +346,8 @@ def leave_FunctionDef(self, original_node: cst.FunctionDef) -> None: self._stack.pop() -class StaticInspector: - """Static analysis of Python packages. +class TypesDatabase: + """A static database of collected types usable as an annotation. Attributes ---------- @@ -355,9 +355,9 @@ class StaticInspector: Examples -------- - >>> from docstub._analysis import StaticInspector, common_known_imports - >>> inspector = StaticInspector(known_imports=common_known_imports()) - >>> inspector.query("Any") + >>> from docstub._analysis import TypesDatabase, common_known_imports + >>> db = TypesDatabase(known_imports=common_known_imports()) + >>> db.query("Any") ('Any', ) """ diff --git a/src/docstub/_cli.py b/src/docstub/_cli.py index 4e98aad..49d39ff 100644 --- a/src/docstub/_cli.py +++ b/src/docstub/_cli.py @@ -8,8 +8,8 @@ from ._analysis import ( KnownImport, - StaticInspector, TypeCollector, + TypesDatabase, common_known_imports, ) from ._cache import FileCache @@ -145,12 +145,12 @@ def main(source_dir, out_dir, config_path, verbose): config = _load_configuration(config_path) known_imports = _build_import_map(config, source_dir) - inspector = StaticInspector( + types_db = TypesDatabase( source_pkgs=[source_dir.parent.resolve()], known_imports=known_imports ) # and the stub transformer stub_transformer = Py2StubTransformer( - inspector=inspector, replace_doctypes=config.replace_doctypes + types_db=types_db, replace_doctypes=config.replace_doctypes ) if not out_dir: @@ -182,14 +182,14 @@ def main(source_dir, out_dir, config_path, verbose): fo.write(stub_content) # Report basic statistics - successful_queries = inspector.stats["successful_queries"] + successful_queries = types_db.stats["successful_queries"] click.secho(f"{successful_queries} matched annotations", fg="green") grammar_errors = stub_transformer.transformer.stats["grammar_errors"] if grammar_errors: click.secho(f"{grammar_errors} grammar violations", fg="red") - unknown_doctypes = inspector.stats["unknown_doctypes"] + unknown_doctypes = types_db.stats["unknown_doctypes"] if unknown_doctypes: click.secho(f"{len(unknown_doctypes)} unknown doctypes:", fg="red") click.echo(" " + "\n ".join(set(unknown_doctypes))) diff --git a/src/docstub/_docstrings.py b/src/docstub/_docstrings.py index d7ba3d4..e4d26b8 100644 --- a/src/docstub/_docstrings.py +++ b/src/docstub/_docstrings.py @@ -155,13 +155,12 @@ class DoctypeTransformer(lark.visitors.Transformer): [('tuple', 0, 5), ('int', 9, 12)] """ - def __init__(self, *, inspector=None, replace_doctypes=None, **kwargs): + def __init__(self, *, types_db=None, replace_doctypes=None, **kwargs): """ Parameters ---------- - inspector : ~.StaticInspector - A dictionary mapping atomic names used in doctypes to information such - as where to import from or how to replace the name itself. + types_db : ~.TypesDatabase + A static database of collected types usable as an annotation. replace_doctypes : dict[str, str], optional Replacements for human-friendly aliases. kwargs : dict[Any, Any], optional @@ -170,7 +169,7 @@ def __init__(self, *, inspector=None, replace_doctypes=None, **kwargs): if replace_doctypes is None: replace_doctypes = {} - self.inspector = inspector + self.types_db = types_db self.replace_doctypes = replace_doctypes self._collected_imports = None @@ -302,16 +301,16 @@ def contains(self, tree): def literals(self, tree): out = ", ".join(tree.children) out = f"Literal[{out}]" - if self.inspector is not None: - _, known_import = self.inspector.query("Literal") + if self.types_db is not None: + _, known_import = self.types_db.query("Literal") if known_import: self._collected_imports.add(known_import) return out def _find_import(self, qualname, meta): """Match type names to known imports.""" - if self.inspector is not None: - annotation_name, known_import = self.inspector.query(qualname) + if self.types_db is not None: + annotation_name, known_import = self.types_db.query(qualname) else: annotation_name = None known_import = None diff --git a/src/docstub/_stubs.py b/src/docstub/_stubs.py index d903ac1..3951a77 100644 --- a/src/docstub/_stubs.py +++ b/src/docstub/_stubs.py @@ -179,7 +179,7 @@ class Py2StubTransformer(cst.CSTTransformer): Attributes ---------- - inspector : ~._analysis.StaticInspector + types_db : ~.TypesDatabase """ METADATA_DEPENDENCIES = (cst.metadata.PositionProvider,) @@ -198,17 +198,17 @@ class Py2StubTransformer(cst.CSTTransformer): _Annotation_Any = cst.Annotation(cst.Name("Any")) _Annotation_None = cst.Annotation(cst.Name("None")) - def __init__(self, *, inspector=None, replace_doctypes=None): + def __init__(self, *, types_db=None, replace_doctypes=None): """ Parameters ---------- - inspector : ~._analysis.StaticInspector + types_db : ~.TypesDatabase replace_doctypes : dict[str, str] """ - self.inspector = inspector + self.types_db = types_db self.replace_doctypes = replace_doctypes self.transformer = DoctypeTransformer( - inspector=inspector, replace_doctypes=replace_doctypes + types_db=types_db, replace_doctypes=replace_doctypes ) # Relevant docstring for the current context self._scope_stack = None # Entered module, class or function scopes @@ -225,8 +225,8 @@ def current_source(self): @current_source.setter def current_source(self, value): self._current_source = value - if self.inspector is not None: - self.inspector.current_source = value + if self.types_db is not None: + self.types_db.current_source = value def python_to_stub(self, source, *, module_path=None): """Convert Python source code to stub-file ready code. diff --git a/tests/test_analysis.py b/tests/test_analysis.py index 8da4d13..8959ec4 100644 --- a/tests/test_analysis.py +++ b/tests/test_analysis.py @@ -1,9 +1,9 @@ import pytest -from docstub._analysis import KnownImport, StaticInspector +from docstub._analysis import KnownImport, TypesDatabase -class Test_StaticInspector: +class Test_TypesDatabase: known_imports = { # noqa: RUF012 "dict": KnownImport(builtin_name="dict"), "np": KnownImport(import_name="numpy", import_alias="np"), @@ -48,9 +48,9 @@ class Test_StaticInspector: ] ) def test_query(self, name, exp_annotation, exp_import_line): - inspector = StaticInspector(known_imports=self.known_imports.copy()) + db = TypesDatabase(known_imports=self.known_imports.copy()) - annotation, known_import = inspector.query(name) + annotation, known_import = db.query(name) if exp_annotation is None and exp_import_line is None: assert exp_annotation is annotation