Commit 53cdce0d by Randy Döring

Add option to compile bytecode during installation (similar to default behavior of old installer)

parent f127bd27
......@@ -225,6 +225,21 @@ If you want to skip this installation, use the `--no-root` option.
poetry install --no-root
```
By default `poetry` does not compile Python source files to bytecode during installation.
This speeds up the installation process, but the first execution may take a little more
time because Python then compiles source files to bytecode automatically.
If you want to compile source files to bytecode during installation,
you can use the `--compile` option:
```bash
poetry install --compile
```
{{% note %}}
The `--compile` option has no effect if `installer.modern-installation`
is set to `false` because the old installer always compiles source files to bytecode.
{{% /note %}}
### Options
* `--without`: The dependency groups to ignore.
......@@ -236,6 +251,7 @@ poetry install --no-root
* `--dry-run`: Output the operations but do not execute anything (implicitly enables --verbose).
* `--extras (-E)`: Features to install (multiple values allowed).
* `--all-extras`: Install all extra features (conflicts with --extras).
* `--compile`: Compile Python source files to bytecode.
* `--no-dev`: Do not install dev dependencies. (**Deprecated**, use `--without dev` or `--only main` instead)
* `--remove-untracked`: Remove dependencies not presented in the lock file. (**Deprecated**, use `--sync` instead)
......
......@@ -54,12 +54,15 @@ class InstallCommand(InstallerCommand):
multiple=True,
),
option("all-extras", None, "Install all extra dependencies."),
option("only-root", None, "Exclude all dependencies."),
option(
"only-root",
"compile",
None,
"Exclude all dependencies.",
flag=True,
multiple=False,
(
"Compile Python source files to bytecode."
" (This option has no effect if modern-installation is disabled"
" because the old installer always compiles.)"
),
),
]
......@@ -146,6 +149,7 @@ dependencies and not including the current project, run the command with the
self.installer.only_groups(self.activated_groups)
self.installer.dry_run(self.option("dry-run"))
self.installer.requires_synchronization(with_synchronization)
self.installer.executor.enable_bytecode_compilation(self.option("compile"))
self.installer.verbose(self.io.is_verbose())
return_code = self.installer.run()
......
......@@ -123,6 +123,9 @@ class Executor:
return self
def enable_bytecode_compilation(self, enable: bool = True) -> None:
self._wheel_installer.enable_bytecode_compilation(enable)
def pip_install(
self, req: Path, upgrade: bool = False, editable: bool = False
) -> int:
......
......@@ -66,7 +66,10 @@ class WheelDestination(SchemeDictionaryDestination):
scheme_dict["headers"] = str(Path(scheme_dict["headers"]) / source.distribution)
return self.__class__(
scheme_dict, interpreter=self.interpreter, script_kind=self.script_kind
scheme_dict,
interpreter=self.interpreter,
script_kind=self.script_kind,
bytecode_optimization_levels=self.bytecode_optimization_levels,
)
......@@ -90,6 +93,9 @@ class WheelInstaller:
schemes, interpreter=self._env.python, script_kind=script_kind
)
def enable_bytecode_compilation(self, enable: bool = True) -> None:
self._destination.bytecode_optimization_levels = (1,) if enable else ()
def install(self, wheel: Path) -> None:
with WheelFile.open(Path(wheel.as_posix())) as source:
install(
......
......@@ -162,6 +162,24 @@ def test_sync_option_is_passed_to_the_installer(
assert tester.command.installer._requires_synchronization
@pytest.mark.parametrize("compile", [False, True])
def test_compile_option_is_passed_to_the_installer(
tester: CommandTester, mocker: MockerFixture, compile: bool
):
"""
The --compile option is passed properly to the installer.
"""
mocker.patch.object(tester.command.installer, "run", return_value=1)
enable_bytecode_compilation_mock = mocker.patch.object(
tester.command.installer.executor._wheel_installer,
"enable_bytecode_compilation",
)
tester.execute("--compile" if compile else "")
enable_bytecode_compilation_mock.assert_called_once_with(compile)
def test_no_all_extras_doesnt_populate_installer(
tester: CommandTester, mocker: MockerFixture
):
......
......@@ -59,3 +59,23 @@ def test_installer_file_contains_valid_version(default_installation: Path) -> No
match = re.match(r"Poetry (?P<version>.*)", installer_content)
assert match
parse_constraint(match.group("version")) # must not raise an error
def test_default_installation_no_bytecode(default_installation: Path) -> None:
cache_dir = default_installation / "demo" / "__pycache__"
assert not cache_dir.exists()
@pytest.mark.parametrize("compile", [True, False])
def test_enable_bytecode_compilation(
env: MockEnv, demo_wheel: Path, compile: bool
) -> None:
installer = WheelInstaller(env)
installer.enable_bytecode_compilation(compile)
installer.install(demo_wheel)
cache_dir = Path(env.paths["purelib"]) / "demo" / "__pycache__"
if compile:
assert cache_dir.exists()
assert list(cache_dir.glob("*.pyc"))
else:
assert not cache_dir.exists()
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment