diff --git a/README.md b/README.md index 13b2fd2..ca072ee 100644 --- a/README.md +++ b/README.md @@ -347,6 +347,8 @@ See also git tags: https://github.com/jedie/manageprojects/tags [comment]: <> (✂✂✂ auto generated history start ✂✂✂) +* [**dev**](https://github.com/jedie/manageprojects/compare/v0.20.0...main) + * 2024-11-21 - Switch from click to tyro * [v0.20.0](https://github.com/jedie/manageprojects/compare/v0.19.2...v0.20.0) * 2024-11-11 - Bugfix publish: Add "build" dep. * 2024-11-11 - Bugfix publish command: Add missing "setuptools" dep. @@ -359,12 +361,12 @@ See also git tags: https://github.com/jedie/manageprojects/tags * 2024-09-24 - Update requirements * [v0.19.1](https://github.com/jedie/manageprojects/compare/v0.19.0...v0.19.1) * 2024-09-15 - Bugfix and enhance "setup_python.py" -* [v0.19.0](https://github.com/jedie/manageprojects/compare/v0.18.0...v0.19.0) - * 2024-09-15 - NEW: setup_python.py - * 2024-09-15 - Update requirements
Expand older history entries ... +* [v0.19.0](https://github.com/jedie/manageprojects/compare/v0.18.0...v0.19.0) + * 2024-09-15 - NEW: setup_python.py + * 2024-09-15 - Update requirements * [v0.18.0](https://github.com/jedie/manageprojects/compare/v0.17.1...v0.18.0) * 2024-08-29 - Fix wrong "module" in publish call :( * 2024-08-29 - Fix wrong "distribution_name" in publish command diff --git a/manageprojects/cli_app/__init__.py b/manageprojects/cli_app/__init__.py index 36393ef..60f56f4 100644 --- a/manageprojects/cli_app/__init__.py +++ b/manageprojects/cli_app/__init__.py @@ -5,13 +5,11 @@ import logging import sys -import rich_click as click from cli_base.autodiscover import import_all_files +from cli_base.cli_tools.rich_utils import rich_traceback_install from cli_base.cli_tools.version_info import print_version from rich import print # noqa -from rich.console import Console -from rich.traceback import install as rich_traceback_install -from rich_click import RichGroup +from tyro.extras import SubcommandApp import manageprojects from manageprojects import constants @@ -19,26 +17,14 @@ logger = logging.getLogger(__name__) +app = SubcommandApp() -class ClickGroup(RichGroup): # FIXME: How to set the "info_name" easier? - def make_context(self, info_name, *args, **kwargs): - info_name = './cli.py' - return super().make_context(info_name, *args, **kwargs) - -@click.group( - cls=ClickGroup, - epilog=constants.CLI_EPILOG, -) -def cli(): - pass - - -# Register all click commands, just by import all files in this package: +# Register all CLI commands, just by import all files in this package: import_all_files(package=__package__, init_file=__file__) -@cli.command() +@app.command def version(): """Print version and exit""" # Pseudo command, because the version always printed on every CLI call ;) @@ -48,14 +34,14 @@ def version(): def main(): print_version(manageprojects) - console = Console() - rich_traceback_install( - width=console.size.width, # full terminal width - show_locals=True, - suppress=[click], - max_frames=2, - ) + rich_traceback_install() + + # Work-a-round for: https://github.com/brentyi/tyro/issues/205 + app._subcommands = {k.replace('_', '-'): v for k, v in app._subcommands.items()} - # Execute Click CLI: - cli.name = './cli.py' - cli() + app.cli( + prog='./cli.py', + description=constants.CLI_EPILOG, + use_underscores=False, # use hyphens instead of underscores + sort_subcommands=True, + ) diff --git a/manageprojects/cli_app/manage.py b/manageprojects/cli_app/manage.py index d708cee..633c623 100644 --- a/manageprojects/cli_app/manage.py +++ b/manageprojects/cli_app/manage.py @@ -9,25 +9,15 @@ import subprocess import sys from pathlib import Path +from typing import Annotated -import rich_click as click from bx_py_utils.path import assert_is_dir from cli_base.cli_tools.subprocess_utils import verbose_check_call -from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE -from cli_base.cli_tools.version_info import print_version -from cli_base.click_defaults import ( - ARGUMENT_EXISTING_DIR, - ARGUMENT_EXISTING_FILE, - ARGUMENT_NOT_EXISTING_DIR, - OPTION_ARGS_DEFAULT_FALSE, - OPTION_ARGS_DEFAULT_TRUE, -) +from cli_base.tyro_commands import TyroVerbosityArgType from rich import print # noqa -from rich.console import Console -from rich.traceback import install as rich_traceback_install +from tyro.conf import arg -import manageprojects -from manageprojects.cli_app import cli +from manageprojects.cli_app import app from manageprojects.constants import ( FORMAT_PY_FILE_DARKER_PRE_FIXES, FORMAT_PY_FILE_DEFAULT_MAX_LINE_LENGTH, @@ -47,52 +37,49 @@ logger = logging.getLogger(__name__) -@cli.command() -@click.argument('template') -@click.argument('output_dir', **ARGUMENT_NOT_EXISTING_DIR) -@click.option( - '--directory', - default=None, - help=( - 'Cookiecutter Option: Directory within repo that holds cookiecutter.json file' - ' for advanced repositories with multi templates in it' - ), -) -@click.option( - '--checkout', - default=None, - help='Cookiecutter Option: branch, tag or commit to checkout after git clone', -) -@click.option( - '--input/--no-input', - **OPTION_ARGS_DEFAULT_TRUE, - help=('Cookiecutter Option: Do not prompt for parameters' ' and only use cookiecutter.json file content'), -) -@click.option( - '--replay/--no-replay', - **OPTION_ARGS_DEFAULT_FALSE, - help=('Cookiecutter Option: Do not prompt for parameters' ' and only use information entered previously'), -) -@click.option( - '--password', - default=None, - help='Cookiecutter Option: Password to use when extracting the repository', -) -@click.option( - '--config-file', - default=None, - type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True), - help='Cookiecutter Option: Optional path to "cookiecutter_config.yaml"', -) +@app.command def start_project( - template: str, - output_dir: Path, - directory: str | None, - checkout: str | None, - input: bool, - replay: bool, - password: str | None, - config_file: Path | None, + template: Annotated[ + str, + arg(help='The name of the CookieCutter Template.'), + ], + output_dir: Annotated[ + Path, + arg(help='Target path for the new project. Must not exist yet!'), + ], + /, + verbosity: TyroVerbosityArgType, + # + # Cookiecutter options: + directory: Annotated[ + str, + arg( + help=( + 'Cookiecutter Option: Directory within repo that holds cookiecutter.json file' + ' for advanced repositories with multi templates in it' + ) + ), + ] = None, + replay: Annotated[ + bool, + arg(help='Cookiecutter Option: Do not prompt for parameters and only use information entered previously'), + ] = False, + input: Annotated[ + bool, + arg(help='Cookiecutter Option: Do not prompt for parameters and only use cookiecutter.json file content'), + ] = False, + checkout: Annotated[ + str | None, + arg(help='Cookiecutter Option: Optional branch, tag or commit ID to checkout after clone'), + ] = None, + password: Annotated[ + str | None, + arg(help='Cookiecutter Option: Password to use when extracting the repository'), + ] = None, + config_file: Annotated[ + Path | None, + arg(help='Cookiecutter Option: Optional path to "cookiecutter_config.yaml"'), + ] = None, ): """ Start a new "managed" project via a CookieCutter Template. @@ -102,7 +89,7 @@ def start_project( ./cli.py start-project https://github.com/jedie/cookiecutter_templates/ --directory piptools-python ~/foobar/ """ - log_config() + log_config(verbosity, log_in_file=True) print(f'Start project with template: {template!r}') print(f'Destination: {output_dir}') if output_dir.exists(): @@ -127,49 +114,40 @@ def start_project( return result -cli.add_command(start_project) - - -@cli.command() -@click.argument('project_path', **ARGUMENT_EXISTING_DIR) -@click.option( - '--overwrite/--no-overwrite', - **OPTION_ARGS_DEFAULT_TRUE, - help=( - 'Overwrite all Cookiecutter template files to the last template state and' - ' do not apply the changes via git patches.' - ' The developer is supposed to apply the differences manually via git.' - ' Will be aborted if the project git repro is not in a clean state.' - ), -) -@click.option( - '--password', - default=None, - help='Cookiecutter Option: Password to use when extracting the repository', -) -@click.option( - '--config-file', - default=None, - type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True), - help='Cookiecutter Option: Optional path to "cookiecutter_config.yaml"', -) -@click.option( - '--input/--no-input', - **OPTION_ARGS_DEFAULT_FALSE, - help='Cookiecutter Option: Do not prompt for parameters and only use cookiecutter.json file content', -) -@click.option( - '--cleanup/--no-cleanup', - **OPTION_ARGS_DEFAULT_TRUE, - help='Cleanup created temporary files', -) +@app.command def update_project( project_path: Path, - overwrite: bool, - password: str | None, - config_file: Path | None, - input: bool, - cleanup: bool, + /, + verbosity: TyroVerbosityArgType, + overwrite: Annotated[ + bool, + arg( + help=( + 'Overwrite all Cookiecutter template files to the last template state and' + ' do not apply the changes via git patches.' + ' The developer is supposed to apply the differences manually via git.' + ' Will be aborted if the project git repro is not in a clean state.' + ) + ), + ] = True, + cleanup: Annotated[ + bool, + arg(help='Cleanup created temporary files'), + ] = True, + # + # Cookiecutter options: + input: Annotated[ + bool, + arg(help='Cookiecutter Option: Do not prompt for parameters and only use cookiecutter.json file content'), + ] = False, + password: Annotated[ + str | None, + arg(help='Cookiecutter Option: Password to use when extracting the repository'), + ] = None, + config_file: Annotated[ + Path | None, + arg(help='Cookiecutter Option: Optional path to "cookiecutter_config.yaml"'), + ] = None, ): """ Update a existing project. @@ -178,7 +156,7 @@ def update_project( ./cli.py update-project ~/foo/bar/ """ - log_config() + log_config(verbosity, log_in_file=True) print(f'Update project: "{project_path}"...') update_managed_project( project_path=project_path, @@ -191,35 +169,36 @@ def update_project( print(f'Managed project "{project_path}" updated, ok.') -cli.add_command(update_project) - - -@cli.command() -@click.argument('project_path', **ARGUMENT_EXISTING_DIR) -@click.argument('output_dir', **ARGUMENT_NOT_EXISTING_DIR) -@click.option( - '--password', - default=None, - help='Cookiecutter Option: Password to use when extracting the repository', -) -@click.option( - '--config-file', - default=None, - type=click.Path(exists=True, file_okay=True, dir_okay=False, readable=True), - help='Cookiecutter Option: Optional path to "cookiecutter_config.yaml"', -) -@click.option( - '--input/--no-input', - **OPTION_ARGS_DEFAULT_FALSE, - help=('Cookiecutter Option: Do not prompt for parameters' ' and only use cookiecutter.json file content'), -) +@app.command def clone_project( - project_path: Path, - output_dir: Path, - input: bool, - checkout: str | None = None, - password: str | None = None, - config_file: Path | None = None, + project_path: Annotated[ + Path, + arg(help='Source project that should be cloned. Must be a managed project!'), + ], + output_dir: Annotated[ + Path, + arg(help='Destination of the cloned project. Must not exist yet!'), + ], + /, + verbosity: TyroVerbosityArgType, + # + # Cookiecutter options: + input: Annotated[ + bool, + arg(help='Cookiecutter Option: Do not prompt for parameters and only use cookiecutter.json file content'), + ] = False, + checkout: Annotated[ + str | None, + arg(help='Cookiecutter Option: Optional branch, tag or commit ID to checkout after clone'), + ] = None, + password: Annotated[ + str | None, + arg(help='Cookiecutter Option: Password to use when extracting the repository'), + ] = None, + config_file: Annotated[ + Path | None, + arg(help='Cookiecutter Option: Optional path to "cookiecutter_config.yaml"'), + ] = None, ): """ Clone existing project by replay the cookiecutter template in a new directory. @@ -228,8 +207,7 @@ def clone_project( ./cli.py clone-project ~/foo/bar ~/cloned/ """ - print(locals()) - log_config() + log_config(verbosity=verbosity) return clone_managed_project( project_path=project_path, destination=output_dir, @@ -240,23 +218,13 @@ def clone_project( ) -cli.add_command(clone_project) - - -@cli.command() -@click.argument('project_path', **ARGUMENT_EXISTING_DIR) -@click.argument('destination', **ARGUMENT_NOT_EXISTING_DIR) -@click.option( - '--overwrite/--no-overwrite', - **OPTION_ARGS_DEFAULT_FALSE, - help='Overwrite existing files.', -) -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) +@app.command def reverse( project_path: Path, destination: Path, - overwrite: bool, - verbosity: int, + /, + verbosity: TyroVerbosityArgType, + overwrite: Annotated[bool, arg(help='Overwrite existing files.')] = False, ): """ Create a cookiecutter template from a managed project. @@ -265,7 +233,7 @@ def reverse( ./cli.py reverse ~/my_managed_project/ ~/my_new_cookiecutter_template/ """ - log_config() + log_config(verbosity) return reverse_managed_project( project_path=project_path, destination=destination, @@ -274,17 +242,12 @@ def reverse( ) -cli.add_command(reverse) - - -@cli.command() -@click.argument('project_path', **ARGUMENT_EXISTING_DIR) -@click.option( - '--words/--no-words', - **OPTION_ARGS_DEFAULT_FALSE, - help='wiggle Option: word-wise diff and merge.', -) -def wiggle(project_path: Path, words: bool): +@app.command +def wiggle( + project_path: Path, + /, + words: Annotated[bool, arg(help='wiggle Option: word-wise diff and merge.')] = False, +): """ Run wiggle to merge *.rej in given directory. https://github.com/neilbrown/wiggle @@ -323,43 +286,27 @@ def wiggle(project_path: Path, words: bool): continue -cli.add_command(wiggle) - - -@cli.command() -@click.option( - '--py-version', - default=FORMAT_PY_FILE_DEFAULT_MIN_PYTHON_VERSION, - show_default=True, - help='Fallback Python version for darker/pyupgrade, if version is not defined in pyproject.toml', -) -@click.option( - '-l', - '--max-line-length', - default=FORMAT_PY_FILE_DEFAULT_MAX_LINE_LENGTH, - type=int, - show_default=True, - help='Fallback max. line length for darker/isort etc., if not defined in .editorconfig', -) -@click.option( - '--darker-prefixes', - default=FORMAT_PY_FILE_DARKER_PRE_FIXES, - show_default=True, - help='Apply prefixes via autopep8 before calling darker.', -) -@click.option( - '--remove-all-unused-imports', - help='Remove all unused imports (not just those from the standard library) via autoflake', - **OPTION_ARGS_DEFAULT_TRUE, -) -@click.argument('file_path', **ARGUMENT_EXISTING_FILE) +@app.command def format_file( - *, - py_version: str, - max_line_length: int, - darker_prefixes: str, - remove_all_unused_imports: bool, file_path: Path, + /, + verbosity: TyroVerbosityArgType, + py_version: Annotated[ + str, + arg(help='Fallback Python version for darker/pyupgrade, if version is not defined in pyproject.toml'), + ] = FORMAT_PY_FILE_DEFAULT_MIN_PYTHON_VERSION, + max_line_length: Annotated[ + int, + arg(help='Fallback max. line length for darker/isort etc., if not defined in .editorconfig'), + ] = FORMAT_PY_FILE_DEFAULT_MAX_LINE_LENGTH, + darker_prefixes: Annotated[ + str, + arg(help='Apply prefixes via autopep8 before calling darker.'), + ] = FORMAT_PY_FILE_DARKER_PRE_FIXES, + remove_all_unused_imports: Annotated[ + bool, + arg(help='Remove all unused imports (not just those from the standard library) via autoflake'), + ] = True, ): """ Format and check the given python source code file with darker/autoflake/isort/pyupgrade/autopep8/mypy etc. @@ -367,6 +314,7 @@ def format_file( The optional fallback values will be only used, if we can't get them from the project meta files like ".editorconfig" and "pyproject.toml" """ + log_config(verbosity=verbosity, log_in_file=False) format_one_file( default_min_py_version=py_version, default_max_line_length=max_line_length, @@ -376,29 +324,8 @@ def format_file( ) -cli.add_command(format_file) - - -@cli.command() +@app.command def version(): """Print version and exit""" # Pseudo command, because the version always printed on every CLI call ;) sys.exit(0) - - -cli.add_command(version) - - -def main(): - print_version(manageprojects) - console = Console() - rich_traceback_install( - width=console.size.width, # full terminal width - show_locals=True, - suppress=[click], - max_frames=2, - ) - - # Execute Click CLI: - cli.name = './cli.py' - cli() diff --git a/manageprojects/cli_app/update_readme_history.py b/manageprojects/cli_app/update_readme_history.py index 922f9b0..8024096 100644 --- a/manageprojects/cli_app/update_readme_history.py +++ b/manageprojects/cli_app/update_readme_history.py @@ -1,16 +1,20 @@ +import logging import sys +from pathlib import Path -import rich_click as click from cli_base.cli_tools import git_history -from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE, setup_logging +from cli_base.cli_tools.verbosity import setup_logging +from cli_base.tyro_commands import TyroVerbosityArgType from rich import print # noqa -from manageprojects.cli_app import cli +from manageprojects.cli_app import app -@cli.command() -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def update_readme_history(verbosity: int): +logger = logging.getLogger(__name__) + + +@app.command +def update_readme_history(verbosity: TyroVerbosityArgType): """ Update project history base on git commits/tags in README.md @@ -20,6 +24,8 @@ def update_readme_history(verbosity: int): python -m cli_base update-readme-history -v """ setup_logging(verbosity=verbosity) + + logger.debug('%s called. CWD: %s', __name__, Path.cwd()) updated = git_history.update_readme_history(verbosity=verbosity) exit_code = 1 if updated else 0 if verbosity: diff --git a/manageprojects/cli_dev/__init__.py b/manageprojects/cli_dev/__init__.py index 531afc7..7a725ae 100644 --- a/manageprojects/cli_dev/__init__.py +++ b/manageprojects/cli_dev/__init__.py @@ -2,18 +2,17 @@ CLI for development """ +import importlib import logging import sys -import rich_click as click from bx_py_utils.path import assert_is_file from cli_base.autodiscover import import_all_files from cli_base.cli_tools.dev_tools import run_coverage, run_tox, run_unittest_cli +from cli_base.cli_tools.rich_utils import rich_traceback_install from cli_base.cli_tools.version_info import print_version -from rich.console import Console -from rich.traceback import install as rich_traceback_install -from rich_click import RichGroup from typeguard import install_import_hook +from tyro.extras import SubcommandApp import manageprojects from manageprojects import constants @@ -23,6 +22,9 @@ # Sadly we must activate this here and can't do this in ./tests/__init__.py install_import_hook(packages=('manageprojects',)) +# reload the module, after the typeguard import hook is activated: +importlib.reload(manageprojects) + logger = logging.getLogger(__name__) @@ -31,25 +33,14 @@ assert_is_file(PACKAGE_ROOT / 'pyproject.toml') # Exists only in cloned git repo -class ClickGroup(RichGroup): # FIXME: How to set the "info_name" easier? - def make_context(self, info_name, *args, **kwargs): - info_name = './dev-cli.py' - return super().make_context(info_name, *args, **kwargs) - - -@click.group( - cls=ClickGroup, - epilog=constants.CLI_EPILOG, -) -def cli(): - pass +app = SubcommandApp() -# Register all click commands, just by import all files in this package: +# Register all CLI commands, just by import all files in this package: import_all_files(package=__package__, init_file=__file__) -@cli.command() +@app.command def version(): """Print version and exit""" # Pseudo command, because the version always printed on every CLI call ;) @@ -59,13 +50,7 @@ def version(): def main(): print_version(manageprojects) - console = Console() - rich_traceback_install( - width=console.size.width, # full terminal width - show_locals=True, - suppress=[click], - max_frames=2, - ) + rich_traceback_install() if len(sys.argv) >= 2: # Check if we can just pass a command call to origin CLI: @@ -78,5 +63,12 @@ def main(): if real_func := command_map.get(command): real_func(argv=sys.argv, exit_after_run=True) - # Execute Click CLI: - cli() + # Work-a-round for: https://github.com/brentyi/tyro/issues/205 + app._subcommands = {k.replace('_', '-'): v for k, v in app._subcommands.items()} + + app.cli( + prog='./dev-cli.py', + description=constants.CLI_EPILOG, + use_underscores=False, # use hyphens instead of underscores + sort_subcommands=True, + ) diff --git a/manageprojects/cli_dev/code_style.py b/manageprojects/cli_dev/code_style.py index 01bf7a0..959949e 100644 --- a/manageprojects/cli_dev/code_style.py +++ b/manageprojects/cli_dev/code_style.py @@ -1,25 +1,19 @@ -import rich_click as click from cli_base.cli_tools import code_style -from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE -from cli_base.click_defaults import OPTION_ARGS_DEFAULT_TRUE +from cli_base.tyro_commands import TyroVerbosityArgType -from manageprojects.cli_dev import PACKAGE_ROOT, cli +from manageprojects.cli_dev import PACKAGE_ROOT, app -@cli.command() -@click.option('--color/--no-color', **OPTION_ARGS_DEFAULT_TRUE) -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def fix_code_style(color: bool, verbosity: int): +@app.command +def fix_code_style(verbosity: TyroVerbosityArgType, color: bool = True): """ Fix code style of all manageprojects source code files via darker """ code_style.fix(package_root=PACKAGE_ROOT, darker_color=color, darker_verbose=verbosity > 0) -@cli.command() -@click.option('--color/--no-color', **OPTION_ARGS_DEFAULT_TRUE) -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def check_code_style(color: bool, verbosity: int): +@app.command +def check_code_style(verbosity: TyroVerbosityArgType, color: bool = True): """ Check code style by calling darker + flake8 """ diff --git a/manageprojects/cli_dev/git_hooks.py b/manageprojects/cli_dev/git_hooks.py index 01be66a..3951bc0 100644 --- a/manageprojects/cli_dev/git_hooks.py +++ b/manageprojects/cli_dev/git_hooks.py @@ -1,8 +1,10 @@ -from manageprojects.cli_dev import PACKAGE_ROOT, cli +import dataclasses + +from manageprojects.cli_dev import PACKAGE_ROOT, app from manageprojects.format_file import ToolsExecutor -@cli.command() +@app.command def git_hooks(): """ Setup our "pre-commit" git hooks @@ -11,10 +13,13 @@ def git_hooks(): executor.verbose_check_call('pre-commit', 'install') -@cli.command() +@app.command def run_git_hooks(): """ Run the installed "pre-commit" git hooks """ executor = ToolsExecutor(cwd=PACKAGE_ROOT) executor.verbose_check_call('pre-commit', 'run', '--verbose', exit_on_error=True) + + + diff --git a/manageprojects/cli_dev/packaging.py b/manageprojects/cli_dev/packaging.py index 43c5f6e..e29a1cd 100644 --- a/manageprojects/cli_dev/packaging.py +++ b/manageprojects/cli_dev/packaging.py @@ -1,21 +1,20 @@ import logging -import tempfile -import click -from bx_py_utils.pyproject_toml import get_pyproject_config from cli_base.cli_tools.dev_tools import run_unittest_cli from cli_base.cli_tools.subprocess_utils import ToolsExecutor -from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE, setup_logging +from cli_base.cli_tools.verbosity import setup_logging +from cli_base.run_pip_audit import run_pip_audit +from cli_base.tyro_commands import TyroVerbosityArgType +from manageprojects.utilities.publish import publish_package import manageprojects -from manageprojects.cli_dev import PACKAGE_ROOT, cli -from manageprojects.utilities.publish import publish_package +from manageprojects.cli_dev import PACKAGE_ROOT, app logger = logging.getLogger(__name__) -@cli.command() +@app.command def install(): """ Install requirements and 'manageprojects' via pip as editable. @@ -25,55 +24,17 @@ def install(): tools_executor.verbose_check_call('pip', 'install', '--no-deps', '-e', '.') -def run_pip_audit(verbosity: int): - tools_executor = ToolsExecutor(cwd=PACKAGE_ROOT) - - with tempfile.NamedTemporaryFile(prefix='requirements', suffix='.txt') as temp_file: - tools_executor.verbose_check_call( - 'uv', - 'export', - '--no-header', - '--frozen', - '--no-editable', - '--no-emit-project', - '-o', - temp_file.name, - ) - - config: dict = get_pyproject_config( - section=('tool', 'cli_base', 'pip_audit'), - base_path=PACKAGE_ROOT, - ) - logger.debug('pip_audit config: %r', config) - assert isinstance(config, dict), f'Expected a dict: {config=}' - - popenargs = ['pip-audit', '--strict', '--require-hashes'] - - if verbosity: - popenargs.append(f'-{"v" * verbosity}') - - for vulnerability_id in config.get('ignore-vuln', []): - popenargs.extend(['--ignore-vuln', vulnerability_id]) - - popenargs.extend(['-r', temp_file.name]) - - logger.debug('pip_audit args: %s', popenargs) - tools_executor.verbose_check_call(*popenargs) - - -@cli.command() -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def pip_audit(verbosity: int): +@app.command +def pip_audit(verbosity: TyroVerbosityArgType): """ Run pip-audit check against current requirements files """ setup_logging(verbosity=verbosity) - run_pip_audit(verbosity=verbosity) + run_pip_audit(base_path=PACKAGE_ROOT, verbosity=verbosity) -@cli.command() -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def update(verbosity: int): +@app.command +def update(verbosity: TyroVerbosityArgType): """ Update "requirements*.txt" dependencies files """ @@ -85,7 +46,7 @@ def update(verbosity: int): tools_executor.verbose_check_call('pip', 'install', '-U', 'uv') tools_executor.verbose_check_call('uv', 'lock', '--upgrade') - run_pip_audit(verbosity=verbosity) + run_pip_audit(base_path=PACKAGE_ROOT, verbosity=verbosity) # Install new dependencies in current .venv: tools_executor.verbose_check_call('uv', 'sync') @@ -94,7 +55,7 @@ def update(verbosity: int): tools_executor.verbose_check_call('pre-commit', 'autoupdate') -@cli.command() +@app.command def publish(): """ Build and upload this project to PyPi diff --git a/manageprojects/cli_dev/testing.py b/manageprojects/cli_dev/testing.py index 62437eb..5199150 100644 --- a/manageprojects/cli_dev/testing.py +++ b/manageprojects/cli_dev/testing.py @@ -1,26 +1,22 @@ -import rich_click as click from cli_base.cli_tools.dev_tools import run_coverage, run_tox, run_unittest_cli from cli_base.cli_tools.subprocess_utils import verbose_check_call from cli_base.cli_tools.test_utils.snapshot import UpdateTestSnapshotFiles -from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE +from cli_base.tyro_commands import TyroVerbosityArgType -from manageprojects.cli_dev import PACKAGE_ROOT, cli +from manageprojects.cli_dev import PACKAGE_ROOT, app -@cli.command() -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def mypy(verbosity: int): +@app.command +def mypy(verbosity: TyroVerbosityArgType): """Run Mypy (configured in pyproject.toml)""" verbose_check_call('mypy', '.', cwd=PACKAGE_ROOT, verbose=verbosity > 0, exit_on_error=True) -@cli.command() -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def update_test_snapshot_files(verbosity: int): +@app.command +def update_test_snapshot_files(verbosity: TyroVerbosityArgType): """ Update all test snapshot files (by remove and recreate all snapshot files) """ - with UpdateTestSnapshotFiles(root_path=PACKAGE_ROOT, verbose=verbosity > 0): # Just recreate them by running tests: run_unittest_cli( @@ -32,7 +28,7 @@ def update_test_snapshot_files(verbosity: int): ) -@cli.command() # Dummy command +@app.command # Dummy command def test(): """ Run unittests @@ -40,7 +36,7 @@ def test(): run_unittest_cli() -@cli.command() # Dummy command +@app.command # Dummy command def coverage(): """ Run tests and show coverage report. @@ -48,7 +44,7 @@ def coverage(): run_coverage() -@cli.command() # Dummy "tox" command +@app.command # Dummy "tox" command def tox(): """ Run tox diff --git a/manageprojects/cli_dev/update_readme_history.py b/manageprojects/cli_dev/update_readme_history.py index b49765c..daa17e6 100644 --- a/manageprojects/cli_dev/update_readme_history.py +++ b/manageprojects/cli_dev/update_readme_history.py @@ -1,16 +1,16 @@ import sys -import rich_click as click + from cli_base.cli_tools import git_history from cli_base.cli_tools.verbosity import OPTION_KWARGS_VERBOSE, setup_logging +from cli_base.tyro_commands import TyroVerbosityArgType from rich import print # noqa -from manageprojects.cli_dev import cli +from manageprojects.cli_dev import app -@cli.command() -@click.option('-v', '--verbosity', **OPTION_KWARGS_VERBOSE) -def update_readme_history(verbosity: int): +@app.command +def update_readme_history(verbosity: TyroVerbosityArgType): """ Update project history base on git commits/tags in README.md diff --git a/manageprojects/tests/test_readme.py b/manageprojects/tests/test_readme.py index d8bf7c4..e81a82a 100644 --- a/manageprojects/tests/test_readme.py +++ b/manageprojects/tests/test_readme.py @@ -1,12 +1,10 @@ from bx_py_utils.auto_doc import assert_readme_block from bx_py_utils.path import assert_is_file +from cli_base.cli_tools.test_utils.rich_test_utils import NoColorRichClickCli +from manageprojects.tests.base import BaseTestCase from manageprojects import constants -from manageprojects.cli_app import cli from manageprojects.cli_dev import PACKAGE_ROOT -from manageprojects.cli_dev import cli as dev_cli -from manageprojects.test_utils.click_cli_utils import invoke_click -from manageprojects.tests.base import BaseTestCase def assert_cli_help_in_readme(text_block: str, marker: str): @@ -24,25 +22,27 @@ def assert_cli_help_in_readme(text_block: str, marker: str): class ReadmeTestCase(BaseTestCase): + def test_main_help(self): - stdout = invoke_click(cli, '--help') + with NoColorRichClickCli() as cm: + stdout = cm.invoke(cli_bin=PACKAGE_ROOT / 'cli.py', args=['--help'], strip_line_prefix='usage: ') self.assert_in_content( got=stdout, parts=( - 'Usage: ./cli.py [OPTIONS] COMMAND [ARGS]...', - ' start-project ', - ' update-project ', + 'usage: ./cli.py [-h]', + ' update-readme-history ', constants.CLI_EPILOG, ), ) assert_cli_help_in_readme(text_block=stdout, marker='main help') def test_dev_help(self): - stdout = invoke_click(dev_cli, '--help') + with NoColorRichClickCli() as cm: + stdout = cm.invoke(cli_bin=PACKAGE_ROOT / 'dev-cli.py', args=['--help'], strip_line_prefix='usage: ') self.assert_in_content( got=stdout, parts=( - 'Usage: ./dev-cli.py [OPTIONS] COMMAND [ARGS]...', + 'usage: ./dev-cli.py [-h]', ' check-code-style ', ' coverage ', constants.CLI_EPILOG, diff --git a/manageprojects/utilities/log_utils.py b/manageprojects/utilities/log_utils.py index fa1efe8..48430ab 100644 --- a/manageprojects/utilities/log_utils.py +++ b/manageprojects/utilities/log_utils.py @@ -3,6 +3,8 @@ import tempfile from bx_py_utils.test_utils.log_utils import RaiseLogUsage +from cli_base.tyro_commands import TyroVerbosityArgType +from rich import get_console def logger_setup(*, logger_name, level, format, log_filename, raise_log_output): @@ -28,11 +30,22 @@ def print_log_info(filename): def log_config( - level=logging.DEBUG, - format='%(asctime)s %(levelname)s %(name)s.%(funcName)s %(lineno)d | %(message)s', - log_in_file=True, + verbosity: TyroVerbosityArgType, + log_in_file=False, raise_log_output=False, ): + log_format = '%(message)s' + if verbosity == 0: + level = logging.ERROR + elif verbosity == 1: + level = logging.WARNING + elif verbosity == 2: + level = logging.INFO + log_format = '(%(name)s) %(message)s' + else: + level = logging.DEBUG + log_format = '%(asctime)s %(levelname)s %(name)s.%(funcName)s %(lineno)d | %(message)s' + if log_in_file: log_file = tempfile.NamedTemporaryFile( prefix='manageprojects_', suffix='.log', delete=False @@ -41,17 +54,20 @@ def log_config( else: log_filename = None + console = get_console() + console.print(f'(Set log level {verbosity}: {logging.getLevelName(level)})', justify='right') + logger_setup( logger_name='manageprojects', level=level, - format=format, + format=log_format, log_filename=log_filename, raise_log_output=raise_log_output, ) logger_setup( logger_name='cookiecutter', level=level, - format=format, + format=log_format, log_filename=log_filename, raise_log_output=raise_log_output, ) diff --git a/pyproject.toml b/pyproject.toml index 9e05f7b..5a6e185 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -30,8 +30,7 @@ dependencies = [ "mypy", # https://github.com/python/mypy "cli-base-utilities", # https://github.com/jedie/cli-base-utilities - "click", # https://github.com/pallets/click/ - "rich-click", # https://github.com/ewels/rich-click + "tyro", # https://github.com/brentyi/tyro "rich", # https://github.com/Textualize/rich ] @@ -205,6 +204,7 @@ applied_migrations = [ "2cdc1d8", # 2024-08-25T19:00:41+02:00 "56c3caa", # 2024-09-22T16:52:30+02:00 "ff48b81", # 2024-11-09T19:08:01+01:00 + "690a4fb", # 2024-11-21T18:54:44+01:00 ] [manageprojects.cookiecutter_context.cookiecutter] diff --git a/uv.lock b/uv.lock index 90ff0c7..09bcf93 100644 --- a/uv.lock +++ b/uv.lock @@ -130,11 +130,11 @@ wheels = [ [[package]] name = "bx-py-utils" -version = "105" +version = "106" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/f7/c3/4949fd3031a26eaf7378befacc5a2858d68a4e328b342e2ffc4c321c9a89/bx_py_utils-105.tar.gz", hash = "sha256:1bb7c1401147df35a95ca78c1de9f25d104aeda941a5cc89f9cfc2d1616ddbd7", size = 192317 } +sdist = { url = "https://files.pythonhosted.org/packages/07/97/25d9c34122d4d9a33383c8b265a0bd9f5391f18a7ae9aa65c61877941649/bx_py_utils-106.tar.gz", hash = "sha256:26d6d3353ccd7d93ae322d33f8dde1b14d01b88f10329a714cd43da67b2e3d9f", size = 192712 } wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/e5/da929891157b56f7a9bf825118926910e5e3629eb1cd3ec441d292e7501c/bx_py_utils-105-py3-none-any.whl", hash = "sha256:d441b0e413f8b19b03ab1784187ca2cf2ec5b68d64082790bdbca16a4612cb3e", size = 175660 }, + { url = "https://files.pythonhosted.org/packages/0c/75/297e15764b5e46259ef68ed3deef98413a3ae038512a468e36623b41d13e/bx_py_utils-106-py3-none-any.whl", hash = "sha256:1b5e7622310c5ef814de241419bc0f0929c3d0445e1418fa477d2be3f7da0332", size = 176056 }, ] [[package]] @@ -280,7 +280,7 @@ wheels = [ [[package]] name = "cli-base-utilities" -version = "0.13.1" +version = "0.14.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "bx-py-utils" }, @@ -291,9 +291,9 @@ dependencies = [ { name = "tomlkit" }, { name = "tyro" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/c1/77/6b8ee5ca3a0e7ea726d41664cf6fb881a8d481d15e633563b3711f67335c/cli_base_utilities-0.13.1.tar.gz", hash = "sha256:a0142b46ced685fda8e7393c90d2cb1a709ea7ae37469249e3f519bd8c7844e2", size = 101509 } +sdist = { url = "https://files.pythonhosted.org/packages/94/6e/ec1348f37a84d4f63499c42c24363677f16c859740b9625b7f74bc64f0c3/cli_base_utilities-0.14.0.tar.gz", hash = "sha256:2c2c41db60e978fd7ef82ec82e4ec19870a2965310cb0f4d894319c8100109bc", size = 116523 } wheels = [ - { url = "https://files.pythonhosted.org/packages/fe/1b/be59924db1af6d7c2ca9d36d0f2586ac7acfc9f81d18f57f742832e34481/cli_base_utilities-0.13.1-py3-none-any.whl", hash = "sha256:abb265fee788af0e347395bd9c863370df04ddc6b8aff97e77841c994f5daee6", size = 82447 }, + { url = "https://files.pythonhosted.org/packages/50/62/69731ae4a952f8bb2571e13fd2787532b4eba307f9abf5622f08d5a31a33/cli_base_utilities-0.14.0-py3-none-any.whl", hash = "sha256:9168ab86cb61afe3885dc97d4522a1a349b9e6fc16ba2955c2de787f577c950d", size = 82590 }, ] [[package]] @@ -347,50 +347,50 @@ wheels = [ [[package]] name = "coverage" -version = "7.6.4" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/52/12/3669b6382792783e92046730ad3327f53b2726f0603f4c311c4da4824222/coverage-7.6.4.tar.gz", hash = "sha256:29fc0f17b1d3fea332f8001d4558f8214af7f1d87a345f3a133c901d60347c73", size = 798716 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/87/31/9c0cf84f0dfcbe4215b7eb95c31777cdc0483c13390e69584c8150c85175/coverage-7.6.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:73d2b73584446e66ee633eaad1a56aad577c077f46c35ca3283cd687b7715b0b", size = 206819 }, - { url = "https://files.pythonhosted.org/packages/53/ed/a38401079ad320ad6e054a01ec2b61d270511aeb3c201c80e99c841229d5/coverage-7.6.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:51b44306032045b383a7a8a2c13878de375117946d68dcb54308111f39775a25", size = 207263 }, - { url = "https://files.pythonhosted.org/packages/20/e7/c3ad33b179ab4213f0d70da25a9c214d52464efa11caeab438592eb1d837/coverage-7.6.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0b3fb02fe73bed561fa12d279a417b432e5b50fe03e8d663d61b3d5990f29546", size = 239205 }, - { url = "https://files.pythonhosted.org/packages/36/91/fc02e8d8e694f557752120487fd982f654ba1421bbaa5560debf96ddceda/coverage-7.6.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed8fe9189d2beb6edc14d3ad19800626e1d9f2d975e436f84e19efb7fa19469b", size = 236612 }, - { url = "https://files.pythonhosted.org/packages/cc/57/cb08f0eda0389a9a8aaa4fc1f9fec7ac361c3e2d68efd5890d7042c18aa3/coverage-7.6.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b369ead6527d025a0fe7bd3864e46dbee3aa8f652d48df6174f8d0bac9e26e0e", size = 238479 }, - { url = "https://files.pythonhosted.org/packages/d5/c9/2c7681a9b3ca6e6f43d489c2e6653a53278ed857fd6e7010490c307b0a47/coverage-7.6.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ade3ca1e5f0ff46b678b66201f7ff477e8fa11fb537f3b55c3f0568fbfe6e718", size = 237405 }, - { url = "https://files.pythonhosted.org/packages/b5/4e/ebfc6944b96317df8b537ae875d2e57c27b84eb98820bc0a1055f358f056/coverage-7.6.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:27fb4a050aaf18772db513091c9c13f6cb94ed40eacdef8dad8411d92d9992db", size = 236038 }, - { url = "https://files.pythonhosted.org/packages/13/f2/3a0bf1841a97c0654905e2ef531170f02c89fad2555879db8fe41a097871/coverage-7.6.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4f704f0998911abf728a7783799444fcbbe8261c4a6c166f667937ae6a8aa522", size = 236812 }, - { url = "https://files.pythonhosted.org/packages/b9/9c/66bf59226b52ce6ed9541b02d33e80a6e816a832558fbdc1111a7bd3abd4/coverage-7.6.4-cp311-cp311-win32.whl", hash = "sha256:29155cd511ee058e260db648b6182c419422a0d2e9a4fa44501898cf918866cf", size = 209400 }, - { url = "https://files.pythonhosted.org/packages/2a/a0/b0790934c04dfc8d658d4a62acb8f7ca0efdf3818456fcad757b11c6479d/coverage-7.6.4-cp311-cp311-win_amd64.whl", hash = "sha256:8902dd6a30173d4ef09954bfcb24b5d7b5190cf14a43170e386979651e09ba19", size = 210243 }, - { url = "https://files.pythonhosted.org/packages/7d/e7/9291de916d084f41adddfd4b82246e68d61d6a75747f075f7e64628998d2/coverage-7.6.4-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:12394842a3a8affa3ba62b0d4ab7e9e210c5e366fbac3e8b2a68636fb19892c2", size = 207013 }, - { url = "https://files.pythonhosted.org/packages/27/03/932c2c5717a7fa80cd43c6a07d3177076d97b79f12f40f882f9916db0063/coverage-7.6.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2b6b4c83d8e8ea79f27ab80778c19bc037759aea298da4b56621f4474ffeb117", size = 207251 }, - { url = "https://files.pythonhosted.org/packages/d5/3f/0af47dcb9327f65a45455fbca846fe96eb57c153af46c4754a3ba678938a/coverage-7.6.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d5b8007f81b88696d06f7df0cb9af0d3b835fe0c8dbf489bad70b45f0e45613", size = 240268 }, - { url = "https://files.pythonhosted.org/packages/8a/3c/37a9d81bbd4b23bc7d46ca820e16174c613579c66342faa390a271d2e18b/coverage-7.6.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b57b768feb866f44eeed9f46975f3d6406380275c5ddfe22f531a2bf187eda27", size = 237298 }, - { url = "https://files.pythonhosted.org/packages/c0/70/6b0627e5bd68204ee580126ed3513140b2298995c1233bd67404b4e44d0e/coverage-7.6.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5915fcdec0e54ee229926868e9b08586376cae1f5faa9bbaf8faf3561b393d52", size = 239367 }, - { url = "https://files.pythonhosted.org/packages/3c/eb/634d7dfab24ac3b790bebaf9da0f4a5352cbc125ce6a9d5c6cf4c6cae3c7/coverage-7.6.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0b58c672d14f16ed92a48db984612f5ce3836ae7d72cdd161001cc54512571f2", size = 238853 }, - { url = "https://files.pythonhosted.org/packages/d9/0d/8e3ed00f1266ef7472a4e33458f42e39492e01a64281084fb3043553d3f1/coverage-7.6.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:2fdef0d83a2d08d69b1f2210a93c416d54e14d9eb398f6ab2f0a209433db19e1", size = 237160 }, - { url = "https://files.pythonhosted.org/packages/ce/9c/4337f468ef0ab7a2e0887a9c9da0e58e2eada6fc6cbee637a4acd5dfd8a9/coverage-7.6.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cf717ee42012be8c0cb205dbbf18ffa9003c4cbf4ad078db47b95e10748eec5", size = 238824 }, - { url = "https://files.pythonhosted.org/packages/5e/09/3e94912b8dd37251377bb02727a33a67ee96b84bbbe092f132b401ca5dd9/coverage-7.6.4-cp312-cp312-win32.whl", hash = "sha256:7bb92c539a624cf86296dd0c68cd5cc286c9eef2d0c3b8b192b604ce9de20a17", size = 209639 }, - { url = "https://files.pythonhosted.org/packages/01/69/d4f3a4101171f32bc5b3caec8ff94c2c60f700107a6aaef7244b2c166793/coverage-7.6.4-cp312-cp312-win_amd64.whl", hash = "sha256:1032e178b76a4e2b5b32e19d0fd0abbce4b58e77a1ca695820d10e491fa32b08", size = 210428 }, - { url = "https://files.pythonhosted.org/packages/c2/4d/2dede4f7cb5a70fb0bb40a57627fddf1dbdc6b9c1db81f7c4dcdcb19e2f4/coverage-7.6.4-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:023bf8ee3ec6d35af9c1c6ccc1d18fa69afa1cb29eaac57cb064dbb262a517f9", size = 207039 }, - { url = "https://files.pythonhosted.org/packages/3f/f9/d86368ae8c79e28f1fb458ebc76ae9ff3e8bd8069adc24e8f2fed03c58b7/coverage-7.6.4-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b0ac3d42cb51c4b12df9c5f0dd2f13a4f24f01943627120ec4d293c9181219ba", size = 207298 }, - { url = "https://files.pythonhosted.org/packages/64/c5/b4cc3c3f64622c58fbfd4d8b9a7a8ce9d355f172f91fcabbba1f026852f6/coverage-7.6.4-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8fe4984b431f8621ca53d9380901f62bfb54ff759a1348cd140490ada7b693c", size = 239813 }, - { url = "https://files.pythonhosted.org/packages/8a/86/14c42e60b70a79b26099e4d289ccdfefbc68624d096f4481163085aa614c/coverage-7.6.4-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5fbd612f8a091954a0c8dd4c0b571b973487277d26476f8480bfa4b2a65b5d06", size = 236959 }, - { url = "https://files.pythonhosted.org/packages/7f/f8/4436a643631a2fbab4b44d54f515028f6099bfb1cd95b13cfbf701e7f2f2/coverage-7.6.4-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dacbc52de979f2823a819571f2e3a350a7e36b8cb7484cdb1e289bceaf35305f", size = 238950 }, - { url = "https://files.pythonhosted.org/packages/49/50/1571810ddd01f99a0a8be464a4ac8b147f322cd1e8e296a1528984fc560b/coverage-7.6.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:dab4d16dfef34b185032580e2f2f89253d302facba093d5fa9dbe04f569c4f4b", size = 238610 }, - { url = "https://files.pythonhosted.org/packages/f3/8c/6312d241fe7cbd1f0cade34a62fea6f333d1a261255d76b9a87074d8703c/coverage-7.6.4-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:862264b12ebb65ad8d863d51f17758b1684560b66ab02770d4f0baf2ff75da21", size = 236697 }, - { url = "https://files.pythonhosted.org/packages/ce/5f/fef33dfd05d87ee9030f614c857deb6df6556b8f6a1c51bbbb41e24ee5ac/coverage-7.6.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5beb1ee382ad32afe424097de57134175fea3faf847b9af002cc7895be4e2a5a", size = 238541 }, - { url = "https://files.pythonhosted.org/packages/a9/64/6a984b6e92e1ea1353b7ffa08e27f707a5e29b044622445859200f541e8c/coverage-7.6.4-cp313-cp313-win32.whl", hash = "sha256:bf20494da9653f6410213424f5f8ad0ed885e01f7e8e59811f572bdb20b8972e", size = 209707 }, - { url = "https://files.pythonhosted.org/packages/5c/60/ce5a9e942e9543783b3db5d942e0578b391c25cdd5e7f342d854ea83d6b7/coverage-7.6.4-cp313-cp313-win_amd64.whl", hash = "sha256:182e6cd5c040cec0a1c8d415a87b67ed01193ed9ad458ee427741c7d8513d963", size = 210439 }, - { url = "https://files.pythonhosted.org/packages/78/53/6719677e92c308207e7f10561a1b16ab8b5c00e9328efc9af7cfd6fb703e/coverage-7.6.4-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:a181e99301a0ae128493a24cfe5cfb5b488c4e0bf2f8702091473d033494d04f", size = 207784 }, - { url = "https://files.pythonhosted.org/packages/fa/dd/7054928930671fcb39ae6a83bb71d9ab5f0afb733172543ced4b09a115ca/coverage-7.6.4-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:df57bdbeffe694e7842092c5e2e0bc80fff7f43379d465f932ef36f027179806", size = 208058 }, - { url = "https://files.pythonhosted.org/packages/b5/7d/fd656ddc2b38301927b9eb3aae3fe827e7aa82e691923ed43721fd9423c9/coverage-7.6.4-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0bcd1069e710600e8e4cf27f65c90c7843fa8edfb4520fb0ccb88894cad08b11", size = 250772 }, - { url = "https://files.pythonhosted.org/packages/90/d0/eb9a3cc2100b83064bb086f18aedde3afffd7de6ead28f69736c00b7f302/coverage-7.6.4-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:99b41d18e6b2a48ba949418db48159d7a2e81c5cc290fc934b7d2380515bd0e3", size = 246490 }, - { url = "https://files.pythonhosted.org/packages/45/44/3f64f38f6faab8a0cfd2c6bc6eb4c6daead246b97cf5f8fc23bf3788f841/coverage-7.6.4-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1e54712ba3474f34b7ef7a41e65bd9037ad47916ccb1cc78769bae324c01a", size = 248848 }, - { url = "https://files.pythonhosted.org/packages/5d/11/4c465a5f98656821e499f4b4619929bd5a34639c466021740ecdca42aa30/coverage-7.6.4-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:53d202fd109416ce011578f321460795abfe10bb901b883cafd9b3ef851bacfc", size = 248340 }, - { url = "https://files.pythonhosted.org/packages/f1/96/ebecda2d016cce9da812f404f720ca5df83c6b29f65dc80d2000d0078741/coverage-7.6.4-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:c48167910a8f644671de9f2083a23630fbf7a1cb70ce939440cd3328e0919f70", size = 246229 }, - { url = "https://files.pythonhosted.org/packages/16/d9/3d820c00066ae55d69e6d0eae11d6149a5ca7546de469ba9d597f01bf2d7/coverage-7.6.4-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cc8ff50b50ce532de2fa7a7daae9dd12f0a699bfcd47f20945364e5c31799fef", size = 247510 }, - { url = "https://files.pythonhosted.org/packages/8f/c3/4fa1eb412bb288ff6bfcc163c11700ff06e02c5fad8513817186e460ed43/coverage-7.6.4-cp313-cp313t-win32.whl", hash = "sha256:b8d3a03d9bfcaf5b0141d07a88456bb6a4c3ce55c080712fec8418ef3610230e", size = 210353 }, - { url = "https://files.pythonhosted.org/packages/7e/77/03fc2979d1538884d921c2013075917fc927f41cd8526909852fe4494112/coverage-7.6.4-cp313-cp313t-win_amd64.whl", hash = "sha256:f3ddf056d3ebcf6ce47bdaf56142af51bb7fad09e4af310241e9db7a3a8022e1", size = 211502 }, +version = "7.6.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/bf/68/26895f8b068e384b1ec9ab122565b913b735e6b4c618b3d265a280607edc/coverage-7.6.7.tar.gz", hash = "sha256:d79d4826e41441c9a118ff045e4bccb9fdbdcb1d02413e7ea6eb5c87b5439d24", size = 799938 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c6/d7/1bf7bb0943237149ad01977190ac5c2e17add1f4fe7cabc06401682137f6/coverage-7.6.7-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7e61b0e77ff4dddebb35a0e8bb5a68bf0f8b872407d8d9f0c726b65dfabe2469", size = 206979 }, + { url = "https://files.pythonhosted.org/packages/83/eb/863b2cd654353b94c6ad834008df813424bf3e8f110e5f655fe5dc4c423b/coverage-7.6.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a5407a75ca4abc20d6252efeb238377a71ce7bda849c26c7a9bece8680a5d99", size = 207431 }, + { url = "https://files.pythonhosted.org/packages/35/c9/d7a02a9654c41174fb99402c0fbd9583d0d2cb8714e7f948117fa7f919c4/coverage-7.6.7-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df002e59f2d29e889c37abd0b9ee0d0e6e38c24f5f55d71ff0e09e3412a340ec", size = 239368 }, + { url = "https://files.pythonhosted.org/packages/11/64/6c43a0ec43e5ddc5e09b0b589e3fd31def05fc463920d084e5af35fe527d/coverage-7.6.7-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:673184b3156cba06154825f25af33baa2671ddae6343f23175764e65a8c4c30b", size = 236769 }, + { url = "https://files.pythonhosted.org/packages/1c/dc/e77d98ae433c556c29328712a07fed0e6d159a63b2ec81039ce0a13a24a3/coverage-7.6.7-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e69ad502f1a2243f739f5bd60565d14a278be58be4c137d90799f2c263e7049a", size = 238634 }, + { url = "https://files.pythonhosted.org/packages/cc/84/50df3a8426d686057496171b4ccdb64528dacc4f42e94dceb7de3c598a69/coverage-7.6.7-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:60dcf7605c50ea72a14490d0756daffef77a5be15ed1b9fea468b1c7bda1bc3b", size = 237562 }, + { url = "https://files.pythonhosted.org/packages/2e/0f/9560196247574c1ccdab64cb923d69119fd5abd5b3db28d601ab2b452861/coverage-7.6.7-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:9c2eb378bebb2c8f65befcb5147877fc1c9fbc640fc0aad3add759b5df79d55d", size = 236197 }, + { url = "https://files.pythonhosted.org/packages/df/14/38b7c081e86e845df1867143ddb6e05bf8395f60ab3923c023a56d97cca1/coverage-7.6.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:3c0317288f032221d35fa4cbc35d9f4923ff0dfd176c79c9b356e8ef8ef2dff4", size = 236970 }, + { url = "https://files.pythonhosted.org/packages/8b/f3/af34f814ca3814f798878ae368b638edb91298595470614f5265f3f416fa/coverage-7.6.7-cp311-cp311-win32.whl", hash = "sha256:951aade8297358f3618a6e0660dc74f6b52233c42089d28525749fc8267dccd2", size = 209557 }, + { url = "https://files.pythonhosted.org/packages/5a/9e/5d1080d83d752873bd9dedea5524c0f5fe68a3d5e1e58c590865bd724591/coverage-7.6.7-cp311-cp311-win_amd64.whl", hash = "sha256:5e444b8e88339a2a67ce07d41faabb1d60d1004820cee5a2c2b54e2d8e429a0f", size = 210402 }, + { url = "https://files.pythonhosted.org/packages/84/30/30e9df650b9038962c62d900b093a17414d5b43b4d07d47b8698d9e7ce26/coverage-7.6.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:f07ff574986bc3edb80e2c36391678a271d555f91fd1d332a1e0f4b5ea4b6ea9", size = 207172 }, + { url = "https://files.pythonhosted.org/packages/88/8b/e28f86412317b9514692fd6f9d8ac6faa12494c3f470c3c63f202e10c756/coverage-7.6.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:49ed5ee4109258973630c1f9d099c7e72c5c36605029f3a91fe9982c6076c82b", size = 207406 }, + { url = "https://files.pythonhosted.org/packages/ac/46/da1bd9a3a893f74f5ce85f35e2755fcb00a80ed21e18d300c54f64938b1c/coverage-7.6.7-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3e8796434a8106b3ac025fd15417315d7a58ee3e600ad4dbcfddc3f4b14342c", size = 240424 }, + { url = "https://files.pythonhosted.org/packages/f6/12/af8e932496de1997bf4a36785d025ddac6427cbaf6954f26c2edaf21a58a/coverage-7.6.7-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3b925300484a3294d1c70f6b2b810d6526f2929de954e5b6be2bf8caa1f12c1", size = 237456 }, + { url = "https://files.pythonhosted.org/packages/60/a2/23eb11eb60f825a84397cb94701d6f41d2e8e88ad7d0ba2b4339f38435fb/coverage-7.6.7-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c42ec2c522e3ddd683dec5cdce8e62817afb648caedad9da725001fa530d354", size = 239527 }, + { url = "https://files.pythonhosted.org/packages/47/9e/63b318bc469308a32b0fbd6c80e2ea05dd7a2b7e840a46b3974843083a8c/coverage-7.6.7-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:0266b62cbea568bd5e93a4da364d05de422110cbed5056d69339bd5af5685433", size = 239011 }, + { url = "https://files.pythonhosted.org/packages/99/47/1e84b067df3f021dfbc9cba09ec9acd4cb64938648a234e5bdf3006fd08b/coverage-7.6.7-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:e5f2a0f161d126ccc7038f1f3029184dbdf8f018230af17ef6fd6a707a5b881f", size = 237316 }, + { url = "https://files.pythonhosted.org/packages/12/9d/96baaafc948d4a0ef2248a611d41051eea0917ef881d744879dd20be7c4a/coverage-7.6.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c132b5a22821f9b143f87446805e13580b67c670a548b96da945a8f6b4f2efbb", size = 238980 }, + { url = "https://files.pythonhosted.org/packages/87/d9/97af1886ca3f612d0cea2999d33e90d2f5b8fdf9bedc2d3bc75883efec4c/coverage-7.6.7-cp312-cp312-win32.whl", hash = "sha256:7c07de0d2a110f02af30883cd7dddbe704887617d5c27cf373362667445a4c76", size = 209801 }, + { url = "https://files.pythonhosted.org/packages/f8/4d/1e31c2018b1b3738154639f94188b1f54098fbf0f80c7ec104928576d0bb/coverage-7.6.7-cp312-cp312-win_amd64.whl", hash = "sha256:fd49c01e5057a451c30c9b892948976f5d38f2cbd04dc556a82743ba8e27ed8c", size = 210587 }, + { url = "https://files.pythonhosted.org/packages/21/87/c590d0c7eeb884995d9d06b429c5e88e9fcd65d3a6a686d9476cb50b72a9/coverage-7.6.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:46f21663e358beae6b368429ffadf14ed0a329996248a847a4322fb2e35d64d3", size = 207199 }, + { url = "https://files.pythonhosted.org/packages/40/ee/c88473c4f69c952f4425fabe045cb78d2027634ce50c9d7f7987d389b604/coverage-7.6.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:40cca284c7c310d622a1677f105e8507441d1bb7c226f41978ba7c86979609ab", size = 207454 }, + { url = "https://files.pythonhosted.org/packages/b8/07/afda6e10c50e3a8c21020c5c1d1b4f3d7eff1c190305cef2962adf8de018/coverage-7.6.7-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77256ad2345c29fe59ae861aa11cfc74579c88d4e8dbf121cbe46b8e32aec808", size = 239971 }, + { url = "https://files.pythonhosted.org/packages/85/43/bd1934b75e31f2a49665be6a6b7f8bfaff7266ba19721bdb90239f5e9ed7/coverage-7.6.7-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:87ea64b9fa52bf395272e54020537990a28078478167ade6c61da7ac04dc14bc", size = 237119 }, + { url = "https://files.pythonhosted.org/packages/2b/19/7a70458c1624724086195b40628e91bc5b9ca180cdfefcc778285c49c7b2/coverage-7.6.7-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d608a7808793e3615e54e9267519351c3ae204a6d85764d8337bd95993581a8", size = 239109 }, + { url = "https://files.pythonhosted.org/packages/f3/2c/3dee671415ff13c05ca68243b2264fc95a5eea57697cffa7986b68b8f608/coverage-7.6.7-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdd94501d65adc5c24f8a1a0eda110452ba62b3f4aeaba01e021c1ed9cb8f34a", size = 238769 }, + { url = "https://files.pythonhosted.org/packages/37/ad/e0d1228638711aeacacc98d1197af6226b6d062d12c81a6bcc17d3234533/coverage-7.6.7-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:82c809a62e953867cf57e0548c2b8464207f5f3a6ff0e1e961683e79b89f2c55", size = 236854 }, + { url = "https://files.pythonhosted.org/packages/90/95/6467e9d9765a63c7f142703a7f212f6af114bd73a6c1cffeb7ad7f003a86/coverage-7.6.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bb684694e99d0b791a43e9fc0fa58efc15ec357ac48d25b619f207c41f2fd384", size = 238701 }, + { url = "https://files.pythonhosted.org/packages/b2/7a/fc11a163f0fd6ce8539d0f1b565873fe6903b900214ff71b5d80d16154c3/coverage-7.6.7-cp313-cp313-win32.whl", hash = "sha256:963e4a08cbb0af6623e61492c0ec4c0ec5c5cf74db5f6564f98248d27ee57d30", size = 209865 }, + { url = "https://files.pythonhosted.org/packages/f2/91/58be3a56efff0c3481e48e2caa56d5d6f3c5c8d385bf4adbecdfd85484b0/coverage-7.6.7-cp313-cp313-win_amd64.whl", hash = "sha256:14045b8bfd5909196a90da145a37f9d335a5d988a83db34e80f41e965fb7cb42", size = 210597 }, + { url = "https://files.pythonhosted.org/packages/34/7e/fed983809c2eccb09c5ddccfdb08efb7f2dd1ae3454dabf1c92c5a2e9946/coverage-7.6.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f2c7a045eef561e9544359a0bf5784b44e55cefc7261a20e730baa9220c83413", size = 207944 }, + { url = "https://files.pythonhosted.org/packages/c7/e0/2c1a157986a3927c3920e8e3938a3fdf33ea22b6f371dc3b679f13f619e2/coverage-7.6.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5dd4e4a49d9c72a38d18d641135d2fb0bdf7b726ca60a103836b3d00a1182acd", size = 208215 }, + { url = "https://files.pythonhosted.org/packages/35/2f/77b086b228f6443ae5499467d1629c7428925b390cd171350c403bc00f14/coverage-7.6.7-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c95e0fa3d1547cb6f021ab72f5c23402da2358beec0a8e6d19a368bd7b0fb37", size = 250930 }, + { url = "https://files.pythonhosted.org/packages/60/d8/2ffea937d89ee328fc6e47c2515b890735bdf3f195d507d1c78b5fa96939/coverage-7.6.7-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f63e21ed474edd23f7501f89b53280014436e383a14b9bd77a648366c81dce7b", size = 246647 }, + { url = "https://files.pythonhosted.org/packages/b2/81/efbb3b00a7f7eb5f54a3b3b9f19b26d770a0b7d3870d651f07d2451c5504/coverage-7.6.7-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ead9b9605c54d15be228687552916c89c9683c215370c4a44f1f217d2adcc34d", size = 249006 }, + { url = "https://files.pythonhosted.org/packages/eb/91/ce36990cbefaf7909e96c888ed4d83f3471fc1be3273a5beda10896cde0f/coverage-7.6.7-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:0573f5cbf39114270842d01872952d301027d2d6e2d84013f30966313cadb529", size = 248500 }, + { url = "https://files.pythonhosted.org/packages/75/3f/b8c87dfdd96276870fb4abc7e2957cba7d20d8a435fcd816d807869ec833/coverage-7.6.7-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:e2c8e3384c12dfa19fa9a52f23eb091a8fad93b5b81a41b14c17c78e23dd1d8b", size = 246388 }, + { url = "https://files.pythonhosted.org/packages/a0/51/62273e1d5c25bb8fbef5fbbadc75b4a3e08c11b80516d0a97c25e5cced5b/coverage-7.6.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:70a56a2ec1869e6e9fa69ef6b76b1a8a7ef709972b9cc473f9ce9d26b5997ce3", size = 247669 }, + { url = "https://files.pythonhosted.org/packages/75/e5/d7772e56a7eace80e98ac39f2756d4b690fc0ce2384418174e02519a26a8/coverage-7.6.7-cp313-cp313t-win32.whl", hash = "sha256:dbba8210f5067398b2c4d96b4e64d8fb943644d5eb70be0d989067c8ca40c0f8", size = 210510 }, + { url = "https://files.pythonhosted.org/packages/2d/12/f2666e4e36b43221391ffcd971ab0c50e19439c521c2c87cd7e0b49ddba2/coverage-7.6.7-cp313-cp313t-win_amd64.whl", hash = "sha256:dfd14bcae0c94004baba5184d1c935ae0d1231b8409eb6c103a5fd75e8ecdc56", size = 211660 }, ] [[package]] @@ -718,7 +718,6 @@ dependencies = [ { name = "autoflake" }, { name = "autopep8" }, { name = "cli-base-utilities" }, - { name = "click" }, { name = "codespell" }, { name = "cookiecutter" }, { name = "darker", extra = ["color", "flynt", "isort"] }, @@ -730,8 +729,8 @@ dependencies = [ { name = "pyupgrade" }, { name = "refurb" }, { name = "rich" }, - { name = "rich-click" }, { name = "tomlkit" }, + { name = "tyro" }, ] [package.dev-dependencies] @@ -766,7 +765,6 @@ requires-dist = [ { name = "autoflake" }, { name = "autopep8" }, { name = "cli-base-utilities" }, - { name = "click" }, { name = "codespell" }, { name = "cookiecutter", specifier = ">=2.4.0" }, { name = "darker", extras = ["color", "flynt", "isort"] }, @@ -778,8 +776,8 @@ requires-dist = [ { name = "pyupgrade" }, { name = "refurb" }, { name = "rich" }, - { name = "rich-click" }, { name = "tomlkit" }, + { name = "tyro" }, ] [package.metadata.requires-dev] @@ -1372,20 +1370,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/71/39c7c0d87f8d4e6c020a393182060eaefeeae6c01dab6a84ec346f2567df/rich-13.9.4-py3-none-any.whl", hash = "sha256:6049d5e6ec054bf2779ab3358186963bac2ea89175919d699e378b99738c2a90", size = 242424 }, ] -[[package]] -name = "rich-click" -version = "1.8.3" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "click" }, - { name = "rich" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/3a/a9/a1f1af87e83832d794342fbc09c96cc7cd6798b8dfb8adfbe6ccbef8d70c/rich_click-1.8.3.tar.gz", hash = "sha256:6d75bdfa7aa9ed2c467789a0688bc6da23fbe3a143e19aa6ad3f8bac113d2ab3", size = 38209 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/c6/ea/5a0c5a8e6532e971983d1b0fc99268eb66a10f489da35d9022ce01044191/rich_click-1.8.3-py3-none-any.whl", hash = "sha256:636d9c040d31c5eee242201b5bf4f2d358bfae4db14bb22ec1cafa717cfd02cd", size = 35032 }, -] - [[package]] name = "secretstorage" version = "3.3.3" @@ -1401,11 +1385,11 @@ wheels = [ [[package]] name = "setuptools" -version = "75.3.0" +version = "75.6.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/ed/22/a438e0caa4576f8c383fa4d35f1cc01655a46c75be358960d815bfbb12bd/setuptools-75.3.0.tar.gz", hash = "sha256:fba5dd4d766e97be1b1681d98712680ae8f2f26d7881245f2ce9e40714f1a686", size = 1351577 } +sdist = { url = "https://files.pythonhosted.org/packages/43/54/292f26c208734e9a7f067aea4a7e282c080750c4546559b58e2e45413ca0/setuptools-75.6.0.tar.gz", hash = "sha256:8199222558df7c86216af4f84c30e9b34a61d8ba19366cc914424cdbd28252f6", size = 1337429 } wheels = [ - { url = "https://files.pythonhosted.org/packages/90/12/282ee9bce8b58130cb762fbc9beabd531549952cac11fc56add11dcb7ea0/setuptools-75.3.0-py3-none-any.whl", hash = "sha256:f2504966861356aa38616760c0f66568e535562374995367b4e69c7143cf6bcd", size = 1251070 }, + { url = "https://files.pythonhosted.org/packages/55/21/47d163f615df1d30c094f6c8bbb353619274edccf0327b185cc2493c2c33/setuptools-75.6.0-py3-none-any.whl", hash = "sha256:ce74b49e8f7110f9bf04883b730f4765b774ef3ef28f722cce7c273d253aaf7d", size = 1224032 }, ] [[package]] @@ -1557,7 +1541,7 @@ wheels = [ [[package]] name = "tyro" -version = "0.8.14" +version = "0.9.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "colorama", marker = "platform_system == 'Windows'" }, @@ -1566,9 +1550,9 @@ dependencies = [ { name = "shtab" }, { name = "typing-extensions" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/91/9a/a471d988dd9ac8ea657714734c6834c056dad9928c270652c4f0e030a226/tyro-0.8.14.tar.gz", hash = "sha256:2516e34d21763575159459c3b15fe4a13472a2166dff32169c9d7aab70853058", size = 141970 } +sdist = { url = "https://files.pythonhosted.org/packages/0e/5f/1385156a44d47910e53c7fa91489ff0ac3b056abecf0690b3b67727d0d4a/tyro-0.9.1.tar.gz", hash = "sha256:05c6a2c6d0584b5605972ac563cd3d6afa75597f0f8ce9d32581ce43b9a0f927", size = 231128 } wheels = [ - { url = "https://files.pythonhosted.org/packages/60/ec/e34d546cfd9c5b906d1d534bb75557be9f2b179609d60bb9e97ec07e8ead/tyro-0.8.14-py3-none-any.whl", hash = "sha256:1904bffb0e4d5e16c5eb50c518c89a368a44d56405f79b316c58e1206c102e87", size = 109833 }, + { url = "https://files.pythonhosted.org/packages/99/0e/07035fc62731e10c887786f1d8a1dfb31bbe01bd55d34b21c1d75b50ed0e/tyro-0.9.1-py3-none-any.whl", hash = "sha256:656862e6c10a6df913e78abe98ddae3ae5c0015f4d9446266c9efbd3f0d6817b", size = 111932 }, ] [[package]] @@ -1582,27 +1566,27 @@ wheels = [ [[package]] name = "uv" -version = "0.5.1" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/d2/ec/c05991014f8208c1f3556d7dfc96ef5a6b7da6062e489718f3a0f9a74fb8/uv-0.5.1.tar.gz", hash = "sha256:ad2dd8a994a8334a5d4b354589be4b8c4b3b2ebb7bb2f2976c8e21d2799f45a9", size = 2131866 } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ba/33/9183528527cb8532369b678e1d12fb97e3777fed875f1d7ea6c75c570f64/uv-0.5.1-py3-none-linux_armv6l.whl", hash = "sha256:93f0a02ea9149f4e7e359ef92da6f221da2ecf458cda2af729a1f6fa8c3ed1d2", size = 13504611 }, - { url = "https://files.pythonhosted.org/packages/6b/23/f0f8234624f720b5a856800d85a2220405182cfd798eefbda8b7868f9c4d/uv-0.5.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:f66859e67d10ffff8b17c67c7ede207d67487cef20c3d17bc427b690f9dff795", size = 13482839 }, - { url = "https://files.pythonhosted.org/packages/a7/ef/375bb00fa3e73cbb29ffd1d2a0cea3a52b4c0e67f68bce646a9ed0539f18/uv-0.5.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:c4d209164448c8529e21aca4ef1e3da94303b1bf726924786feffd87ed93ab4a", size = 12503012 }, - { url = "https://files.pythonhosted.org/packages/88/f1/244f0f5e0afdc86de3c12c62c51f594a8b900d8ae1bf7cc64d9d92147199/uv-0.5.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:6ec61220d883751777cbabf0b076607cfbdeb812bc52c28722e897271461e589", size = 12787137 }, - { url = "https://files.pythonhosted.org/packages/86/fc/74a2fbfb9fc5c1772c0f85718da3e79a05aa3bdd5db1d83851f33e119e01/uv-0.5.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:73853b98bce9e118cda2d64360ddd7e0f79e237aca8cd2f28b6d5679400b239e", size = 13300628 }, - { url = "https://files.pythonhosted.org/packages/0f/81/0c08c94a9c9f27adc11fd9c3f55d6244c3066cbdea1a9c636fcc1bf45d53/uv-0.5.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8dce5b6d6dea41db71fe8d9895167cc5abf3e7b28c016174b1b9a9aecb74d483", size = 13874679 }, - { url = "https://files.pythonhosted.org/packages/eb/8c/2b3c642d71f18eff826a74329b23a269f2962b52d251854b645c98121e15/uv-0.5.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:aaa63053ff6dc4456e2ac2a9b6a8eda0cfaa1e0f861633d9e7315c7df9a0a525", size = 14437581 }, - { url = "https://files.pythonhosted.org/packages/9e/65/bae32b05056ba6b5441a491ce17c8216ec92cfade62a7b44702758689646/uv-0.5.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac3fce68002e79f3c070f3e7d914e992f205f05af00bfffbe6c44d37aa39c86a", size = 14164878 }, - { url = "https://files.pythonhosted.org/packages/51/1a/38edd7edf8fc73d1db87130f4ac62f2381166fabcc36288b63d82e43373c/uv-0.5.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72b54a3308e13a81aa2df19baea40611fc344c7556f75d2113f9b9b5a894355e", size = 18438644 }, - { url = "https://files.pythonhosted.org/packages/be/24/b2f69c0adb60d4c5d3c5413454ab869ed275db52da4be02eaa9d1a149191/uv-0.5.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d1ec4a1bc19b523a84fc1bf2a92e9c4d982c831d3da450af71fc3057999d456", size = 13988358 }, - { url = "https://files.pythonhosted.org/packages/43/80/1d887496fa3f2853dd670e43da90ee6efa8e020c82e3a1e2b41c19006d9d/uv-0.5.1-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:01c40f756e9536c05fdf3485c1dfe3da610c3169195bbe20fab03a4c4b7a0d98", size = 12970766 }, - { url = "https://files.pythonhosted.org/packages/11/0c/5ba7bf4b5ca478cf8c9d660d7baa977af1cd3dda2981f20d0c8e436a48f2/uv-0.5.1-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:3db7513c804fb89dcde671ba917cc486cfb574408d6257e19b19ae6b55f5982f", size = 13274891 }, - { url = "https://files.pythonhosted.org/packages/28/08/1ad7ef9ffd0f3c534cbcad47b57afdb785143ec46973faecc5c90de33025/uv-0.5.1-py3-none-musllinux_1_1_i686.whl", hash = "sha256:4601d40b0c02aff9fb791efa5b6f4c7dbad0970e13ac679aa8fb07365f331354", size = 13609667 }, - { url = "https://files.pythonhosted.org/packages/fc/e5/56d1457ac76bedce375c1adbfebeb281d94a24d35463350c7fc40f9413b8/uv-0.5.1-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:821b6a9d591d3e951fbe81c53d32499d11500100d66b1c119e183f3d4a6cd07c", size = 15349628 }, - { url = "https://files.pythonhosted.org/packages/c5/0a/956467ee8bfa59f698f384eef6e072b14b971d36b7ee6d9b8ed15cfed065/uv-0.5.1-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:6a76765c3cc49268f3c6773bd89a0dacf8a91b040fc3faea6c527ef6f2308eba", size = 14110649 }, - { url = "https://files.pythonhosted.org/packages/5e/94/d7546d96c0e447f56817be2210c4a9d75817d1072e526aaaf17f0dd59a3e/uv-0.5.1-py3-none-win32.whl", hash = "sha256:3ffb230be0f6552576da67a2737a32a6a640e4b3f42144088222a669802d7f10", size = 13423908 }, - { url = "https://files.pythonhosted.org/packages/8c/b2/ac107886f60081f6cd2295c9faf3c312a02c5aca87e8c0b7589340a58224/uv-0.5.1-py3-none-win_amd64.whl", hash = "sha256:922685dcaa1c9b6663649b379f9bdbe5b87af230f512e69398efc51bd9d8b8eb", size = 15169543 }, +version = "0.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/ad/66cc8e00c217e7fcf76598c880632b480aa38d4cad311596b78e99737498/uv-0.5.4.tar.gz", hash = "sha256:cd7a5a3a36f975a7678f27849a2d49bafe7272143d938e9b6f3bf28392a3ba00", size = 2315678 } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2b/3e/6bf24d7bb0d11715ea783ecabcacdecdc8c51fca0144fcdad2090d65bae5/uv-0.5.4-py3-none-linux_armv6l.whl", hash = "sha256:2118bb99cbc9787cb5e5cc4a507201e25a3fe88a9f389e8ffb84f242d96038c2", size = 13853445 }, + { url = "https://files.pythonhosted.org/packages/b8/be/c3acbe2944cd694a5d61a7a461468fa886512c84014545bb8f3244092eaa/uv-0.5.4-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:4432215deb8d5c1ccab17ee51cb80f5de1a20865ee02df47532f87442a3d6a58", size = 13969300 }, + { url = "https://files.pythonhosted.org/packages/1f/c5/06e3b93045179b92d75cf94e6e224baec3226070f1cbc0e11d4898300b54/uv-0.5.4-py3-none-macosx_11_0_arm64.whl", hash = "sha256:f40c6c6c3a1b398b56d3a8b28f7b455ac1ce4cbb1469f8d35d3bbc804d83daa4", size = 12932325 }, + { url = "https://files.pythonhosted.org/packages/b8/f9/06ab86e9f0c270c495077ef2b588458172ed84f9c337de725c8b08872354/uv-0.5.4-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.musllinux_1_1_aarch64.whl", hash = "sha256:df3cb58b7da91f4fc647d09c3e96006cd6c7bd424a81ce2308a58593c6887c39", size = 13183356 }, + { url = "https://files.pythonhosted.org/packages/c1/cb/bee01ef23e5020dc1f12d86ca8f82e95a723585db3ec64bfab4016e5616c/uv-0.5.4-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dd2df2ba823e6684230ab4c581f2320be38d7f46de11ce21d2dbba631470d7b6", size = 13622310 }, + { url = "https://files.pythonhosted.org/packages/19/4b/128fd874151919c71af51f528db28964e6d8e509fff12210ec9ba99b13fb/uv-0.5.4-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:928ed95fefe4e1338d0a7ad2f6b635de59e2ec92adaed4a267f7501a3b252263", size = 14207832 }, + { url = "https://files.pythonhosted.org/packages/b1/2b/0fed8a49440494f6806dcb67021ca8f14d46f45a665235fc153791e19574/uv-0.5.4-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:05b45c7eefb178dcdab0d49cd642fb7487377d00727102a8d6d306cc034c0d83", size = 14878796 }, + { url = "https://files.pythonhosted.org/packages/c9/35/a6dc404d4d8884e26ad7bda004c101972fe7d81f86546a8628272812b897/uv-0.5.4-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed5659cde099f39995f4cb793fd939d2260b4a26e4e29412c91e7537f53d8d25", size = 14687838 }, + { url = "https://files.pythonhosted.org/packages/74/9e/c2ebf66b90d48def06cda29626bb38068418ed135ca903beb293825ef66d/uv-0.5.4-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f07e5e0df40a09154007da41b76932671333f9fecb0735c698b19da25aa08927", size = 18960541 }, + { url = "https://files.pythonhosted.org/packages/3d/67/28a8b4c23920ae1b1b0103ebae2fa176bd5677c4353b5e814a51bd183285/uv-0.5.4-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:30ce031e36c54d4ba791d743d992d0a4fd8d70480db781d30a2f6f5125f39194", size = 14471756 }, + { url = "https://files.pythonhosted.org/packages/e9/1c/9698818f4c5493dfd5ab0899a90eee789cac214de2f171220bcdfaefc93a/uv-0.5.4-py3-none-manylinux_2_28_aarch64.whl", hash = "sha256:ca72e6a4c3c6b8b5605867e16a7f767f5c99b7f526de6bbb903c60eb44fd1e01", size = 13389089 }, + { url = "https://files.pythonhosted.org/packages/0b/30/31a9985d84ffb63fb9212fa2b565497e0ceb581be055e5cc760afbe26b11/uv-0.5.4-py3-none-musllinux_1_1_armv7l.whl", hash = "sha256:69079e900bd26b0f65069ac6fa684c74662ed87121c076f2b1cbcf042539034c", size = 13612748 }, + { url = "https://files.pythonhosted.org/packages/26/8d/bae613187ba88d74f0268246ce140f23d399bab96d2cbc055d6e4adafd09/uv-0.5.4-py3-none-musllinux_1_1_i686.whl", hash = "sha256:8d7a4a3df943a7c16cd032ccbaab8ed21ff64f4cb090b3a0a15a8b7502ccd876", size = 13946421 }, + { url = "https://files.pythonhosted.org/packages/0e/22/efd1eec81a566139bced68f4bd140c275edac3dac1bd6236cf8d756423db/uv-0.5.4-py3-none-musllinux_1_1_ppc64le.whl", hash = "sha256:f511faf719b797ef0f14688f1abe20b3fd126209cf58512354d1813249745119", size = 15752913 }, + { url = "https://files.pythonhosted.org/packages/49/b2/0cc4ae143b9605c25e75772aea22876b5875db79982ba62bb6f8d3099fab/uv-0.5.4-py3-none-musllinux_1_1_x86_64.whl", hash = "sha256:f806af0ee451a81099c449c4cff0e813056fdf7dd264f3d3a8fd321b17ff9efc", size = 14599503 }, + { url = "https://files.pythonhosted.org/packages/51/9a/33d40a5068fd37c4f7b4fa82396e3ee90a691cd256f364ff398612c1d5d4/uv-0.5.4-py3-none-win32.whl", hash = "sha256:a79a0885df364b897da44aae308e6ed9cca3a189d455cf1c205bd6f7b03daafa", size = 13749570 }, + { url = "https://files.pythonhosted.org/packages/b1/c8/827e4da65cbdab2c1619767a68ab99a31de078e511b71ca9f24777df33f9/uv-0.5.4-py3-none-win_amd64.whl", hash = "sha256:493aedc3c758bbaede83ecc8d5f7e6a9279ebec151c7f756aa9ea898c73f8ddb", size = 15573613 }, ] [[package]]