Skip to content

Commit

Permalink
refactor: renamed v to _lazy_value
Browse files Browse the repository at this point in the history
  • Loading branch information
15r10nk committed Feb 10, 2024
1 parent fd5b2e0 commit d7bd193
Show file tree
Hide file tree
Showing 6 changed files with 629 additions and 629 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ I hope this project allows more people to use lazy-imports in their projects.

How is it different to PEP 690?

- It has not the same performance like the implementation from the pep. Every access to parts of imported modules is transformed to an attribute access `x` -> `x.v`.
- It has not the same performance like the implementation from the pep. Every access to parts of imported modules is transformed to an attribute access `x` -> `x._lazy_value`.
- Exceptions during deferred import are converted to `LazyImportError`


Expand Down Expand Up @@ -78,7 +78,7 @@ bar = __lazy_imports_lite__.ImportFrom(__package__, "foo", "bar")


def f():
print(bar.v())
print(bar._lazy_value())
```

This transformation should be never visible to you (the original source location is preserved) but it is good to know if something does not work as expected.
Expand Down
26 changes: 13 additions & 13 deletions src/lazy_imports_lite/_hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@


class LazyObject:
__slots__ = ("v",)
__slots__ = ("_lazy_value",)


class LazyImportError(BaseException):
Expand All @@ -19,21 +19,21 @@ def __str__(self):


class ImportFrom(LazyObject):
__slots__ = ("package", "module", "name", "v")
__slots__ = ("package", "module", "name", "_lazy_value")

def __init__(self, package, module, name):
self.package = package
self.module = module
self.name = name

def __getattr__(self, name):
if name == "v":
if name == "_lazy_value":
module = safe_import(self.module, self.package)
try:
attr = getattr(module, self.name)
except AttributeError:
attr = safe_import(self.module + "." + self.name, self.package)
self.v = attr
self._lazy_value = attr
return attr
else:
assert False
Expand All @@ -53,7 +53,7 @@ def safe_import(module, package=None):


class Import(LazyObject):
__slots__ = ("module", "v")
__slots__ = ("module", "_lazy_value")

def __init__(self, module):
self.module = module
Expand All @@ -65,28 +65,28 @@ def __init__(self, module):
pending_imports[m].append(module)

def __getattr__(self, name):
if name == "v":
if name == "_lazy_value":
m = self.module.split(".")[0]
for pending in pending_imports[m]:
safe_import(pending)
result = safe_import(self.module.split(".")[0])
imported_modules.add(m)
self.v = result
self._lazy_value = result
return result
else:
assert False


class ImportAs(LazyObject):
__slots__ = ("module", "v")
__slots__ = ("module", "_lazy_value")

def __init__(self, module):
self.module = module

def __getattr__(self, name):
if name == "v":
if name == "_lazy_value":
module = safe_import(self.module)
self.v = module
self._lazy_value = module
return module
else:
assert False
Expand All @@ -95,9 +95,9 @@ def __getattr__(self, name):
def make_globals(global_provider):
def g():
return {
k: v.v if isinstance(v, LazyObject) else v
for k, v in dict(global_provider()).items()
if k not in ("globals", "__lazy_imports_lite__")
key: value._lazy_value if isinstance(value, LazyObject) else value
for key, value in dict(global_provider()).items()
if key not in ("globals", "__lazy_imports_lite__")
}

return g
14 changes: 7 additions & 7 deletions src/lazy_imports_lite/_loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,19 @@

class LazyModule(types.ModuleType):
def __getattribute__(self, name):
v = super().__getattribute__(name)
if isinstance(v, LazyObject):
return v.v
return v
value = super().__getattribute__(name)
if isinstance(value, LazyObject):
return value._lazy_value
return value

def __setattr__(self, name, value):
try:
v = super().__getattribute__(name)
current_value = super().__getattribute__(name)
except:
super().__setattr__(name, value)
else:
if isinstance(v, LazyObject):
v.v = value
if isinstance(current_value, LazyObject):
current_value._lazy_value = value
else:
super().__setattr__(name, value)

Expand Down
4 changes: 2 additions & 2 deletions src/lazy_imports_lite/_transformer.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ def handle_function(self, function):
for field, value in ast.iter_fields(function):
if field != "body":
if isinstance(value, list):
setattr(function, field, [self.visit(v) for v in value])
setattr(function, field, [self.visit(item) for item in value])
elif isinstance(value, ast.AST):
setattr(function, field, self.visit(value))
self.functions.append(function)
Expand Down Expand Up @@ -152,7 +152,7 @@ def visit_Name(self, node: ast.Name) -> Any:
if node.id in self.transformed_imports and node.id not in self.locals:
old_ctx = node.ctx
node.ctx = ast.Load()
return ast.Attribute(value=node, attr="v", ctx=old_ctx)
return ast.Attribute(value=node, attr="_lazy_value", ctx=old_ctx)
else:
return node

Expand Down
90 changes: 45 additions & 45 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,45 +1,45 @@
import subprocess as sp
import sys

import pytest
from inline_snapshot import snapshot


@pytest.mark.skipif(sys.version_info < (3, 9), reason="3.8 unparses differently")
def test_cli(tmp_path):
file = tmp_path / "example.py"

file.write_text(
"""\
from foo import bar
def f():
print(bar())
print(bar())
"""
)
result = sp.run(["lazy-imports-lite", "preview", str(file)], capture_output=True)
assert result.returncode == 0
assert result.stdout.decode().replace("\r\n", "\n") == snapshot(
"""\
import lazy_imports_lite._hooks as __lazy_imports_lite__
globals = __lazy_imports_lite__.make_globals(lambda g=globals: g())
bar = __lazy_imports_lite__.ImportFrom(__package__, 'foo', 'bar')
def f():
print(bar.v())
print(bar.v())
"""
)


def test_cli_invalid_args():
result = sp.run([sys.executable, "-m", "lazy_imports_lite"], capture_output=True)
assert result.returncode == 1
assert result.stdout.decode().replace("\r\n", "\n") == snapshot("")
assert result.stderr.decode().replace("\r\n", "\n") == snapshot(
"""\
Error: Please specify a valid subcommand. Use 'preview --help' for more information.
"""
)
import subprocess as sp
import sys

import pytest
from inline_snapshot import snapshot


@pytest.mark.skipif(sys.version_info < (3, 9), reason="3.8 unparses differently")
def test_cli(tmp_path):
file = tmp_path / "example.py"

file.write_text(
"""\
from foo import bar
def f():
print(bar())
print(bar())
"""
)
result = sp.run(["lazy-imports-lite", "preview", str(file)], capture_output=True)
assert result.returncode == 0
assert result.stdout.decode().replace("\r\n", "\n") == snapshot(
"""\
import lazy_imports_lite._hooks as __lazy_imports_lite__
globals = __lazy_imports_lite__.make_globals(lambda g=globals: g())
bar = __lazy_imports_lite__.ImportFrom(__package__, 'foo', 'bar')
def f():
print(bar._lazy_value())
print(bar._lazy_value())
"""
)


def test_cli_invalid_args():
result = sp.run([sys.executable, "-m", "lazy_imports_lite"], capture_output=True)
assert result.returncode == 1
assert result.stdout.decode().replace("\r\n", "\n") == snapshot("")
assert result.stderr.decode().replace("\r\n", "\n") == snapshot(
"""\
Error: Please specify a valid subcommand. Use 'preview --help' for more information.
"""
)
Loading

0 comments on commit d7bd193

Please sign in to comment.