From de760708c4147182a7c2ae413d8dfe4a5b569bd9 Mon Sep 17 00:00:00 2001 From: juftin Date: Thu, 7 Dec 2023 21:51:20 -0700 Subject: [PATCH] feat: hatch deps sync --- src/hatch/cli/dep/__init__.py | 71 ++++++++++++++++++++ src/hatch/cli/env/run.py | 121 +++++++++++++++++++++------------- 2 files changed, 146 insertions(+), 46 deletions(-) diff --git a/src/hatch/cli/dep/__init__.py b/src/hatch/cli/dep/__init__.py index 46278d55e..a7932bd79 100644 --- a/src/hatch/cli/dep/__init__.py +++ b/src/hatch/cli/dep/__init__.py @@ -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(): @@ -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, + ) diff --git a/src/hatch/cli/env/run.py b/src/hatch/cli/env/run.py index a6d90d343..96ae6a53d 100644 --- a/src/hatch/cli/env/run.py +++ b/src/hatch/cli/env/run.py @@ -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, @@ -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 @@ -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}) @@ -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 @@ -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) @@ -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, + )