From 119b295d719d418a2821d3ed07a8f472110403f2 Mon Sep 17 00:00:00 2001 From: Dima Gerasimov Date: Tue, 7 Jun 2022 22:37:45 +0100 Subject: [PATCH] core: allow legacy modules to be used in 'hpi module install' for backwards compatibility but show warning kinda hacky, but hopefully we will simplify it further when we have more such legacy modules --- misc/check_legacy_init_py.py | 4 +++- my/core/__main__.py | 3 +++ my/core/discovery_pure.py | 30 +++++++++++++++++++++++++++--- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/misc/check_legacy_init_py.py b/misc/check_legacy_init_py.py index c100368..1ba087e 100755 --- a/misc/check_legacy_init_py.py +++ b/misc/check_legacy_init_py.py @@ -12,7 +12,7 @@ import logzero # type: ignore[import] logger = logzero.logger -MSG = 'importing my.fbmessenger is DEPRECATED' +MSG = 'my.fbmessenger is DEPRECATED' def expect(*cmd: str, should_warn: bool=True) -> None: res = run(cmd, stderr=PIPE) @@ -61,6 +61,7 @@ check_warn('-c', 'from my.fbmessenger import *') check_warn('-c', 'from my.fbmessenger import messages, dump_chat_history') check_warn('-m', 'my.core', 'query' , 'my.fbmessenger.messages', '-o', 'pprint', '--limit=10') check_warn('-m', 'my.core', 'doctor', 'my.fbmessenger') +check_warn('-m', 'my.core', 'module', 'requires', 'my.fbmessenger') # todo kinda annoying it doesn't work when executed as -c (but does as script!) # presumably because doesn't have proper line number information? @@ -71,6 +72,7 @@ check_ok ('-c', 'from my.fbmessenger.export import *') check_ok ('-c', 'from my.fbmessenger.export import messages, dump_chat_history') check_ok ('-m', 'my.core', 'query' , 'my.fbmessenger.export.messages', '-o', 'pprint', '--limit=10') check_ok ('-m', 'my.core', 'doctor', 'my.fbmessenger.export') +check_ok ('-m', 'my.core', 'module', 'requires', 'my.fbmessenger.export') # NOTE: # to check that overlays work, run something like diff --git a/my/core/__main__.py b/my/core/__main__.py index ba9245a..4dfc021 100644 --- a/my/core/__main__.py +++ b/my/core/__main__.py @@ -339,6 +339,9 @@ def _requires(modules: Sequence[str]) -> Sequence[str]: mods = [module_by_name(module) for module in modules] res = [] for mod in mods: + if mod.legacy is not None: + warning(mod.legacy) + reqs = mod.requires if reqs is None: error(f"Module {mod.name} has no REQUIRES specification") diff --git a/my/core/discovery_pure.py b/my/core/discovery_pure.py index dbd07b9..5c9dbed 100644 --- a/my/core/discovery_pure.py +++ b/my/core/discovery_pure.py @@ -34,6 +34,7 @@ class HPIModule(NamedTuple): doc: Optional[str] = None file: Optional[Path] = None requires: Requires = None + legacy: Optional[str] = None # contains reason/deprecation warning def ignored(m: str) -> bool: @@ -75,9 +76,19 @@ def _is_not_module_src(src: Path) -> bool: def _is_not_module_ast(a: ast.Module) -> bool: + marker = NOT_HPI_MODULE_VAR return any( - getattr(node, 'name', None) == NOT_HPI_MODULE_VAR # direct definition - or any(getattr(n, 'name', None) == NOT_HPI_MODULE_VAR for n in getattr(node, 'names', [])) # import from + getattr(node, 'name', None) == marker # direct definition + or any(getattr(n, 'name', None) == marker for n in getattr(node, 'names', [])) # import from + for node in a.body + ) + + +def _is_legacy_module(a: ast.Module) -> bool: + marker = 'handle_legacy_import' + return any( + getattr(node, 'name', None) == marker # direct definition + or any(getattr(n, 'name', None) == marker for n in getattr(node, 'names', [])) # import from for node in a.body ) @@ -156,7 +167,11 @@ def _modules_under_root(my_root: Path) -> Iterable[HPIModule]: if ignored(m): continue a: ast.Module = ast.parse(f.read_text()) - if _is_not_module_ast(a): + + # legacy modules are 'forced' to be modules so 'hpi module install' still works for older modules + # a bit messy, will think how to fix it properly later + legacy_module = _is_legacy_module(a) + if _is_not_module_ast(a) and not legacy_module: continue doc = ast.get_docstring(a, clean=False) @@ -166,12 +181,15 @@ def _modules_under_root(my_root: Path) -> Iterable[HPIModule]: except Exception as e: logging.exception(e) + legacy = f'{m} is DEPRECATED. Please refer to the module documentation.' if legacy_module else None + yield HPIModule( name=m, skip_reason=None, doc=doc, file=f.relative_to(my_root.parent), requires=requires, + legacy=legacy, ) @@ -209,6 +227,12 @@ def test_requires() -> None: assert len(r) == 2 # fragile, but ok for now +def test_legacy_modules() -> None: + # shouldn't crash + module_by_name('my.reddit') + module_by_name('my.fbmessenger') + + def test_pure() -> None: """ We want to keep this module clean of other HPI imports