diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index cc76b77..7f7c1d1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,4 +34,4 @@ jobs: - name: Test run: | - pytest + PYTHONPATH=. pytest diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index fbca482..29ef555 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -9,7 +9,7 @@ repos: - id: end-of-file-fixer - id: trailing-whitespace - repo: https://github.com/psf/black - rev: 22.1.0 + rev: 22.3.0 hooks: - id: black - repo: https://gitlab.com/pycqa/flake8 diff --git a/lazy_loader/__init__.py b/lazy_loader/__init__.py index b1962af..08896b7 100644 --- a/lazy_loader/__init__.py +++ b/lazy_loader/__init__.py @@ -71,8 +71,18 @@ def __getattr__(name): if name in submodules: return importlib.import_module(f"{package_name}.{name}") elif name in attr_to_modules: - submod = importlib.import_module(f"{package_name}.{attr_to_modules[name]}") - return getattr(submod, name) + submod_path = f"{package_name}.{attr_to_modules[name]}" + submod = importlib.import_module(submod_path) + attr = getattr(submod, name) + + # If the attribute lives in a file (module) with the same + # name as the attribute, ensure that the attribute and *not* + # the module is accessible on the package. + if name == attr_to_modules[name]: + pkg = sys.modules[package_name] + pkg.__dict__[name] = attr + + return attr else: raise AttributeError(f"No {package_name} attribute {name}") diff --git a/tests/fake_pkg/__init__.py b/tests/fake_pkg/__init__.py new file mode 100644 index 0000000..540fd73 --- /dev/null +++ b/tests/fake_pkg/__init__.py @@ -0,0 +1,5 @@ +import lazy_loader as lazy + +__getattr__, __lazy_dir__, __all__ = lazy.attach( + __name__, submod_attrs={"some_func": ["some_func"]} +) diff --git a/tests/fake_pkg/some_func.py b/tests/fake_pkg/some_func.py new file mode 100644 index 0000000..10e99ed --- /dev/null +++ b/tests/fake_pkg/some_func.py @@ -0,0 +1,3 @@ +def some_func(): + """Function with same name as submodule.""" + pass diff --git a/tests/test_lazy_loader.py b/tests/test_lazy_loader.py index f74009f..d1ee06c 100644 --- a/tests/test_lazy_loader.py +++ b/tests/test_lazy_loader.py @@ -94,3 +94,17 @@ def test_lazy_attach(): for k, v in expected.items(): if v is not None: assert locls[k] == v + + +def test_attach_same_module_and_attr_name(): + import fake_pkg + + # Grab attribute twice, to ensure that importing it does not + # override function by module + assert isinstance(fake_pkg.some_func, types.FunctionType) + assert isinstance(fake_pkg.some_func, types.FunctionType) + + # Ensure imports from submodule still work + from fake_pkg.some_func import some_func + + assert isinstance(some_func, types.FunctionType)