Skip to content

Commit

Permalink
feat: hatch deps sync
Browse files Browse the repository at this point in the history
  • Loading branch information
juftin committed Dec 8, 2023
1 parent 10271b8 commit de76070
Show file tree
Hide file tree
Showing 2 changed files with 146 additions and 46 deletions.
71 changes: 71 additions & 0 deletions src/hatch/cli/dep/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import click

from hatch.cli.env.run import prepare_and_optionally_run


@click.group(short_help='Manage environment dependencies')
def dep():
Expand Down Expand Up @@ -144,3 +146,72 @@ def requirements(app, project_only, env_only, features, all_features):

for dependency in get_normalized_dependencies(all_requirements):
app.display(dependency)


@dep.command(short_help='Sync the latest dependencies into project environments')
@click.option('--env', '-e', 'env_names', multiple=True, help='The environments to target')
@click.option('--all', '-a', 'sync_all', is_flag=True, help='Sync all environments')
@click.option(
'--matrix/--no-matrix', is_flag=True, default=False, help='Used with `--all` to exclude matrix environments'
)
@click.option('--include', '-i', 'included_variable_specs', multiple=True, help='The matrix variables to include')
@click.option('--exclude', '-x', 'excluded_variable_specs', multiple=True, help='The matrix variables to exclude')
@click.option('--filter', '-f', 'filter_json', help='The JSON data used to select environments')
@click.option('--ignore-compat', is_flag=True, help='Ignore incompatibility when selecting specific environments')
@click.pass_obj
def sync(
app,
env_names,
included_variable_specs,
excluded_variable_specs,
filter_json,
ignore_compat,
sync_all,
matrix,
):
"""
Sync the dependencies within a project environment
The `-e`/`--env` option overrides the equivalent [root option](#hatch) and the `HATCH_ENV` environment variable.
You can also use the `--all` option to sync all environments. You can optionally
combine this with the `--matrix` option to include matrix environments.
\b
```
hatch dep sync --all --matrix
```
If environments provide matrices, then you may use the `-i`/`--include` and `-x`/`--exclude` options to
select or exclude certain variables, optionally followed by specific comma-separated values.
For example, if you have the following configuration:
\b
```toml config-example
[[tool.hatch.envs.test.matrix]]
python = ["3.9", "3.10"]
version = ["42", "3.14", "9000"]
```
then running:
\b
```
hatch dep sync -i py=3.10 -x version=9000
```
would sync the environments `test.py3.10-42` and `test.py3.10-3.14`.
Note that `py` may be used as an alias for `python`.
"""
prepare_and_optionally_run(
app=app,
env_names=env_names,
included_variable_specs=included_variable_specs,
excluded_variable_specs=excluded_variable_specs,
filter_json=filter_json,
ignore_compat=ignore_compat,
args=None,
force_continue=None,
exclude_matrix=not matrix,
run_all=sync_all,
)
121 changes: 75 additions & 46 deletions src/hatch/cli/env/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,18 +49,7 @@ def filter_environments(environments, filter_data):
return selected_environments


@click.command(short_help='Run commands within project environments')
@click.argument('args', required=True, nargs=-1)
@click.option('--env', '-e', 'env_names', multiple=True, help='The environments to target')
@click.option('--include', '-i', 'included_variable_specs', multiple=True, help='The matrix variables to include')
@click.option('--exclude', '-x', 'excluded_variable_specs', multiple=True, help='The matrix variables to exclude')
@click.option('--filter', '-f', 'filter_json', help='The JSON data used to select environments')
@click.option(
'--force-continue', is_flag=True, help='Run every command and if there were any errors exit with the first code'
)
@click.option('--ignore-compat', is_flag=True, help='Ignore incompatibility when selecting specific environments')
@click.pass_obj
def run(
def prepare_and_optionally_run(
app,
args,
env_names,
Expand All @@ -69,33 +58,9 @@ def run(
filter_json,
force_continue,
ignore_compat,
run_all,
exclude_matrix,
):
"""
Run commands within project environments.
The `-e`/`--env` option overrides the equivalent [root option](#hatch) and the `HATCH_ENV` environment variable.
If environments provide matrices, then you may use the `-i`/`--include` and `-x`/`--exclude` options to
select or exclude certain variables, optionally followed by specific comma-separated values.
For example, if you have the following configuration:
\b
```toml config-example
[[tool.hatch.envs.test.matrix]]
python = ["3.9", "3.10"]
version = ["42", "3.14", "9000"]
```
then running:
\b
```
hatch env run -i py=3.10 -x version=9000 test:pytest
```
would execute `pytest` in the environments `test.py3.10-42` and `test.py3.10-3.14`.
Note that `py` may be used as an alias for `python`.
"""
app.ensure_environment_plugin_dependencies()

project = app.project
Expand All @@ -122,7 +87,8 @@ def run(
'scripts': project.config.scripts,
}
}

if run_all:
env_names = list(project.config.envs.keys())
# Deduplicate
env_names = list({env_name: None for env_name in env_names})

Expand Down Expand Up @@ -160,7 +126,8 @@ def run(
with project.location.as_cwd():
for env_name in environments:
environment = app.get_environment(env_name)

if run_all and exclude_matrix and environment.matrix_variables:
continue
try:
environment.check_compatibility()
except Exception as e: # noqa: BLE001
Expand All @@ -178,12 +145,13 @@ def run(
environment.exists = lambda: True

app.prepare_environment(environment)
app.run_shell_commands(
environment,
[environment.join_command_args(args)],
force_continue=force_continue,
show_code_on_error=False,
)
if args:
app.run_shell_commands(
environment,
[environment.join_command_args(args)],
force_continue=force_continue,
show_code_on_error=False,
)

if incompatible:
num_incompatible = len(incompatible)
Expand All @@ -193,3 +161,64 @@ def run(
)
for env_name, reason in incompatible.items():
app.display_warning(f'{env_name} -> {reason}')


@click.command(short_help='Run commands within project environments')
@click.argument('args', required=True, nargs=-1)
@click.option('--env', '-e', 'env_names', multiple=True, help='The environments to target')
@click.option('--include', '-i', 'included_variable_specs', multiple=True, help='The matrix variables to include')
@click.option('--exclude', '-x', 'excluded_variable_specs', multiple=True, help='The matrix variables to exclude')
@click.option('--filter', '-f', 'filter_json', help='The JSON data used to select environments')
@click.option(
'--force-continue', is_flag=True, help='Run every command and if there were any errors exit with the first code'
)
@click.option('--ignore-compat', is_flag=True, help='Ignore incompatibility when selecting specific environments')
@click.pass_obj
def run(
app,
args,
env_names,
included_variable_specs,
excluded_variable_specs,
filter_json,
force_continue,
ignore_compat,
):
"""
Run commands within project environments.
The `-e`/`--env` option overrides the equivalent [root option](#hatch) and the `HATCH_ENV` environment variable.
If environments provide matrices, then you may use the `-i`/`--include` and `-x`/`--exclude` options to
select or exclude certain variables, optionally followed by specific comma-separated values.
For example, if you have the following configuration:
\b
```toml config-example
[[tool.hatch.envs.test.matrix]]
python = ["3.9", "3.10"]
version = ["42", "3.14", "9000"]
```
then running:
\b
```
hatch env run -i py=3.10 -x version=9000 test:pytest
```
would execute `pytest` in the environments `test.py3.10-42` and `test.py3.10-3.14`.
Note that `py` may be used as an alias for `python`.
"""
prepare_and_optionally_run(
app=app,
args=args,
env_names=env_names,
included_variable_specs=included_variable_specs,
excluded_variable_specs=excluded_variable_specs,
filter_json=filter_json,
force_continue=force_continue,
ignore_compat=ignore_compat,
run_all=False,
exclude_matrix=True,
)

0 comments on commit de76070

Please sign in to comment.