From 2a4b00d2d7969eb81f7a1ee6167bcf04797f465f Mon Sep 17 00:00:00 2001 From: barisgit Date: Sat, 6 Sep 2025 12:55:10 +0200 Subject: [PATCH 01/13] Start implementing typer for cli - create a separate typer entry point for now and migrate some commands --- kicad_lib_manager/commands/init/__init__.py | 12 +- kicad_lib_manager/commands/init/command.py | 201 +++++----- .../commands/list_libraries/__init__.py | 13 +- .../commands/list_libraries/command.py | 92 ++++- kicad_lib_manager/commands/pin/__init__.py | 12 +- kicad_lib_manager/commands/pin/command.py | 206 ++++++---- kicad_lib_manager/commands/status/__init__.py | 13 +- kicad_lib_manager/commands/status/command.py | 371 ++++++++++-------- kicad_lib_manager/main.py | 88 +++++ kicad_lib_manager/utils/template.py | 4 +- pyproject.toml | 4 +- 11 files changed, 646 insertions(+), 370 deletions(-) create mode 100644 kicad_lib_manager/main.py diff --git a/kicad_lib_manager/commands/init/__init__.py b/kicad_lib_manager/commands/init/__init__.py index 3ea0b37..c2fb785 100644 --- a/kicad_lib_manager/commands/init/__init__.py +++ b/kicad_lib_manager/commands/init/__init__.py @@ -1,3 +1,13 @@ +import typer from .command import init -__all__ = ["init"] +# Create Typer app and add the init command as callback +init_app = typer.Typer( + name="init", + help="Initialize library configuration", + rich_markup_mode="rich", + callback=init, + invoke_without_command=True, +) + +__all__ = ["init", "init_app"] diff --git a/kicad_lib_manager/commands/init/command.py b/kicad_lib_manager/commands/init/command.py index 408ccd7..dcf6513 100644 --- a/kicad_lib_manager/commands/init/command.py +++ b/kicad_lib_manager/commands/init/command.py @@ -1,12 +1,15 @@ """ -Init command implementation for KiCad Library Manager. +Init command implementation for KiCad Library Manager (Typer version). Initializes the current directory as a KiCad library directory (symbols, footprints, templates). """ -import sys from pathlib import Path +from typing import Annotated, Optional -import click +import typer +from rich.console import Console +from rich.panel import Panel +from rich.prompt import Confirm from ...config import Config from ...utils.metadata import ( @@ -17,95 +20,107 @@ write_github_metadata, ) - -@click.command() -@click.option( - "--name", - help="Name for this library collection (automatic if not provided)", - default=None, -) -@click.option( - "--set-current", - is_flag=True, - default=True, - help="Set this as the current active library", - show_default=True, -) -@click.option( - "--description", - help="Description for this library collection", - default=None, -) -@click.option( - "--env-var", - help="Custom environment variable name for this library", - default=None, -) -@click.option( - "--force", - is_flag=True, - default=False, - help="Overwrite existing metadata file if present", - show_default=True, -) -@click.option( - "--no-env-var", - is_flag=True, - default=False, - help="Don't assign an environment variable to this library", - show_default=True, -) -def init(name, set_current, description, env_var, force, no_env_var): - """Initialize the current directory as a KiCad library collection. +console = Console() + + +def init( + name: Annotated[ + Optional[str], + typer.Option( + "--name", + help="Name for this library collection (automatic if not provided)", + ), + ] = None, + set_current: Annotated[ + bool, + typer.Option( + "--set-current/--no-set-current", + help="Set this as the current active library", + ), + ] = True, + description: Annotated[ + Optional[str], + typer.Option( + "--description", + help="Description for this library collection", + ), + ] = None, + env_var: Annotated[ + Optional[str], + typer.Option( + "--env-var", + help="Custom environment variable name for this library", + ), + ] = None, + force: Annotated[ + bool, + typer.Option( + "--force", + help="Overwrite existing metadata file if present", + ), + ] = False, + no_env_var: Annotated[ + bool, + typer.Option( + "--no-env-var", + help="Don't assign an environment variable to this library", + ), + ] = False, +) -> None: + """ + Initialize the current directory as a KiCad library collection. This command sets up the current directory as a KiCad library containing symbols, footprints, and templates. It creates the required folders if they don't exist and registers the library in the local configuration. - Each library can have its own unique environment variable name, which - will be used when setting up KiCad. This allows you to have multiple symbol/footprint - libraries and reference them individually. - - If a metadata file (kilm.yaml) already exists, information from it will be - used unless overridden by command line options. - - This is intended for GitHub-based libraries containing symbols and footprints, - not for 3D model libraries. + [bold]Features:[/bold] + • Creates symbol, footprint, and template directories + • Generates metadata file with library information + • Assigns unique environment variable for KiCad integration + • Registers library in KiLM configuration + + [bold]Note:[/bold] This is intended for GitHub-based libraries containing + symbols and footprints, not for 3D model libraries. """ current_dir = Path.cwd().resolve() - click.echo(f"Initializing KiCad library at: {current_dir}") + + console.print(Panel( + f"[bold blue]Initializing KiCad library[/bold blue]\n" + f"[cyan]Location:[/cyan] {current_dir}", + title="KiLM Library Initialization", + border_style="blue" + )) # Check for existing metadata metadata = read_github_metadata(current_dir) if metadata and not force: - click.echo(f"Found existing metadata file ({GITHUB_METADATA_FILE}).") + console.print(f"[green]Found existing metadata file[/green] ([cyan]{GITHUB_METADATA_FILE}[/cyan])") library_name = metadata.get("name") library_description = metadata.get("description") library_env_var = metadata.get("env_var") - click.echo(f"Using existing name: {library_name}") + console.print(f"[blue]Using existing name:[/blue] {library_name}") # Show environment variable if present if library_env_var and not no_env_var: - click.echo(f"Using existing environment variable: {library_env_var}") + console.print(f"[blue]Using existing environment variable:[/blue] {library_env_var}") # Override with command line parameters if provided if name: library_name = name - click.echo(f"Overriding with provided name: {library_name}") + console.print(f"[yellow]Overriding with provided name:[/yellow] {library_name}") if description: library_description = description - click.echo(f"Overriding with provided description: {library_description}") + console.print(f"[yellow]Overriding with provided description:[/yellow] {library_description}") if env_var: library_env_var = env_var - click.echo( - f"Overriding with provided environment variable: {library_env_var}" - ) + console.print(f"[yellow]Overriding with provided environment variable:[/yellow] {library_env_var}") elif no_env_var: library_env_var = None - click.echo("Disabling environment variable as requested") + console.print("[yellow]Disabling environment variable as requested[/yellow]") # Update metadata if command line parameters were provided if name or description or env_var or no_env_var: @@ -120,13 +135,13 @@ def init(name, set_current, description, env_var, force, no_env_var): pass metadata["updated_with"] = "kilm" write_github_metadata(current_dir, metadata) - click.echo("Updated metadata file with new information.") + console.print("[green]Updated metadata file with new information.[/green]") else: # Create a new metadata file if metadata and force: - click.echo(f"Overwriting existing metadata file ({GITHUB_METADATA_FILE}).") + console.print(f"[yellow]Overwriting existing metadata file[/yellow] ([cyan]{GITHUB_METADATA_FILE}[/cyan])") else: - click.echo(f"Creating new metadata file ({GITHUB_METADATA_FILE}).") + console.print(f"[green]Creating new metadata file[/green] ([cyan]{GITHUB_METADATA_FILE}[/cyan])") # Generate metadata metadata = get_default_github_metadata(current_dir) @@ -148,7 +163,7 @@ def init(name, set_current, description, env_var, force, no_env_var): # Write metadata file write_github_metadata(current_dir, metadata) - click.echo("Metadata file created.") + console.print("[green]Metadata file created.[/green]") library_name = metadata["name"] library_env_var = metadata.get("env_var") @@ -167,8 +182,8 @@ def init(name, set_current, description, env_var, force, no_env_var): folder_path.mkdir(parents=True, exist_ok=True) created_folders.append(folder) except Exception as e: - click.echo(f"Error creating {folder} directory: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error creating {folder} directory: {e}[/red]") + raise typer.Exit(1) # Create empty library_descriptions.yaml if it doesn't exist library_descriptions_file = current_dir / "library_descriptions.yaml" @@ -192,12 +207,9 @@ def init(name, set_current, description, env_var, force, no_env_var): """ with library_descriptions_file.open("w", encoding="utf-8") as f: f.write(template_content) - click.echo("Created library_descriptions.yaml template file.") + console.print("[green]Created library_descriptions.yaml template file.[/green]") except Exception as e: - click.echo( - f"Warning: Could not create library_descriptions.yaml file: {e}", - err=True, - ) + console.print(f"[yellow]Warning: Could not create library_descriptions.yaml file: {e}[/yellow]") # Update the metadata with current capabilities updated_capabilities = { @@ -210,16 +222,16 @@ def init(name, set_current, description, env_var, force, no_env_var): # Report on folder status if existing_folders: - click.echo(f"Found existing folders: {', '.join(existing_folders)}") + console.print(f"[blue]Found existing folders:[/blue] {', '.join(existing_folders)}") if created_folders: - click.echo(f"Created new folders: {', '.join(created_folders)}") + console.print(f"[green]Created new folders:[/green] {', '.join(created_folders)}") # Verify if this looks like a KiCad library if not created_folders and not existing_folders: - click.echo("Warning: No library folders were found or created.") - if not click.confirm("Continue anyway?", default=True): - click.echo("Initialization cancelled.") - sys.exit(0) + console.print("[yellow]Warning: No library folders were found or created.[/yellow]") + if not Confirm.ask("Continue anyway?", default=True): + console.print("[yellow]Initialization cancelled.[/yellow]") + raise typer.Exit(0) # Update the configuration try: @@ -231,22 +243,29 @@ def init(name, set_current, description, env_var, force, no_env_var): if set_current: config.set_current_library(str(current_dir)) - click.echo(f"Library '{safe_library_name}' initialized successfully!") - click.echo("Type: GitHub library (symbols, footprints, templates)") - click.echo(f"Path: {current_dir}") + # Create success panel + success_content = f"[bold green]Library '{safe_library_name}' initialized successfully![/bold green]\n\n" + success_content += f"[cyan]Type:[/cyan] GitHub library (symbols, footprints, templates)\n" + success_content += f"[cyan]Path:[/cyan] {current_dir}\n" if library_env_var: - click.echo(f"Assigned environment variable: {library_env_var}") + success_content += f"[cyan]Environment Variable:[/cyan] {library_env_var}\n" if set_current: - click.echo("This is now your current active library.") - click.echo("kilm will use this library for all commands by default.") + success_content += f"\n[yellow]This is now your current active library.[/yellow]\n" + success_content += f"[dim]KiLM will use this library for all commands by default.[/dim]" + + console.print(Panel( + success_content, + title="✅ Initialization Complete", + border_style="green" + )) # Add a hint for adding 3D models - click.echo( - "\nTo add a 3D models directory (typically stored in the cloud), use:" - ) - click.echo(" kilm add-3d --name my-3d-models --directory /path/to/3d/models") + console.print("\n[bold]Next Steps:[/bold]") + console.print("To add a 3D models directory (typically stored in the cloud), use:") + console.print("[dim] kilm add-3d --name my-3d-models --directory /path/to/3d/models[/dim]") + except Exception as e: - click.echo(f"Error initializing library: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error initializing library: {e}[/red]") + raise typer.Exit(1) diff --git a/kicad_lib_manager/commands/list_libraries/__init__.py b/kicad_lib_manager/commands/list_libraries/__init__.py index df7abab..a05f940 100644 --- a/kicad_lib_manager/commands/list_libraries/__init__.py +++ b/kicad_lib_manager/commands/list_libraries/__init__.py @@ -1,3 +1,14 @@ +import typer + from .command import list_cmd -__all__ = ["list_cmd"] +# Create Typer app and add the list command as callback +list_app = typer.Typer( + name="list", + help="List available KiCad libraries", + rich_markup_mode="rich", + callback=list_cmd, + invoke_without_command=True, +) + +__all__ = ["list_cmd", "list_app"] diff --git a/kicad_lib_manager/commands/list_libraries/command.py b/kicad_lib_manager/commands/list_libraries/command.py index 89ad48d..17e9533 100644 --- a/kicad_lib_manager/commands/list_libraries/command.py +++ b/kicad_lib_manager/commands/list_libraries/command.py @@ -1,29 +1,41 @@ """ -List command implementation for KiCad Library Manager. +List command implementation for KiCad Library Manager (Typer version). """ -import sys +from typing import Annotated, Optional -import click +import typer +from rich.console import Console +from rich.table import Table from ...library_manager import list_libraries from ...utils.env_vars import expand_user_path, find_environment_variables +console = Console() -@click.command() -@click.option( - "--kicad-lib-dir", - envvar="KICAD_USER_LIB", - help="KiCad library directory (uses KICAD_USER_LIB env var if not specified)", -) -def list_cmd(kicad_lib_dir): - """List available libraries in the specified directory""" + +def list_cmd( + kicad_lib_dir: Annotated[ + Optional[str], + typer.Option( + "--kicad-lib-dir", + help="KiCad library directory (uses KICAD_USER_LIB env var if not specified)", + envvar="KICAD_USER_LIB", + ), + ] = None, +) -> None: + """ + List available libraries in the specified directory. + + This command scans the KiCad library directory for symbol (.kicad_sym) and + footprint (.pretty) libraries and displays them in organized tables. + """ # Find environment variables if not provided if not kicad_lib_dir: kicad_lib_dir = find_environment_variables("KICAD_USER_LIB") if not kicad_lib_dir: - click.echo("Error: KICAD_USER_LIB not set and not provided", err=True) - sys.exit(1) + console.print("[red]Error: KICAD_USER_LIB not set and not provided[/red]") + raise typer.Exit(1) # Expand user home directory if needed kicad_lib_dir = expand_user_path(kicad_lib_dir) @@ -31,19 +43,57 @@ def list_cmd(kicad_lib_dir): try: symbols, footprints = list_libraries(kicad_lib_dir) + console.print(f"[blue]Scanning library directory:[/blue] {kicad_lib_dir}\n") + + # Display symbol libraries in a table if symbols: - click.echo("\nAvailable Symbol Libraries:") + symbol_table = Table( + title="Available Symbol Libraries", + show_header=True, + header_style="bold cyan", + ) + symbol_table.add_column("Library Name", style="cyan", no_wrap=True) + symbol_table.add_column("Type", style="blue") + for symbol in sorted(symbols): - click.echo(f" - {symbol}") + symbol_table.add_row(symbol, ".kicad_sym") + + console.print(symbol_table) else: - click.echo("No symbol libraries found") + console.print("[yellow]No symbol libraries found[/yellow]") + + console.print() # Empty line for spacing + # Display footprint libraries in a table if footprints: - click.echo("\nAvailable Footprint Libraries:") + footprint_table = Table( + title="Available Footprint Libraries", + show_header=True, + header_style="bold magenta", + ) + footprint_table.add_column("Library Name", style="magenta", no_wrap=True) + footprint_table.add_column("Type", style="blue") + for footprint in sorted(footprints): - click.echo(f" - {footprint}") + footprint_table.add_row(footprint, ".pretty") + + console.print(footprint_table) else: - click.echo("No footprint libraries found") + console.print("[yellow]No footprint libraries found[/yellow]") + + # Summary information + total_libs = len(symbols) + len(footprints) + if total_libs > 0: + console.print( + f"\n[green]Found {total_libs} libraries total[/green] " + f"([cyan]{len(symbols)} symbol[/cyan], " + f"[magenta]{len(footprints)} footprint[/magenta])" + ) + else: + console.print( + "[yellow]No libraries found in the specified directory[/yellow]" + ) + except Exception as e: - click.echo(f"Error listing libraries: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error listing libraries: {e}[/red]") + raise typer.Exit(1) diff --git a/kicad_lib_manager/commands/pin/__init__.py b/kicad_lib_manager/commands/pin/__init__.py index 21044cf..0c7e6ca 100644 --- a/kicad_lib_manager/commands/pin/__init__.py +++ b/kicad_lib_manager/commands/pin/__init__.py @@ -1,3 +1,13 @@ +import typer from .command import pin -__all__ = ["pin"] +# Create Typer app and add the pin command as callback +pin_app = typer.Typer( + name="pin", + help="Pin favorite libraries", + rich_markup_mode="rich", + callback=pin, + invoke_without_command=True, +) + +__all__ = ["pin", "pin_app"] diff --git a/kicad_lib_manager/commands/pin/command.py b/kicad_lib_manager/commands/pin/command.py index ea7f030..2379d8d 100644 --- a/kicad_lib_manager/commands/pin/command.py +++ b/kicad_lib_manager/commands/pin/command.py @@ -1,10 +1,13 @@ """ -Pin command implementation for KiCad Library Manager. +Pin command implementation for KiCad Library Manager (Typer version). """ -import sys +from typing import Annotated, List, Optional -import click +import typer +from rich.console import Console +from rich.panel import Panel +from rich.table import Table from ...library_manager import find_kicad_config, list_libraries from ...utils.env_vars import ( @@ -13,112 +16,134 @@ update_pinned_libraries, ) - -@click.command() -@click.option( - "--kicad-lib-dir", - envvar="KICAD_USER_LIB", - help="KiCad library directory (uses KICAD_USER_LIB env var if not specified)", -) -@click.option( - "--symbols", - "-s", - multiple=True, - help="Symbol libraries to pin (can be specified multiple times)", -) -@click.option( - "--footprints", - "-f", - multiple=True, - help="Footprint libraries to pin (can be specified multiple times)", -) -@click.option( - "--all/--selected", - default=True, - show_default=True, - help="Pin all available libraries or only selected ones", -) -@click.option( - "--dry-run", - is_flag=True, - help="Show what would be done without making changes", -) -@click.option( - "--max-backups", - default=5, - show_default=True, - help="Maximum number of backups to keep", -) -@click.option( - "--verbose", - "-v", - is_flag=True, - help="Show verbose output for debugging", -) -def pin(kicad_lib_dir, symbols, footprints, all, dry_run, max_backups, verbose): - """Pin libraries in KiCad for quick access""" +console = Console() + + +def pin( + kicad_lib_dir: Annotated[ + Optional[str], + typer.Option( + "--kicad-lib-dir", + envvar="KICAD_USER_LIB", + help="KiCad library directory (uses KICAD_USER_LIB env var if not specified)", + ), + ] = None, + symbols: Annotated[ + List[str], + typer.Option( + "--symbols", + "-s", + help="Symbol libraries to pin (can be specified multiple times)", + ), + ] = None, + footprints: Annotated[ + List[str], + typer.Option( + "--footprints", + "-f", + help="Footprint libraries to pin (can be specified multiple times)", + ), + ] = None, + all_libs: Annotated[ + bool, + typer.Option( + "--all/--selected", + help="Pin all available libraries or only selected ones", + ), + ] = True, + dry_run: Annotated[ + bool, + typer.Option( + "--dry-run", + help="Show what would be done without making changes", + ), + ] = False, + max_backups: Annotated[ + int, + typer.Option( + "--max-backups", + help="Maximum number of backups to keep", + ), + ] = 5, + verbose: Annotated[ + bool, + typer.Option( + "--verbose", + "-v", + help="Show verbose output for debugging", + ), + ] = False, +) -> None: + """ + Pin libraries in KiCad for quick access. + + This command pins libraries in KiCad's interface for quick access. + You can pin specific symbol and footprint libraries or all available libraries. + """ + # Initialize default values for mutable types + if symbols is None: + symbols = [] + if footprints is None: + footprints = [] + # Find environment variables if not provided if not kicad_lib_dir: kicad_lib_dir = find_environment_variables("KICAD_USER_LIB") if not kicad_lib_dir: - click.echo("Error: KICAD_USER_LIB not set and not provided", err=True) - sys.exit(1) + console.print("[red]Error: KICAD_USER_LIB not set and not provided[/red]") + raise typer.Exit(1) # Expand user home directory if needed kicad_lib_dir = expand_user_path(kicad_lib_dir) if verbose: - click.echo(f"Using KiCad library directory: {kicad_lib_dir}") + console.print(f"[blue]Using KiCad library directory:[/blue] {kicad_lib_dir}") # Find KiCad configuration try: kicad_config = find_kicad_config() if verbose: - click.echo(f"Found KiCad configuration at: {kicad_config}") + console.print(f"[blue]Found KiCad configuration at:[/blue] {kicad_config}") except Exception as e: - click.echo(f"Error finding KiCad configuration: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error finding KiCad configuration: {e}[/red]") + raise typer.Exit(1) # If --all is specified, get all libraries from the directory - if all and not symbols and not footprints: + if all_libs and not symbols and not footprints: try: symbol_libs, footprint_libs = list_libraries(kicad_lib_dir) - symbols = symbol_libs - footprints = footprint_libs + symbols = list(symbol_libs) + footprints = list(footprint_libs) if verbose: - click.echo( - f"Found {len(symbols)} symbol libraries and {len(footprints)} footprint libraries" + console.print( + f"[green]Found {len(symbols)} symbol libraries and {len(footprints)} footprint libraries[/green]" ) except Exception as e: - click.echo(f"Error listing libraries: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error listing libraries: {e}[/red]") + raise typer.Exit(1) - # Convert tuples to lists if needed - if isinstance(symbols, tuple): - symbols = list(symbols) - if isinstance(footprints, tuple): - footprints = list(footprints) + # Ensure we have lists (Typer should already provide lists) + if not isinstance(symbols, list): + symbols = list(symbols) if symbols else [] + if not isinstance(footprints, list): + footprints = list(footprints) if footprints else [] # Validate that libraries exist - if not all and (symbols or footprints): + if not all_libs and (symbols or footprints): try: available_symbols, available_footprints = list_libraries(kicad_lib_dir) # Check symbols for symbol in symbols: if symbol not in available_symbols: - click.echo( - f"Warning: Symbol library '{symbol}' not found", err=True - ) + console.print(f"[yellow]Warning: Symbol library '{symbol}' not found[/yellow]") # Check footprints for footprint in footprints: if footprint not in available_footprints: - click.echo( - f"Warning: Footprint library '{footprint}' not found", err=True - ) + console.print(f"[yellow]Warning: Footprint library '{footprint}' not found[/yellow]") except Exception as e: - click.echo(f"Error validating libraries: {e}", err=True) + console.print(f"[yellow]Error validating libraries: {e}[/yellow]") # Continue anyway, in case the libraries are configured but not in the directory try: @@ -132,28 +157,35 @@ def pin(kicad_lib_dir, symbols, footprints, all, dry_run, max_backups, verbose): if changes_needed: if dry_run: - click.echo( - f"Would pin {len(symbols)} symbol and {len(footprints)} footprint libraries in KiCad" + console.print( + f"[yellow]Would pin {len(symbols)} symbol and {len(footprints)} footprint libraries in KiCad[/yellow]" ) else: - click.echo( - f"Pinned {len(symbols)} symbol and {len(footprints)} footprint libraries in KiCad" - ) - click.echo("Created backup of kicad_common.json") - click.echo("Restart KiCad for changes to take effect") + success_msg = f"[green]Pinned {len(symbols)} symbol and {len(footprints)} footprint libraries in KiCad[/green]" + console.print(Panel( + f"{success_msg}\n\n" + f"[blue]• Created backup of kicad_common.json[/blue]\n" + f"[yellow]• Restart KiCad for changes to take effect[/yellow]", + title="✅ Libraries Pinned", + border_style="green" + )) else: - click.echo("No changes needed, libraries already pinned in KiCad") + console.print("[blue]No changes needed, libraries already pinned in KiCad[/blue]") if verbose: if symbols: - click.echo("\nPinned Symbol Libraries:") + table = Table(title="Pinned Symbol Libraries") + table.add_column("Library", style="cyan") for symbol in sorted(symbols): - click.echo(f" - {symbol}") + table.add_row(symbol) + console.print(table) if footprints: - click.echo("\nPinned Footprint Libraries:") + table = Table(title="Pinned Footprint Libraries") + table.add_column("Library", style="magenta") for footprint in sorted(footprints): - click.echo(f" - {footprint}") + table.add_row(footprint) + console.print(table) except Exception as e: - click.echo(f"Error pinning libraries: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error pinning libraries: {e}[/red]") + raise typer.Exit(1) diff --git a/kicad_lib_manager/commands/status/__init__.py b/kicad_lib_manager/commands/status/__init__.py index 239e435..520d19c 100644 --- a/kicad_lib_manager/commands/status/__init__.py +++ b/kicad_lib_manager/commands/status/__init__.py @@ -1,3 +1,14 @@ +import typer + from .command import status -__all__ = ["status"] +# Create Typer app and add the status command as callback +status_app = typer.Typer( + name="status", + help="Show current library configuration status", + rich_markup_mode="rich", + callback=status, + invoke_without_command=True, +) + +__all__ = ["status", "status_app"] diff --git a/kicad_lib_manager/commands/status/command.py b/kicad_lib_manager/commands/status/command.py index d0b001f..3ccd4c0 100644 --- a/kicad_lib_manager/commands/status/command.py +++ b/kicad_lib_manager/commands/status/command.py @@ -1,179 +1,187 @@ """ -Status command implementation for KiCad Library Manager. +Status command implementation for KiCad Library Manager (Typer version). """ import json from pathlib import Path -import click +import typer import yaml +from rich.console import Console +from rich.panel import Panel +from rich.table import Table +from rich.text import Text from ...library_manager import find_kicad_config, list_configured_libraries from ...utils.metadata import read_cloud_metadata, read_github_metadata +console = Console() -@click.command() -def status(): + +def status() -> None: """Show the current KiCad configuration status""" try: # Show KILM configuration first - try: - config_file = Path.home() / ".config" / "kicad-lib-manager" / "config.yaml" - if config_file.exists(): - click.echo("KILM Configuration:") - try: - with config_file.open() as f: - config_data = yaml.safe_load(f) - - # Show libraries - if ( - config_data - and "libraries" in config_data - and config_data["libraries"] - ): - click.echo(" Configured Libraries:") - - # Group by type - github_libs = [ - lib - for lib in config_data["libraries"] - if lib.get("type") == "github" - ] - cloud_libs = [ - lib - for lib in config_data["libraries"] - if lib.get("type") == "cloud" - ] - - if github_libs: - click.echo(" GitHub Libraries (symbols/footprints):") - for lib in github_libs: - name = lib.get("name", "unnamed") - path = lib.get("path", "unknown") - current = ( - " (current)" - if config_data - and config_data.get("current_library") == path - else "" - ) - click.echo(f" - {name}: {path}{current}") - - # Check if metadata file exists - try: - if read_github_metadata(Path(path)): - click.echo(" Metadata: Yes") - except Exception: - pass - - if cloud_libs: - click.echo(" Cloud Libraries (3D models):") - for lib in cloud_libs: - name = lib.get("name", "unnamed") - path = lib.get("path", "unknown") - current = ( - " (current)" - if config_data - and config_data.get("current_library") == path - else "" - ) - click.echo(f" - {name}: {path}{current}") - - # Check if metadata file exists - try: - if read_cloud_metadata(Path(path)): - click.echo(" Metadata: Yes") - except Exception: - pass - else: - click.echo(" No libraries configured") - - # Show current library - if ( - config_data - and "current_library" in config_data - and config_data["current_library"] - ): - click.echo( - f" Current Library: {config_data['current_library']}" - ) - else: - click.echo(" No current library set") - - # Show other settings - if config_data and "max_backups" in config_data: - click.echo(f" Max Backups: {config_data['max_backups']}") - - except Exception as e: - click.echo(f" Error reading configuration: {e}", err=True) - else: - click.echo( - "No KILM configuration file found. Run 'kilm init' to create one." - ) - except Exception as e: - click.echo(f"Error reading KILM configuration: {e}", err=True) + _show_kilm_configuration() - click.echo("\n--- KiCad Configuration ---") + console.print("\n[bold cyan]KiCad Configuration[/bold cyan]") kicad_config = find_kicad_config() - click.echo(f"KiCad configuration directory: {kicad_config}") + console.print(f"KiCad configuration directory: [blue]{kicad_config}[/blue]") # Check environment variables in KiCad common - kicad_common = kicad_config / "kicad_common.json" - if kicad_common.exists(): - try: - with kicad_common.open() as f: - common_config = json.load(f) - - click.echo("\nEnvironment Variables in KiCad:") - if ( - "environment" in common_config - and "vars" in common_config["environment"] - ): - env_vars = common_config["environment"]["vars"] - if env_vars: - for key, value in env_vars.items(): - click.echo(f" {key} = {value}") - else: - click.echo(" No environment variables set") - else: - click.echo(" No environment variables found") - except Exception as e: - click.echo(f" Error reading KiCad common configuration: {e}", err=True) + _show_kicad_environment_variables(kicad_config) # Check pinned libraries - check_pinned_libraries(kicad_config) + _check_pinned_libraries(kicad_config) # Check configured libraries - try: - sym_libs, fp_libs = list_configured_libraries(kicad_config) - - click.echo("\nConfigured Symbol Libraries:") - if sym_libs: - for lib in sym_libs: - lib_name = lib["name"] - lib_uri = lib["uri"] - click.echo(f" - {lib_name}: {lib_uri}") - else: - click.echo(" No symbol libraries configured") - - click.echo("\nConfigured Footprint Libraries:") - if fp_libs: - for lib in fp_libs: - lib_name = lib["name"] - lib_uri = lib["uri"] - click.echo(f" - {lib_name}: {lib_uri}") - else: - click.echo(" No footprint libraries configured") - except Exception as e: - click.echo(f"Error listing configured libraries: {e}", err=True) + _show_configured_libraries(kicad_config) except Exception as e: - click.echo(f"Error getting KiCad configuration: {e}", err=True) + console.print(f"[red]Error getting KiCad configuration: {e}[/red]") + raise typer.Exit(1) from e + + +def _show_kilm_configuration() -> None: + """Show KILM configuration section""" + try: + config_file = Path.home() / ".config" / "kicad-lib-manager" / "config.yaml" + if config_file.exists(): + console.print("[bold cyan]KILM Configuration[/bold cyan]") + try: + with config_file.open() as f: + config_data = yaml.safe_load(f) + _show_configured_libraries_table(config_data) + _show_kilm_settings(config_data) + + except Exception as e: + console.print(f"[red]Error reading configuration: {e}[/red]") + else: + console.print( + "[yellow]No KILM configuration file found. Run 'kilm init' to create one.[/yellow]" + ) + except Exception as e: + console.print(f"[red]Error reading KILM configuration: {e}[/red]") + + +def _show_configured_libraries_table(config_data: dict) -> None: + """Show configured libraries in a table format""" + if not config_data or not config_data.get("libraries"): + console.print("[yellow] No libraries configured[/yellow]") + return + + # Create tables for different library types + github_libs = [ + lib for lib in config_data["libraries"] if lib.get("type") == "github" + ] + cloud_libs = [lib for lib in config_data["libraries"] if lib.get("type") == "cloud"] + + current_library = config_data.get("current_library", "") + + if github_libs: + table = Table(title="GitHub Libraries (symbols/footprints)", show_header=True) + table.add_column("Name", style="cyan", no_wrap=True) + table.add_column("Path", style="blue") + table.add_column("Status", justify="center") + table.add_column("Metadata", justify="center") + + for lib in github_libs: + name = lib.get("name", "unnamed") + path = lib.get("path", "unknown") + is_current = "✓ Current" if current_library == path else "" + + # Check metadata + try: + has_metadata = "✓" if read_github_metadata(Path(path)) else "✗" + except Exception: + has_metadata = "?" + + table.add_row(name, path, is_current, has_metadata) + + console.print(table) + + if cloud_libs: + table = Table(title="Cloud Libraries (3D models)", show_header=True) + table.add_column("Name", style="cyan", no_wrap=True) + table.add_column("Path", style="blue") + table.add_column("Status", justify="center") + table.add_column("Metadata", justify="center") + + for lib in cloud_libs: + name = lib.get("name", "unnamed") + path = lib.get("path", "unknown") + is_current = "✓ Current" if current_library == path else "" + + # Check metadata + try: + has_metadata = "✓" if read_cloud_metadata(Path(path)) else "✗" + except Exception: + has_metadata = "?" -def check_pinned_libraries(kicad_config): + table.add_row(name, path, is_current, has_metadata) + + console.print(table) + + +def _show_kilm_settings(config_data: dict) -> None: + """Show KILM settings""" + if not config_data: + return + + settings_text = Text() + + # Current library + current_lib = config_data.get("current_library") + if current_lib: + settings_text.append(f"Current Library: {current_lib}\n", style="green") + else: + settings_text.append("No current library set\n", style="yellow") + + # Max backups + max_backups = config_data.get("max_backups") + if max_backups is not None: + settings_text.append(f"Max Backups: {max_backups}", style="blue") + + if settings_text.plain: + console.print(Panel(settings_text, title="Settings", border_style="blue")) + + +def _show_kicad_environment_variables(kicad_config: Path) -> None: + """Show KiCad environment variables""" + kicad_common = kicad_config / "kicad_common.json" + if not kicad_common.exists(): + console.print("[yellow]No kicad_common.json found[/yellow]") + return + + try: + with kicad_common.open() as f: + common_config = json.load(f) + + console.print("\n[bold]Environment Variables in KiCad:[/bold]") + + if "environment" in common_config and "vars" in common_config["environment"]: + env_vars = common_config["environment"]["vars"] + if env_vars: + table = Table(show_header=True) + table.add_column("Variable", style="cyan", no_wrap=True) + table.add_column("Value", style="blue") + + for key, value in env_vars.items(): + table.add_row(key, str(value)) + + console.print(table) + else: + console.print("[yellow] No environment variables set[/yellow]") + else: + console.print("[yellow] No environment variables found[/yellow]") + except Exception as e: + console.print(f"[red]Error reading KiCad common configuration: {e}[/red]") + + +def _check_pinned_libraries(kicad_config: Path) -> None: """Check and display pinned libraries""" - # First look in kicad_common.json kicad_common = kicad_config / "kicad_common.json" if kicad_common.exists(): try: @@ -181,7 +189,7 @@ def check_pinned_libraries(kicad_config): common_config = json.load(f) found_pinned = False - click.echo("\nPinned Libraries in KiCad:") + console.print("\n[bold]Pinned Libraries in KiCad:[/bold]") # Check for pinned symbol libraries if ( @@ -191,9 +199,9 @@ def check_pinned_libraries(kicad_config): sym_libs = common_config["session"]["pinned_symbol_libs"] if sym_libs: found_pinned = True - click.echo(" Symbol Libraries:") + console.print("[cyan]Symbol Libraries:[/cyan]") for lib in sym_libs: - click.echo(f" - {lib}") + console.print(f" • {lib}") # Check for pinned footprint libraries if ( @@ -203,18 +211,19 @@ def check_pinned_libraries(kicad_config): fp_libs = common_config["session"]["pinned_fp_libs"] if fp_libs: found_pinned = True - click.echo(" Footprint Libraries:") + console.print("[cyan]Footprint Libraries:[/cyan]") for lib in fp_libs: - click.echo(f" - {lib}") + console.print(f" • {lib}") if not found_pinned: - click.echo(" No pinned libraries found in kicad_common.json") + console.print( + "[yellow] No pinned libraries found in kicad_common.json[/yellow]" + ) return except Exception as e: - click.echo( - f" Error reading pinned libraries from kicad_common.json: {e}", - err=True, + console.print( + f"[red]Error reading pinned libraries from kicad_common.json: {e}[/red]" ) # Fall back to the old method of looking for a separate pinned file @@ -224,28 +233,62 @@ def check_pinned_libraries(kicad_config): with pinned_libs.open() as f: pinned_config = json.load(f) - click.echo("\nPinned Libraries in KiCad (legacy format):") + console.print("\n[bold]Pinned Libraries in KiCad (legacy format):[/bold]") found_pinned = False if "pinned_symbol_libs" in pinned_config: sym_libs = pinned_config["pinned_symbol_libs"] if sym_libs: found_pinned = True - click.echo(" Symbol Libraries:") + console.print("[cyan]Symbol Libraries:[/cyan]") for lib in sym_libs: - click.echo(f" - {lib}") + console.print(f" • {lib}") if "pinned_footprint_libs" in pinned_config: fp_libs = pinned_config["pinned_footprint_libs"] if fp_libs: found_pinned = True - click.echo(" Footprint Libraries:") + console.print("[cyan]Footprint Libraries:[/cyan]") for lib in fp_libs: - click.echo(f" - {lib}") + console.print(f" • {lib}") if not found_pinned: - click.echo(" No pinned libraries found") + console.print("[yellow] No pinned libraries found[/yellow]") except Exception as e: - click.echo(f" Error reading pinned libraries: {e}", err=True) + console.print(f"[red]Error reading pinned libraries: {e}[/red]") else: - click.echo("\nNo pinned libraries file found") + console.print("\n[yellow]No pinned libraries file found[/yellow]") + + +def _show_configured_libraries(kicad_config: Path) -> None: + """Show configured libraries in KiCad""" + try: + sym_libs, fp_libs = list_configured_libraries(kicad_config) + + console.print("\n[bold]Configured Symbol Libraries:[/bold]") + if sym_libs: + table = Table(show_header=True) + table.add_column("Library Name", style="cyan", no_wrap=True) + table.add_column("URI", style="blue") + + for lib in sym_libs: + table.add_row(lib["name"], lib["uri"]) + + console.print(table) + else: + console.print("[yellow] No symbol libraries configured[/yellow]") + + console.print("\n[bold]Configured Footprint Libraries:[/bold]") + if fp_libs: + table = Table(show_header=True) + table.add_column("Library Name", style="cyan", no_wrap=True) + table.add_column("URI", style="blue") + + for lib in fp_libs: + table.add_row(lib["name"], lib["uri"]) + + console.print(table) + else: + console.print("[yellow] No footprint libraries configured[/yellow]") + except Exception as e: + console.print(f"[red]Error listing configured libraries: {e}[/red]") diff --git a/kicad_lib_manager/main.py b/kicad_lib_manager/main.py new file mode 100644 index 0000000..08e415d --- /dev/null +++ b/kicad_lib_manager/main.py @@ -0,0 +1,88 @@ +#!/usr/bin/env python3 +""" +Main Typer CLI entry point for KiCad Library Manager +""" + +import importlib.metadata +from typing import Annotated, Optional + +import typer +from rich.console import Console +from rich.traceback import install + +from .commands.init import init_app +from .commands.list_libraries import list_app +from .commands.status import status_app + +# Install rich traceback handler for better error display +install(show_locals=True) + +# Initialize Rich console +console = Console() + +# Create main Typer app +app = typer.Typer( + name="kilm", + help="KiCad Library Manager - Manage KiCad libraries across projects and workstations", + context_settings={"help_option_names": ["-h", "--help"]}, + rich_markup_mode="rich", + pretty_exceptions_enable=True, + pretty_exceptions_show_locals=False, + no_args_is_help=True, +) + + +def version_callback(value: bool) -> None: + """Print version information and exit.""" + if value: + version = importlib.metadata.version("kilm") + console.print(f"KiCad Library Manager (KiLM) version {version}") + raise typer.Exit() + + +@app.callback() +def main( + version: Annotated[ + Optional[bool], + typer.Option( + "--version", + "-V", + callback=version_callback, + is_eager=True, + help="Show version information and exit", + ), + ] = None, +) -> None: + """ + [bold blue]KiCad Library Manager[/bold blue] - Professional KiCad library management + + This tool helps you configure and manage KiCad libraries across your projects + and workstations with a modern, type-safe CLI interface. + + [bold]Common Commands:[/bold] + • [cyan]kilm status[/cyan] - Show current configuration + • [cyan]kilm setup[/cyan] - Configure KiCad to use libraries + • [cyan]kilm list[/cyan] - List available libraries + • [cyan]kilm sync[/cyan] - Update library content + """ + pass + + +# Register command apps (migrated to Typer) +app.add_typer(status_app, name="status", help="Show current library configuration") +app.add_typer(list_app, name="list", help="List available KiCad libraries") +app.add_typer(init_app, name="init", help="Initialize library configuration") + +# TODO: Migrate remaining commands to Typer +# - setup: Configure KiCad to use libraries +# - pin/unpin: Pin/unpin favorite libraries +# - add-3d: Add 3D model libraries +# - config: Manage configuration settings +# - sync: Update/sync library content +# - update: Update KiLM itself +# - add-hook: Add project hooks +# - template: Manage project templates + + +if __name__ == "__main__": + app() diff --git a/kicad_lib_manager/utils/template.py b/kicad_lib_manager/utils/template.py index 6e32a32..03b2c8e 100644 --- a/kicad_lib_manager/utils/template.py +++ b/kicad_lib_manager/utils/template.py @@ -626,8 +626,8 @@ def post_create(context): # readme_path = os.path.join(context["project_dir"], "README.md") # if not os.path.exists(readme_path): # with Path(readme_path).open("w") as f: - # f.write(f"# {context['variables']['project_name']}\\n\\n") - # f.write("Created with KiCad Library Manager\\n") + # f.write(f"# {context['variables']['project_name']}\n\n") + # f.write("Created with KiCad Library Manager\n") # Print message to user click.echo(f"Project {context['variables']['project_name']} created successfully!") diff --git a/pyproject.toml b/pyproject.toml index b98e47a..42950fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,6 +44,8 @@ keywords = [ requires-python = ">=3.8" dependencies = [ "click>=8.0", + "typer>=0.17.4", + "rich>=14.0.0", "packaging>=25.0", "pyyaml>=6.0", "pathlib>=1.0.1", @@ -72,7 +74,7 @@ Repository = "https://github.com/barisgit/KiLM" [project.scripts] kilm = "kicad_lib_manager.cli:main" -kicad-lib-manager = "kicad_lib_manager.cli:main" +kilm-typer = "kicad_lib_manager.main:app" [tool.hatch.build.targets.wheel] From f8704162fcd7a5a411d604296abfb6b19e6e92c7 Mon Sep 17 00:00:00 2001 From: barisgit Date: Sat, 6 Sep 2025 21:19:31 +0200 Subject: [PATCH 02/13] Restructure codebase: move files to services/utils organization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Major refactoring to improve code organization and maintainability: **File Reorganization:** • Move constants.py → utils/constants.py • Move config.py → services/config_service.py (consolidated) • Move library_manager.py → services/library_service.py (consolidated) • Move auto_update.py → services/update_service.py **Code Quality Improvements:** • Convert standalone functions to static methods in service classes • Fix all import statements across commands and services • Maintain comprehensive type hints and professional standards • Preserve main.py as entry point, migrate from cli.py to Typer **Architecture Benefits:** • Clean separation: services (business logic) vs utils (utilities) • Better type safety with consolidated service layer • Static methods provide better organization than plain functions • Follows SOLID principles and professional code standards **Breaking Changes:** • CLI entry point moved from cli.py to main.py • Functions converted to static methods (LibraryService.method_name) • Import paths updated for moved modules Note: Tests will be updated in follow-up commit 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude --- .gitignore | 3 +- kicad_lib_manager/__main__.py | 4 +- kicad_lib_manager/cli.py | 50 -- kicad_lib_manager/commands/add_3d/command.py | 2 +- kicad_lib_manager/commands/config/command.py | 2 +- kicad_lib_manager/commands/init/__init__.py | 1 + kicad_lib_manager/commands/init/command.py | 208 +++---- .../commands/list_libraries/command.py | 8 +- kicad_lib_manager/commands/pin/__init__.py | 1 + kicad_lib_manager/commands/pin/command.py | 56 +- kicad_lib_manager/commands/setup/command.py | 8 +- kicad_lib_manager/commands/status/command.py | 27 +- kicad_lib_manager/commands/sync/command.py | 2 +- .../commands/template/command.py | 2 +- kicad_lib_manager/commands/unpin/command.py | 4 +- kicad_lib_manager/commands/update/command.py | 2 +- kicad_lib_manager/interfaces/__init__.py | 1 + .../interfaces/config_service.py | 55 ++ kicad_lib_manager/interfaces/kicad_service.py | 60 ++ .../interfaces/library_service.py | 68 +++ kicad_lib_manager/library_manager.py | 405 ------------- kicad_lib_manager/main.py | 6 +- kicad_lib_manager/services/__init__.py | 1 + .../{config.py => services/config_service.py} | 65 ++- kicad_lib_manager/services/kicad_service.py | 103 ++++ kicad_lib_manager/services/library_service.py | 544 ++++++++++++++++++ .../update_service.py} | 31 + kicad_lib_manager/{ => utils}/constants.py | 0 kicad_lib_manager/utils/env_vars.py | 2 +- kicad_lib_manager/utils/metadata.py | 2 +- kicad_lib_manager/utils/template.py | 2 +- pyproject.toml | 3 +- tests/test_config_commands.py | 2 +- tests/test_library_manager.py | 2 +- 34 files changed, 1092 insertions(+), 640 deletions(-) delete mode 100644 kicad_lib_manager/cli.py create mode 100644 kicad_lib_manager/interfaces/__init__.py create mode 100644 kicad_lib_manager/interfaces/config_service.py create mode 100644 kicad_lib_manager/interfaces/kicad_service.py create mode 100644 kicad_lib_manager/interfaces/library_service.py delete mode 100644 kicad_lib_manager/library_manager.py create mode 100644 kicad_lib_manager/services/__init__.py rename kicad_lib_manager/{config.py => services/config_service.py} (87%) create mode 100644 kicad_lib_manager/services/kicad_service.py create mode 100644 kicad_lib_manager/services/library_service.py rename kicad_lib_manager/{auto_update.py => services/update_service.py} (87%) rename kicad_lib_manager/{ => utils}/constants.py (100%) diff --git a/.gitignore b/.gitignore index 41c9af8..823e6aa 100644 --- a/.gitignore +++ b/.gitignore @@ -46,4 +46,5 @@ test_template/ TODO.md CLAUDE.md -.claude/ \ No newline at end of file +.claude/ +temp*/ \ No newline at end of file diff --git a/kicad_lib_manager/__main__.py b/kicad_lib_manager/__main__.py index add54db..840bbfa 100644 --- a/kicad_lib_manager/__main__.py +++ b/kicad_lib_manager/__main__.py @@ -2,7 +2,7 @@ Entry point for running the package as a module """ -from .cli import main +from .main import app if __name__ == "__main__": - main() + app() diff --git a/kicad_lib_manager/cli.py b/kicad_lib_manager/cli.py deleted file mode 100644 index 90d95d7..0000000 --- a/kicad_lib_manager/cli.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python3 -""" -Command-line interface for KiCad Library Manager -""" - -import importlib.metadata - -import click - -from .commands.add_3d import add_3d -from .commands.add_hook import add_hook -from .commands.config import config -from .commands.init import init -from .commands.list_libraries import list_cmd -from .commands.pin import pin -from .commands.setup import setup -from .commands.status import status -from .commands.sync import sync -from .commands.template import template -from .commands.unpin import unpin -from .commands.update import update - - -@click.group() -@click.version_option(version=importlib.metadata.version("kilm")) -def main(): - """KiCad Library Manager - Manage KiCad libraries - - This tool helps configure and manage KiCad libraries across your projects. - """ - pass - - -# Register commands -main.add_command(setup) -main.add_command(list_cmd, name="list") -main.add_command(status) -main.add_command(pin) -main.add_command(unpin) -main.add_command(init) -main.add_command(add_3d) -main.add_command(config) -main.add_command(sync) -main.add_command(update) -main.add_command(add_hook) -main.add_command(template) - - -if __name__ == "__main__": - main() diff --git a/kicad_lib_manager/commands/add_3d/command.py b/kicad_lib_manager/commands/add_3d/command.py index 84f2f76..10e94ae 100644 --- a/kicad_lib_manager/commands/add_3d/command.py +++ b/kicad_lib_manager/commands/add_3d/command.py @@ -7,7 +7,7 @@ import click -from ...config import Config +from ...services.config_service import Config from ...utils.metadata import ( CLOUD_METADATA_FILE, generate_env_var_name, diff --git a/kicad_lib_manager/commands/config/command.py b/kicad_lib_manager/commands/config/command.py index 1b59c38..73f32c7 100644 --- a/kicad_lib_manager/commands/config/command.py +++ b/kicad_lib_manager/commands/config/command.py @@ -8,7 +8,7 @@ import click -from ...config import Config +from ...services.config_service import Config from ...utils.metadata import ( CLOUD_METADATA_FILE, GITHUB_METADATA_FILE, diff --git a/kicad_lib_manager/commands/init/__init__.py b/kicad_lib_manager/commands/init/__init__.py index c2fb785..30d926c 100644 --- a/kicad_lib_manager/commands/init/__init__.py +++ b/kicad_lib_manager/commands/init/__init__.py @@ -1,4 +1,5 @@ import typer + from .command import init # Create Typer app and add the init command as callback diff --git a/kicad_lib_manager/commands/init/command.py b/kicad_lib_manager/commands/init/command.py index dcf6513..e52cdcd 100644 --- a/kicad_lib_manager/commands/init/command.py +++ b/kicad_lib_manager/commands/init/command.py @@ -11,14 +11,8 @@ from rich.panel import Panel from rich.prompt import Confirm -from ...config import Config -from ...utils.metadata import ( - GITHUB_METADATA_FILE, - generate_env_var_name, - get_default_github_metadata, - read_github_metadata, - write_github_metadata, -) +from ...services.config_service import Config +from ...services.library_service import LibraryService console = Console() @@ -79,111 +73,52 @@ def init( • Generates metadata file with library information • Assigns unique environment variable for KiCad integration • Registers library in KiLM configuration - - [bold]Note:[/bold] This is intended for GitHub-based libraries containing + + [bold]Note:[/bold] This is intended for GitHub-based libraries containing symbols and footprints, not for 3D model libraries. """ current_dir = Path.cwd().resolve() - - console.print(Panel( - f"[bold blue]Initializing KiCad library[/bold blue]\n" - f"[cyan]Location:[/cyan] {current_dir}", - title="KiLM Library Initialization", - border_style="blue" - )) - # Check for existing metadata - metadata = read_github_metadata(current_dir) + console.print( + Panel( + f"[bold blue]Initializing KiCad library[/bold blue]\n" + f"[cyan]Location:[/cyan] {current_dir}", + title="KiLM Library Initialization", + border_style="blue", + ) + ) + + # Use library service to initialize + library_service = LibraryService() + try: + metadata = library_service.initialize_library( + directory=current_dir, + name=name, + description=description, + env_var=env_var, + force=force, + no_env_var=no_env_var, + ) - if metadata and not force: - console.print(f"[green]Found existing metadata file[/green] ([cyan]{GITHUB_METADATA_FILE}[/cyan])") library_name = metadata.get("name") - library_description = metadata.get("description") library_env_var = metadata.get("env_var") - console.print(f"[blue]Using existing name:[/blue] {library_name}") - - # Show environment variable if present - if library_env_var and not no_env_var: - console.print(f"[blue]Using existing environment variable:[/blue] {library_env_var}") - - # Override with command line parameters if provided - if name: - library_name = name - console.print(f"[yellow]Overriding with provided name:[/yellow] {library_name}") - - if description: - library_description = description - console.print(f"[yellow]Overriding with provided description:[/yellow] {library_description}") - - if env_var: - library_env_var = env_var - console.print(f"[yellow]Overriding with provided environment variable:[/yellow] {library_env_var}") - elif no_env_var: - library_env_var = None - console.print("[yellow]Disabling environment variable as requested[/yellow]") - - # Update metadata if command line parameters were provided - if name or description or env_var or no_env_var: - if library_name is not None: - metadata["name"] = library_name - if library_description is not None: - metadata["description"] = library_description - if library_env_var and not no_env_var: - metadata["env_var"] = library_env_var - else: - # Don't set env_var if not needed - pass - metadata["updated_with"] = "kilm" - write_github_metadata(current_dir, metadata) - console.print("[green]Updated metadata file with new information.[/green]") - else: - # Create a new metadata file - if metadata and force: - console.print(f"[yellow]Overwriting existing metadata file[/yellow] ([cyan]{GITHUB_METADATA_FILE}[/cyan])") - else: - console.print(f"[green]Creating new metadata file[/green] ([cyan]{GITHUB_METADATA_FILE}[/cyan])") - - # Generate metadata - metadata = get_default_github_metadata(current_dir) - - # Override with command line parameters if provided - if name: - metadata["name"] = name - # If name is provided but env_var isn't, regenerate the env_var based on the new name - if not env_var and not no_env_var: - metadata["env_var"] = generate_env_var_name(name, "KICAD_LIB") - if description: - metadata["description"] = description + # Get the directory status + existing_folders = [] + created_folders = [] + capabilities = metadata.get("capabilities", {}) - if env_var: - metadata["env_var"] = env_var - elif no_env_var: - metadata["env_var"] = None + for folder_type, exists in capabilities.items(): + if exists: + folder_path = current_dir / folder_type + if folder_path.exists(): + existing_folders.append(folder_type) + else: + created_folders.append(folder_type) - # Write metadata file - write_github_metadata(current_dir, metadata) - console.print("[green]Metadata file created.[/green]") - - library_name = metadata["name"] - library_env_var = metadata.get("env_var") - - # Create library directory structure if folders don't exist - required_folders = ["symbols", "footprints", "templates"] - existing_folders = [] - created_folders = [] - - for folder in required_folders: - folder_path = current_dir / folder - if folder_path.exists(): - existing_folders.append(folder) - else: - try: - folder_path.mkdir(parents=True, exist_ok=True) - created_folders.append(folder) - except Exception as e: - console.print(f"[red]Error creating {folder} directory: {e}[/red]") - raise typer.Exit(1) + except Exception as e: + console.print(f"[red]Error initializing library: {e}[/red]") + raise typer.Exit(1) from e # Create empty library_descriptions.yaml if it doesn't exist library_descriptions_file = current_dir / "library_descriptions.yaml" @@ -207,28 +142,31 @@ def init( """ with library_descriptions_file.open("w", encoding="utf-8") as f: f.write(template_content) - console.print("[green]Created library_descriptions.yaml template file.[/green]") + console.print( + "[green]Created library_descriptions.yaml template file.[/green]" + ) except Exception as e: - console.print(f"[yellow]Warning: Could not create library_descriptions.yaml file: {e}[/yellow]") + console.print( + f"[yellow]Warning: Could not create library_descriptions.yaml file: {e}[/yellow]" + ) - # Update the metadata with current capabilities - updated_capabilities = { - "symbols": (current_dir / "symbols").exists(), - "footprints": (current_dir / "footprints").exists(), - "templates": (current_dir / "templates").exists(), - } - metadata["capabilities"] = updated_capabilities - write_github_metadata(current_dir, metadata) + # Metadata is already updated by the service # Report on folder status if existing_folders: - console.print(f"[blue]Found existing folders:[/blue] {', '.join(existing_folders)}") + console.print( + f"[blue]Found existing folders:[/blue] {', '.join(existing_folders)}" + ) if created_folders: - console.print(f"[green]Created new folders:[/green] {', '.join(created_folders)}") + console.print( + f"[green]Created new folders:[/green] {', '.join(created_folders)}" + ) # Verify if this looks like a KiCad library if not created_folders and not existing_folders: - console.print("[yellow]Warning: No library folders were found or created.[/yellow]") + console.print( + "[yellow]Warning: No library folders were found or created.[/yellow]" + ) if not Confirm.ask("Continue anyway?", default=True): console.print("[yellow]Initialization cancelled.[/yellow]") raise typer.Exit(0) @@ -245,27 +183,39 @@ def init( # Create success panel success_content = f"[bold green]Library '{safe_library_name}' initialized successfully![/bold green]\n\n" - success_content += f"[cyan]Type:[/cyan] GitHub library (symbols, footprints, templates)\n" + success_content += ( + "[cyan]Type:[/cyan] GitHub library (symbols, footprints, templates)\n" + ) success_content += f"[cyan]Path:[/cyan] {current_dir}\n" if library_env_var: success_content += f"[cyan]Environment Variable:[/cyan] {library_env_var}\n" if set_current: - success_content += f"\n[yellow]This is now your current active library.[/yellow]\n" - success_content += f"[dim]KiLM will use this library for all commands by default.[/dim]" - - console.print(Panel( - success_content, - title="✅ Initialization Complete", - border_style="green" - )) + success_content += ( + "\n[yellow]This is now your current active library.[/yellow]\n" + ) + success_content += ( + "[dim]KiLM will use this library for all commands by default.[/dim]" + ) + + console.print( + Panel( + success_content, + title="✅ Initialization Complete", + border_style="green", + ) + ) # Add a hint for adding 3D models console.print("\n[bold]Next Steps:[/bold]") - console.print("To add a 3D models directory (typically stored in the cloud), use:") - console.print("[dim] kilm add-3d --name my-3d-models --directory /path/to/3d/models[/dim]") - + console.print( + "To add a 3D models directory (typically stored in the cloud), use:" + ) + console.print( + "[dim] kilm add-3d --name my-3d-models --directory /path/to/3d/models[/dim]" + ) + except Exception as e: console.print(f"[red]Error initializing library: {e}[/red]") - raise typer.Exit(1) + raise typer.Exit(1) from e diff --git a/kicad_lib_manager/commands/list_libraries/command.py b/kicad_lib_manager/commands/list_libraries/command.py index 17e9533..334c181 100644 --- a/kicad_lib_manager/commands/list_libraries/command.py +++ b/kicad_lib_manager/commands/list_libraries/command.py @@ -2,13 +2,14 @@ List command implementation for KiCad Library Manager (Typer version). """ +from pathlib import Path from typing import Annotated, Optional import typer from rich.console import Console from rich.table import Table -from ...library_manager import list_libraries +from ...services.library_service import LibraryService from ...utils.env_vars import expand_user_path, find_environment_variables console = Console() @@ -41,7 +42,8 @@ def list_cmd( kicad_lib_dir = expand_user_path(kicad_lib_dir) try: - symbols, footprints = list_libraries(kicad_lib_dir) + library_service = LibraryService() + symbols, footprints = library_service.list_libraries(Path(kicad_lib_dir)) console.print(f"[blue]Scanning library directory:[/blue] {kicad_lib_dir}\n") @@ -96,4 +98,4 @@ def list_cmd( except Exception as e: console.print(f"[red]Error listing libraries: {e}[/red]") - raise typer.Exit(1) + raise typer.Exit(1) from e diff --git a/kicad_lib_manager/commands/pin/__init__.py b/kicad_lib_manager/commands/pin/__init__.py index 0c7e6ca..24e32dc 100644 --- a/kicad_lib_manager/commands/pin/__init__.py +++ b/kicad_lib_manager/commands/pin/__init__.py @@ -1,4 +1,5 @@ import typer + from .command import pin # Create Typer app and add the pin command as callback diff --git a/kicad_lib_manager/commands/pin/command.py b/kicad_lib_manager/commands/pin/command.py index 2379d8d..a87468e 100644 --- a/kicad_lib_manager/commands/pin/command.py +++ b/kicad_lib_manager/commands/pin/command.py @@ -2,6 +2,7 @@ Pin command implementation for KiCad Library Manager (Typer version). """ +from pathlib import Path from typing import Annotated, List, Optional import typer @@ -9,7 +10,8 @@ from rich.panel import Panel from rich.table import Table -from ...library_manager import find_kicad_config, list_libraries +from ...services.kicad_service import KiCadService +from ...services.library_service import LibraryService from ...utils.env_vars import ( expand_user_path, find_environment_variables, @@ -29,7 +31,7 @@ def pin( ), ] = None, symbols: Annotated[ - List[str], + Optional[List[str]], typer.Option( "--symbols", "-s", @@ -37,7 +39,7 @@ def pin( ), ] = None, footprints: Annotated[ - List[str], + Optional[List[str]], typer.Option( "--footprints", "-f", @@ -76,7 +78,7 @@ def pin( ) -> None: """ Pin libraries in KiCad for quick access. - + This command pins libraries in KiCad's interface for quick access. You can pin specific symbol and footprint libraries or all available libraries. """ @@ -85,7 +87,7 @@ def pin( symbols = [] if footprints is None: footprints = [] - + # Find environment variables if not provided if not kicad_lib_dir: kicad_lib_dir = find_environment_variables("KICAD_USER_LIB") @@ -99,9 +101,13 @@ def pin( if verbose: console.print(f"[blue]Using KiCad library directory:[/blue] {kicad_lib_dir}") + # Initialize services + library_service = LibraryService() + kicad_service = KiCadService() + # Find KiCad configuration try: - kicad_config = find_kicad_config() + kicad_config = kicad_service.find_kicad_config_dir() if verbose: console.print(f"[blue]Found KiCad configuration at:[/blue] {kicad_config}") except Exception as e: @@ -111,7 +117,9 @@ def pin( # If --all is specified, get all libraries from the directory if all_libs and not symbols and not footprints: try: - symbol_libs, footprint_libs = list_libraries(kicad_lib_dir) + symbol_libs, footprint_libs = library_service.list_libraries( + Path(kicad_lib_dir) + ) symbols = list(symbol_libs) footprints = list(footprint_libs) if verbose: @@ -131,17 +139,23 @@ def pin( # Validate that libraries exist if not all_libs and (symbols or footprints): try: - available_symbols, available_footprints = list_libraries(kicad_lib_dir) + available_symbols, available_footprints = library_service.list_libraries( + Path(kicad_lib_dir) + ) # Check symbols for symbol in symbols: if symbol not in available_symbols: - console.print(f"[yellow]Warning: Symbol library '{symbol}' not found[/yellow]") + console.print( + f"[yellow]Warning: Symbol library '{symbol}' not found[/yellow]" + ) # Check footprints for footprint in footprints: if footprint not in available_footprints: - console.print(f"[yellow]Warning: Footprint library '{footprint}' not found[/yellow]") + console.print( + f"[yellow]Warning: Footprint library '{footprint}' not found[/yellow]" + ) except Exception as e: console.print(f"[yellow]Error validating libraries: {e}[/yellow]") # Continue anyway, in case the libraries are configured but not in the directory @@ -162,15 +176,19 @@ def pin( ) else: success_msg = f"[green]Pinned {len(symbols)} symbol and {len(footprints)} footprint libraries in KiCad[/green]" - console.print(Panel( - f"{success_msg}\n\n" - f"[blue]• Created backup of kicad_common.json[/blue]\n" - f"[yellow]• Restart KiCad for changes to take effect[/yellow]", - title="✅ Libraries Pinned", - border_style="green" - )) + console.print( + Panel( + f"{success_msg}\n\n" + f"[blue]• Created backup of kicad_common.json[/blue]\n" + f"[yellow]• Restart KiCad for changes to take effect[/yellow]", + title="✅ Libraries Pinned", + border_style="green", + ) + ) else: - console.print("[blue]No changes needed, libraries already pinned in KiCad[/blue]") + console.print( + "[blue]No changes needed, libraries already pinned in KiCad[/blue]" + ) if verbose: if symbols: @@ -181,7 +199,7 @@ def pin( console.print(table) if footprints: - table = Table(title="Pinned Footprint Libraries") + table = Table(title="Pinned Footprint Libraries") table.add_column("Library", style="magenta") for footprint in sorted(footprints): table.add_row(footprint) diff --git a/kicad_lib_manager/commands/setup/command.py b/kicad_lib_manager/commands/setup/command.py index f6b0715..97f4f47 100644 --- a/kicad_lib_manager/commands/setup/command.py +++ b/kicad_lib_manager/commands/setup/command.py @@ -10,8 +10,8 @@ import click # TODO: Use full path (kicad_lib_manager...) -from ...config import Config, LibraryDict -from ...library_manager import add_libraries, find_kicad_config +from ...services.config_service import Config, LibraryDict +from ...services.library_service import LibraryService from ...utils.backup import create_backup from ...utils.env_vars import ( expand_user_path, @@ -367,7 +367,7 @@ def setup( # Find KiCad configuration try: - kicad_config = find_kicad_config() + kicad_config = LibraryService.find_kicad_config() click.echo(f"Found KiCad configuration at: {kicad_config}") # Fix any invalid URIs in existing library entries @@ -436,7 +436,7 @@ def setup( three_d_dirs["KICAD_3D_LIB"] = kicad_3d_dir # Call add_libraries with the main library and all 3D libraries - added_libraries, changes_needed = add_libraries( + added_libraries, changes_needed = LibraryService.add_libraries( kicad_lib_dir, kicad_config, kicad_3d_dir=kicad_3d_dir, diff --git a/kicad_lib_manager/commands/status/command.py b/kicad_lib_manager/commands/status/command.py index 3ccd4c0..bce1e48 100644 --- a/kicad_lib_manager/commands/status/command.py +++ b/kicad_lib_manager/commands/status/command.py @@ -12,7 +12,7 @@ from rich.table import Table from rich.text import Text -from ...library_manager import find_kicad_config, list_configured_libraries +from ...services.kicad_service import KiCadService from ...utils.metadata import read_cloud_metadata, read_github_metadata console = Console() @@ -21,22 +21,25 @@ def status() -> None: """Show the current KiCad configuration status""" try: + # Initialize services + kicad_service = KiCadService() + # Show KILM configuration first _show_kilm_configuration() console.print("\n[bold cyan]KiCad Configuration[/bold cyan]") - kicad_config = find_kicad_config() + kicad_config = kicad_service.find_kicad_config_dir() console.print(f"KiCad configuration directory: [blue]{kicad_config}[/blue]") # Check environment variables in KiCad common _show_kicad_environment_variables(kicad_config) # Check pinned libraries - _check_pinned_libraries(kicad_config) + _check_pinned_libraries(kicad_config, kicad_service) # Check configured libraries - _show_configured_libraries(kicad_config) + _show_configured_libraries(kicad_config, kicad_service) except Exception as e: console.print(f"[red]Error getting KiCad configuration: {e}[/red]") @@ -53,8 +56,13 @@ def _show_kilm_configuration() -> None: with config_file.open() as f: config_data = yaml.safe_load(f) - _show_configured_libraries_table(config_data) - _show_kilm_settings(config_data) + if config_data is not None: + _show_configured_libraries_table(config_data) + _show_kilm_settings(config_data) + else: + console.print( + "[yellow]Configuration file is empty or invalid[/yellow]" + ) except Exception as e: console.print(f"[red]Error reading configuration: {e}[/red]") @@ -180,8 +188,9 @@ def _show_kicad_environment_variables(kicad_config: Path) -> None: console.print(f"[red]Error reading KiCad common configuration: {e}[/red]") -def _check_pinned_libraries(kicad_config: Path) -> None: +def _check_pinned_libraries(kicad_config: Path, kicad_service: KiCadService) -> None: """Check and display pinned libraries""" + _ = kicad_service # Suppress unused warning, TODO: implement functionality kicad_common = kicad_config / "kicad_common.json" if kicad_common.exists(): try: @@ -260,10 +269,10 @@ def _check_pinned_libraries(kicad_config: Path) -> None: console.print("\n[yellow]No pinned libraries file found[/yellow]") -def _show_configured_libraries(kicad_config: Path) -> None: +def _show_configured_libraries(kicad_config: Path, kicad_service: KiCadService) -> None: """Show configured libraries in KiCad""" try: - sym_libs, fp_libs = list_configured_libraries(kicad_config) + sym_libs, fp_libs = kicad_service.get_configured_libraries(kicad_config) console.print("\n[bold]Configured Symbol Libraries:[/bold]") if sym_libs: diff --git a/kicad_lib_manager/commands/sync/command.py b/kicad_lib_manager/commands/sync/command.py index b5ad7d9..70bdc71 100644 --- a/kicad_lib_manager/commands/sync/command.py +++ b/kicad_lib_manager/commands/sync/command.py @@ -8,7 +8,7 @@ import click -from ...config import Config +from ...services.config_service import Config @click.command() diff --git a/kicad_lib_manager/commands/template/command.py b/kicad_lib_manager/commands/template/command.py index d6bf8bb..737ea1e 100644 --- a/kicad_lib_manager/commands/template/command.py +++ b/kicad_lib_manager/commands/template/command.py @@ -16,7 +16,7 @@ import questionary import yaml -from ...config import Config +from ...services.config_service import Config from ...utils.template import ( HOOKS_DIR, POST_CREATE_HOOK, diff --git a/kicad_lib_manager/commands/unpin/command.py b/kicad_lib_manager/commands/unpin/command.py index 0db172c..c299ff6 100644 --- a/kicad_lib_manager/commands/unpin/command.py +++ b/kicad_lib_manager/commands/unpin/command.py @@ -7,7 +7,7 @@ import click -from ...library_manager import find_kicad_config +from ...services.library_service import LibraryService from ...utils.backup import create_backup @@ -56,7 +56,7 @@ def unpin(symbols, footprints, all, dry_run, max_backups, verbose): # Find KiCad configuration try: - kicad_config = find_kicad_config() + kicad_config = LibraryService.find_kicad_config() if verbose: click.echo(f"Found KiCad configuration at: {kicad_config}") except Exception as e: diff --git a/kicad_lib_manager/commands/update/command.py b/kicad_lib_manager/commands/update/command.py index 7f8c764..85d5ec5 100644 --- a/kicad_lib_manager/commands/update/command.py +++ b/kicad_lib_manager/commands/update/command.py @@ -7,7 +7,7 @@ import click -from ...auto_update import UpdateManager +from ...services.update_service import UpdateManager @click.command() diff --git a/kicad_lib_manager/interfaces/__init__.py b/kicad_lib_manager/interfaces/__init__.py new file mode 100644 index 0000000..9f5a2aa --- /dev/null +++ b/kicad_lib_manager/interfaces/__init__.py @@ -0,0 +1 @@ +"""Service interfaces for KiCad Library Manager.""" diff --git a/kicad_lib_manager/interfaces/config_service.py b/kicad_lib_manager/interfaces/config_service.py new file mode 100644 index 0000000..f00cfb1 --- /dev/null +++ b/kicad_lib_manager/interfaces/config_service.py @@ -0,0 +1,55 @@ +""" +Configuration service protocol interface for KiCad Library Manager. +""" + +from abc import abstractmethod +from pathlib import Path +from typing import Dict, List, Optional, Protocol + + +class ConfigServiceProtocol(Protocol): + """Protocol for configuration management services.""" + + @abstractmethod + def get_config_file_path(self) -> Path: + """Get the path to the KiLM configuration file.""" + + @abstractmethod + def load_config(self) -> Dict: + """Load the KiLM configuration.""" + + @abstractmethod + def save_config(self, config: Dict) -> None: + """Save the KiLM configuration.""" + + @abstractmethod + def add_library(self, name: str, path: str, library_type: str) -> None: + """Add a library to the configuration.""" + + @abstractmethod + def remove_library(self, name: str) -> None: + """Remove a library from the configuration.""" + + @abstractmethod + def get_libraries(self) -> List[Dict]: + """Get all configured libraries.""" + + @abstractmethod + def get_library_by_name(self, name: str) -> Optional[Dict]: + """Get a specific library by name.""" + + @abstractmethod + def get_current_library(self) -> Optional[str]: + """Get the current active library path.""" + + @abstractmethod + def set_current_library(self, path: str) -> None: + """Set the current active library.""" + + @abstractmethod + def get_max_backups(self) -> int: + """Get the maximum number of backups to keep.""" + + @abstractmethod + def set_max_backups(self, count: int) -> None: + """Set the maximum number of backups to keep.""" diff --git a/kicad_lib_manager/interfaces/kicad_service.py b/kicad_lib_manager/interfaces/kicad_service.py new file mode 100644 index 0000000..a7fcbee --- /dev/null +++ b/kicad_lib_manager/interfaces/kicad_service.py @@ -0,0 +1,60 @@ +""" +KiCad service protocol interface for KiCad Library Manager. +""" + +from abc import abstractmethod +from pathlib import Path +from typing import Dict, List, Optional, Protocol, Tuple + + +class KiCadServiceProtocol(Protocol): + """Protocol for KiCad configuration and management services.""" + + @abstractmethod + def find_kicad_config_dir(self) -> Path: + """Find the KiCad configuration directory.""" + + @abstractmethod + def get_environment_variables(self, config_dir: Path) -> Dict[str, str]: + """Get KiCad environment variables from configuration.""" + + @abstractmethod + def set_environment_variables( + self, + config_dir: Path, + env_vars: Dict[str, str], + backup: bool = True, + max_backups: int = 5, + ) -> bool: + """Set KiCad environment variables.""" + + @abstractmethod + def get_configured_libraries( + self, config_dir: Path + ) -> Tuple[List[Dict], List[Dict]]: + """ + Get configured symbol and footprint libraries. + + Returns: + Tuple of (symbol_libraries, footprint_libraries) + """ + + @abstractmethod + def add_libraries_to_kicad( + self, + config_dir: Path, + symbol_libs: Optional[List[Dict]] = None, + footprint_libs: Optional[List[Dict]] = None, + backup: bool = True, + max_backups: int = 5, + ) -> bool: + """Add libraries to KiCad library tables.""" + + @abstractmethod + def get_pinned_libraries(self, config_dir: Path) -> Tuple[List[str], List[str]]: + """ + Get pinned libraries from KiCad configuration. + + Returns: + Tuple of (symbol_libraries, footprint_libraries) + """ diff --git a/kicad_lib_manager/interfaces/library_service.py b/kicad_lib_manager/interfaces/library_service.py new file mode 100644 index 0000000..0401d35 --- /dev/null +++ b/kicad_lib_manager/interfaces/library_service.py @@ -0,0 +1,68 @@ +""" +Library service protocol interface for KiCad Library Manager. +""" + +from abc import abstractmethod +from pathlib import Path +from typing import Any, Dict, List, Optional, Protocol, Tuple + + +class LibraryServiceProtocol(Protocol): + """Protocol for library management services.""" + + @abstractmethod + def list_libraries(self, directory: Path) -> Tuple[List[str], List[str]]: + """ + List symbol and footprint libraries in a directory. + + Returns: + Tuple of (symbol_libraries, footprint_libraries) + """ + + @abstractmethod + def initialize_library( + self, + directory: Path, + name: Optional[str] = None, + description: Optional[str] = None, + env_var: Optional[str] = None, + force: bool = False, + no_env_var: bool = False, + ) -> Dict[str, Any]: + """Initialize a library in the given directory.""" + + @abstractmethod + def get_library_metadata(self, directory: Path) -> Optional[Dict[str, Any]]: + """Get metadata for a library directory.""" + + @abstractmethod + def pin_libraries( + self, + symbol_libs: List[str], + footprint_libs: List[str], + kicad_config_dir: Path, + dry_run: bool = False, + max_backups: int = 5, + ) -> bool: + """ + Pin libraries in KiCad for quick access. + + Returns: + True if changes were made, False otherwise + """ + + @abstractmethod + def unpin_libraries( + self, + symbol_libs: List[str], + footprint_libs: List[str], + kicad_config_dir: Path, + dry_run: bool = False, + max_backups: int = 5, + ) -> bool: + """ + Unpin libraries in KiCad. + + Returns: + True if changes were made, False otherwise + """ diff --git a/kicad_lib_manager/library_manager.py b/kicad_lib_manager/library_manager.py deleted file mode 100644 index 8e0b9ed..0000000 --- a/kicad_lib_manager/library_manager.py +++ /dev/null @@ -1,405 +0,0 @@ -""" -Core functionality for managing KiCad libraries -""" - -import os -import platform -from pathlib import Path -from typing import Dict, List, Optional, Set, Tuple - -import yaml - -from .utils.env_vars import expand_user_path -from .utils.file_ops import ( - list_configured_libraries, - list_libraries, - validate_lib_table, -) - - -def find_kicad_config() -> Path: - """ - Find the KiCad configuration directory for the current platform - - Returns: - Path to the KiCad configuration directory - - Raises: - FileNotFoundError: If KiCad configuration directory is not found - """ - system = platform.system() - - if system == "Darwin": # macOS - config_dir = Path.home() / "Library" / "Preferences" / "kicad" - elif system == "Linux": - config_dir = Path.home() / ".config" / "kicad" - elif system == "Windows": - appdata = os.environ.get("APPDATA") - if not appdata: - raise FileNotFoundError("APPDATA environment variable not found") - config_dir = Path(appdata) / "kicad" - else: - raise FileNotFoundError(f"Unsupported platform: {system}") - - if not config_dir.exists(): - raise FileNotFoundError( - f"KiCad configuration directory not found at {config_dir}. " - "Please run KiCad at least once before using this tool." - ) - - # Find the most recent KiCad version directory - version_dirs = [d for d in config_dir.iterdir() if d.is_dir()] - if not version_dirs: - raise FileNotFoundError( - f"No KiCad version directories found in {config_dir}. " - "Please run KiCad at least once before using this tool." - ) - - # Sort directories by version number (assuming directories with numbers are version dirs) - version_dirs = [d for d in version_dirs if any(c.isdigit() for c in d.name)] - if not version_dirs: - raise FileNotFoundError( - f"No KiCad version directories found in {config_dir}. " - "Please run KiCad at least once before using this tool." - ) - - latest_dir = sorted(version_dirs, key=lambda d: d.name)[-1] - - # Check for required files - sym_table = latest_dir / "sym-lib-table" - fp_table = latest_dir / "fp-lib-table" - - if not sym_table.exists() and not fp_table.exists(): - raise FileNotFoundError( - f"KiCad library tables not found in {latest_dir}. " - "Please run KiCad at least once before using this tool." - ) - - return latest_dir - - -def get_library_description(lib_type: str, lib_name: str, kicad_lib_dir: str) -> str: - """ - Get a description for a library from the YAML file or generate a default one - - Args: - lib_type: Either 'symbols' or 'footprints' - lib_name: The name of the library - kicad_lib_dir: The KiCad library directory - - Returns: - A description for the library - """ - yaml_file = Path(kicad_lib_dir) / "library_descriptions.yaml" - - # Check if YAML file exists - if yaml_file.exists(): - try: - with yaml_file.open() as f: - data = yaml.safe_load(f) - - if ( - data - and isinstance(data, dict) - and lib_type in data - and isinstance(data[lib_type], dict) - and lib_name in data[lib_type] - ): - return data[lib_type][lib_name] - except Exception: - pass - - # Default description if YAML file doesn't exist or doesn't contain the library - if lib_type == "symbols": - return f"{lib_name} symbol library" - else: - return f"{lib_name} footprint library" - - -def format_uri(base_path: str, lib_name: str, lib_type: str) -> str: - """ - Format a URI for a KiCad library. - - Args: - base_path: The base path to the library directory - lib_name: The name of the library - lib_type: The type of library (symbols or footprints) - - Returns: - The formatted URI string - - Raises: - ValueError: If base_path is empty, lib_type is invalid, or path format is invalid - """ - if not base_path: - raise ValueError("Base path cannot be empty") - - if lib_type not in ["symbols", "footprints"]: - raise ValueError(f"Invalid library type: {lib_type}") - - # Validate ${...} format if present - if base_path.startswith("${") and not base_path.endswith("}"): - raise ValueError(f"Invalid environment variable format: {base_path}") - - # Helper function to check if a path is absolute - def is_absolute_path(path: str) -> bool: - return ( - path.startswith("/") # Unix-style - or path.startswith("\\") # Windows-style with backslash - or (len(path) > 1 and path[1] == ":") # Windows-style with drive letter - ) - - # Normalize path separators to forward slashes first - base_path = base_path.replace("\\", "/") - - # Check if the path is already in ${...} format - if base_path.startswith("${") and base_path.endswith("}"): - # Extract the path from inside the curly braces - path = base_path[2:-1] - if is_absolute_path(path): - # If it's an absolute path, remove the ${...} wrapper - base_path = path - # Otherwise, keep the ${...} wrapper for environment variables - else: - # If it's not in ${...} format, check if it's an absolute path - if not is_absolute_path(base_path): - # If it's not an absolute path, treat it as an environment variable - base_path = f"${{{base_path}}}" - - # Construct the URI based on library type - if lib_type == "symbols": - return f"{base_path}/symbols/{lib_name}.kicad_sym" - else: - return f"{base_path}/footprints/{lib_name}.pretty" - - -def add_libraries( - kicad_lib_dir: str, - kicad_config: Path, - kicad_3d_dir: Optional[str] = None, - additional_3d_dirs: Optional[Dict[str, str]] = None, - dry_run: bool = False, -) -> Tuple[Set[str], bool]: - """ - Add KiCad libraries to the configuration. - - Args: - kicad_lib_dir: Path to the KiCad library directory - kicad_config: Path to the KiCad configuration directory - kicad_3d_dir: Path to the KiCad 3D models directory (optional) - additional_3d_dirs: Dictionary of additional 3D model directories with their - environment variable names as keys (optional) - dry_run: If True, don't actually make any changes - - Returns: - Tuple of (set of libraries added, whether changes were needed) - - Raises: - FileNotFoundError: If the library directory does not exist - ValueError: If the library directory does not contain symbols or footprints - """ - # Check if library directory exists - # First expand any environment variables in the path - if kicad_lib_dir.startswith("${") and kicad_lib_dir.endswith("}"): - env_var = kicad_lib_dir[2:-1] - if env_var in os.environ: - kicad_lib_dir = os.environ[env_var] - else: - raise FileNotFoundError(f"Environment variable {env_var} not found") - # Check if it's NOT an absolute path (Unix/Windows) or UNC path (Windows) - # and treat it as a potential environment variable name if it's not. - elif not ( - kicad_lib_dir.startswith("/") - or ( - len(kicad_lib_dir) > 2 and kicad_lib_dir[1] == ":" - ) # Check for C: style paths - or (kicad_lib_dir.startswith("\\\\")) # Check for UNC paths like \\server\share - ): - # If it's an environment variable name without ${} - if kicad_lib_dir in os.environ: - kicad_lib_dir = os.environ[kicad_lib_dir] - else: - raise FileNotFoundError(f"Environment variable {kicad_lib_dir} not found") - - # Now expand any user paths - kicad_lib_dir = expand_user_path(kicad_lib_dir) - lib_dir = Path(kicad_lib_dir) - if not lib_dir.exists(): - raise FileNotFoundError(f"KiCad library directory not found: {kicad_lib_dir}") - - # Check if 3D models directory exists - if kicad_3d_dir: - kicad_3d_dir = expand_user_path(kicad_3d_dir) - models_dir = Path(kicad_3d_dir) - if not models_dir.exists(): - raise FileNotFoundError( - f"KiCad 3D models directory not found: {kicad_3d_dir}" - ) - - # Check if additional 3D model directories exist - all_3d_dirs = {} - if kicad_3d_dir: - all_3d_dirs["KICAD_3D_LIB"] = kicad_3d_dir - - if additional_3d_dirs: - for env_var, path in additional_3d_dirs.items(): - path = expand_user_path(path) - dir_path = Path(path) - if not dir_path.exists(): - print(f"Warning: 3D models directory not found: {path} (skipping)") - continue - - # Only add if this is a different path than the main 3D models directory - if kicad_3d_dir and os.path.normpath(path) == os.path.normpath( - kicad_3d_dir - ): - continue - - all_3d_dirs[env_var] = path - - # Get list of available libraries - symbols, footprints = list_libraries(kicad_lib_dir) - if not symbols and not footprints: - raise ValueError(f"No libraries found in {kicad_lib_dir}") - - # Check if library tables exist - sym_table = kicad_config / "sym-lib-table" - fp_table = kicad_config / "fp-lib-table" - - # Get existing libraries - sym_libs, fp_libs = list_configured_libraries(kicad_config) - sym_lib_names = {lib["name"] for lib in sym_libs} - fp_lib_names = {lib["name"] for lib in fp_libs} - - # Check for new libraries - new_symbols = [lib for lib in symbols if lib not in sym_lib_names] - new_footprints = [lib for lib in footprints if lib not in fp_lib_names] - - # Generate variable references for 3D model paths - env_var_refs = {} - for env_var, path in all_3d_dirs.items(): - # Convert to format KiCad expects: ${ENV_VAR} - env_var_refs[path] = f"${{{env_var}}}" - - # Add new libraries to symbol table - sym_changes_needed = False - new_sym_entries = [] - for lib in new_symbols: - uri = format_uri(kicad_lib_dir, lib, "symbols") - - # Add the library with UTF-8 encoded description - new_sym_entries.append( - { - "name": lib, - "uri": uri, - "options": "", - "description": get_library_description("symbols", lib, kicad_lib_dir) - .encode("utf-8") - .decode("utf-8"), - } - ) - sym_changes_needed = True - - # Add new libraries to footprint table - fp_changes_needed = False - new_fp_entries = [] - for lib in new_footprints: - uri = format_uri(kicad_lib_dir, lib, "footprints") - - # Add the library with UTF-8 encoded description - new_fp_entries.append( - { - "name": lib, - "uri": uri, - "options": "", - "description": get_library_description("footprints", lib, kicad_lib_dir) - .encode("utf-8") - .decode("utf-8"), - } - ) - fp_changes_needed = True - - # Only make changes if needed - changes_needed = sym_changes_needed or fp_changes_needed - if changes_needed and not dry_run: - # Add new entries to symbol table - if sym_changes_needed: - add_entries_to_table(sym_table, new_sym_entries) - - # Add new entries to footprint table - if fp_changes_needed: - add_entries_to_table(fp_table, new_fp_entries) - - # Return the set of added libraries - added_libraries = set(new_symbols + new_footprints) - return added_libraries, changes_needed - - -def add_entries_to_table(table_path: Path, entries: List[Dict[str, str]]) -> None: - """ - Add entries to a KiCad library table file - - Args: - table_path: Path to the library table - entries: List of entries to add - """ - # Make sure the table exists and has a valid format - validate_lib_table(table_path, False) - - # Read existing content, ensuring UTF-8 encoding - with table_path.open(encoding="utf-8") as f: - content = f.read() - - # Find the last proper closing parenthesis of the table - closing_paren_index = -1 - lines = content.splitlines() - for i in range(len(lines) - 1, -1, -1): - if lines[i].strip() == ")": - closing_paren_index = i - break - - if closing_paren_index == -1: - raise ValueError( - f"Could not find closing parenthesis in library table: {table_path}" - ) - - # Insert new entries before the closing parenthesis - new_content = "" - for i, line in enumerate(lines): - if i == closing_paren_index: - # Insert entries before the closing parenthesis line - for entry in entries: - # Process the URI to make sure it's properly formatted - uri = entry["uri"] - - # Check if URI starts with ${/ or ${\ - this indicates an improperly formatted path - if uri.startswith("${/") or uri.startswith("${\\"): - # Extract the path from inside the curly braces using a more robust method - try: - # Find the first { and last } - start = uri.find("{") - end = uri.rfind("}") - if start != -1 and end != -1 and end > start: - path = uri[start + 1 : end] - # Replace with the actual path without environment variable syntax - uri = path + uri[end + 1 :] - except Exception: - # If there's any error in processing, keep the original URI - pass - - # Format the entry with proper escaping - entry_str = ( - f" (lib " - f'(name "{entry["name"]}")' - f'(type "KiCad")' - f'(uri "{uri}")' - f'(options "{entry["options"]}")' - f'(descr "{entry["description"]}"))\n' - ) - new_content += entry_str - - new_content += line + "\n" - - # Write updated content, ensuring UTF-8 encoding - with table_path.open("w", encoding="utf-8") as f: - f.write(new_content) diff --git a/kicad_lib_manager/main.py b/kicad_lib_manager/main.py index 08e415d..fbe7546 100644 --- a/kicad_lib_manager/main.py +++ b/kicad_lib_manager/main.py @@ -12,6 +12,7 @@ from .commands.init import init_app from .commands.list_libraries import list_app +from .commands.pin import pin_app from .commands.status import status_app # Install rich traceback handler for better error display @@ -36,7 +37,7 @@ def version_callback(value: bool) -> None: """Print version information and exit.""" if value: version = importlib.metadata.version("kilm") - console.print(f"KiCad Library Manager (KiLM) version {version}") + console.print(f"KiCad Library Manager (KiLM) version [cyan]{version}[/cyan]") raise typer.Exit() @@ -72,10 +73,11 @@ def main( app.add_typer(status_app, name="status", help="Show current library configuration") app.add_typer(list_app, name="list", help="List available KiCad libraries") app.add_typer(init_app, name="init", help="Initialize library configuration") +app.add_typer(pin_app, name="pin", help="Pin favorite libraries") # TODO: Migrate remaining commands to Typer # - setup: Configure KiCad to use libraries -# - pin/unpin: Pin/unpin favorite libraries +# - unpin: Unpin favorite libraries # - add-3d: Add 3D model libraries # - config: Manage configuration settings # - sync: Update/sync library content diff --git a/kicad_lib_manager/services/__init__.py b/kicad_lib_manager/services/__init__.py new file mode 100644 index 0000000..f8c2b40 --- /dev/null +++ b/kicad_lib_manager/services/__init__.py @@ -0,0 +1 @@ +"""Service implementations for KiCad Library Manager.""" diff --git a/kicad_lib_manager/config.py b/kicad_lib_manager/services/config_service.py similarity index 87% rename from kicad_lib_manager/config.py rename to kicad_lib_manager/services/config_service.py index 76123f5..6eb2a6b 100644 --- a/kicad_lib_manager/config.py +++ b/kicad_lib_manager/services/config_service.py @@ -1,5 +1,5 @@ """ -Configuration management +Configuration management for KiCad Library Manager. """ import time @@ -9,7 +9,7 @@ import click import yaml -from .constants import ( +from ..utils.constants import ( CONFIG_DIR_NAME, CONFIG_FILE_NAME, DEFAULT_LIBRARIES, @@ -462,3 +462,64 @@ def _validate_library_entry( type_=str(lib["type"]), ) return None + + +class ConfigService: + """Service wrapper for managing KiLM configuration.""" + + def __init__(self): + """Initialize the configuration service.""" + self._config = Config() + + def get_config_file_path(self) -> Path: + """Get the path to the KiLM configuration file.""" + return self._config._get_config_file() + + def load_config(self) -> Dict: + """Load the KiLM configuration.""" + return self._config._config + + def save_config(self, config: Dict) -> None: + """Save the KiLM configuration.""" + self._config._config = config + self._config.save() + + def add_library(self, name: str, path: str, library_type: str) -> None: + """Add a library to the configuration.""" + self._config.add_library(name, path, library_type) + + def remove_library(self, name: str) -> None: + """Remove a library from the configuration.""" + self._config.remove_library(name) + + def get_libraries(self) -> List[LibraryDict]: + """Get all configured libraries.""" + return self._config.get_libraries() + + def get_library_by_name(self, name: str) -> Optional[LibraryDict]: + """Get a specific library by name.""" + libraries = self.get_libraries() + for lib in libraries: + if lib.get("name") == name: + return lib + return None + + def get_current_library(self) -> Optional[str]: + """Get the current active library path.""" + return self._config.get_current_library() + + def set_current_library(self, path: str) -> None: + """Set the current active library.""" + self._config.set_current_library(path) + + def get_max_backups(self) -> int: + """Get the maximum number of backups to keep.""" + value = self._config.get("max_backups", 5) + if isinstance(value, int): + return value + return 5 + + def set_max_backups(self, count: int) -> None: + """Set the maximum number of backups to keep.""" + self._config.set("max_backups", count) + self._config.save() diff --git a/kicad_lib_manager/services/kicad_service.py b/kicad_lib_manager/services/kicad_service.py new file mode 100644 index 0000000..16ccf60 --- /dev/null +++ b/kicad_lib_manager/services/kicad_service.py @@ -0,0 +1,103 @@ +""" +KiCad service implementation for KiCad Library Manager. +""" + +import json +from pathlib import Path +from typing import Dict, List, Optional, Tuple + +from ..utils.file_ops import list_configured_libraries +from .library_service import LibraryService + + +class KiCadService: + """Service for managing KiCad configuration and libraries.""" + + @staticmethod + def find_kicad_config_dir() -> Path: + return LibraryService.find_kicad_config() + + def get_environment_variables(self, config_dir: Path) -> Dict[str, str]: + """Get KiCad environment variables from configuration.""" + kicad_common = config_dir / "kicad_common.json" + + if not kicad_common.exists(): + return {} + + try: + with kicad_common.open() as f: + config = json.load(f) + + if "environment" in config and "vars" in config["environment"]: + return config["environment"]["vars"] + + except Exception: + pass + + return {} + + def set_environment_variables( + self, + config_dir: Path, + env_vars: Dict[str, str], + backup: bool = True, + max_backups: int = 5, + ) -> bool: + """Set KiCad environment variables.""" + # This would use the existing update_kicad_env_vars function + from ..utils.env_vars import update_kicad_env_vars + + return update_kicad_env_vars(config_dir, env_vars, backup, max_backups) + + def get_configured_libraries( + self, config_dir: Path + ) -> Tuple[List[Dict], List[Dict]]: + """Get configured symbol and footprint libraries.""" + return list_configured_libraries(config_dir) + + def add_libraries_to_kicad( + self, + config_dir: Path, + symbol_libs: Optional[List[Dict]] = None, + footprint_libs: Optional[List[Dict]] = None, + backup: bool = True, + max_backups: int = 5, + ) -> bool: + """Add libraries to KiCad library tables.""" + # This would use the existing add_libraries function + from .library_service import LibraryService + + # TODO: Properly implement library addition with symbol_libs and footprint_libs + _ = symbol_libs, footprint_libs, max_backups # Suppress unused warnings + added_libs, changes_needed = LibraryService.add_libraries( + str(config_dir), + config_dir, + dry_run=not backup, + ) + _ = added_libs # Suppress unused warning + return changes_needed + + def get_pinned_libraries(self, config_dir: Path) -> Tuple[List[str], List[str]]: + """Get pinned libraries from KiCad configuration.""" + kicad_common = config_dir / "kicad_common.json" + + if not kicad_common.exists(): + return [], [] + + try: + with kicad_common.open() as f: + config = json.load(f) + + symbol_libs = [] + footprint_libs = [] + + if "session" in config: + if "pinned_symbol_libs" in config["session"]: + symbol_libs = config["session"]["pinned_symbol_libs"] + if "pinned_fp_libs" in config["session"]: + footprint_libs = config["session"]["pinned_fp_libs"] + + return symbol_libs, footprint_libs + + except Exception: + return [], [] diff --git a/kicad_lib_manager/services/library_service.py b/kicad_lib_manager/services/library_service.py new file mode 100644 index 0000000..1782145 --- /dev/null +++ b/kicad_lib_manager/services/library_service.py @@ -0,0 +1,544 @@ +""" +Library service implementation for KiCad Library Manager. +Core functionality for managing KiCad libraries. +""" + +import os +import platform +from pathlib import Path +from typing import Dict, List, Optional, Set, Tuple + +import yaml + +from ..utils.env_vars import expand_user_path, update_pinned_libraries +from ..utils.file_ops import ( + list_configured_libraries, + list_libraries, + validate_lib_table, +) +from ..utils.metadata import ( + generate_env_var_name, + get_default_github_metadata, + read_github_metadata, + write_github_metadata, +) + + +class LibraryService: + """Service for managing KiCad libraries.""" + + def list_libraries(self, directory: Path) -> Tuple[List[str], List[str]]: + """List symbol and footprint libraries in a directory.""" + return list_libraries(str(directory)) + + def initialize_library( + self, + directory: Path, + name: Optional[str] = None, + description: Optional[str] = None, + env_var: Optional[str] = None, + force: bool = False, + no_env_var: bool = False, + ) -> Dict: + """Initialize a library in the given directory.""" + # Check for existing metadata + metadata = read_github_metadata(directory) + + if metadata and not force: + # Use existing metadata with potential overrides + if name: + metadata["name"] = name + if description: + metadata["description"] = description + if env_var: + metadata["env_var"] = env_var + elif no_env_var and "env_var" in metadata: + del metadata["env_var"] + + if any([name, description, env_var, no_env_var]): + metadata["updated_with"] = "kilm" + write_github_metadata(directory, metadata) + else: + # Create new metadata + metadata = get_default_github_metadata(directory) + + if name: + metadata["name"] = name + if not env_var and not no_env_var: + metadata["env_var"] = generate_env_var_name(name, "KICAD_LIB") + + if description: + metadata["description"] = description + + if env_var: + metadata["env_var"] = env_var + elif no_env_var and "env_var" in metadata: + del metadata["env_var"] + + write_github_metadata(directory, metadata) + + # Create library directory structure + self._create_library_structure(directory) + + # Update capabilities + capabilities = { + "symbols": (directory / "symbols").exists(), + "footprints": (directory / "footprints").exists(), + "templates": (directory / "templates").exists(), + } + metadata["capabilities"] = capabilities + write_github_metadata(directory, metadata) + + return metadata + + def get_library_metadata(self, directory: Path) -> Optional[Dict]: + """Get metadata for a library directory.""" + return read_github_metadata(directory) + + def pin_libraries( + self, + symbol_libs: List[str], + footprint_libs: List[str], + kicad_config_dir: Path, + dry_run: bool = False, + max_backups: int = 5, + ) -> bool: + """Pin libraries in KiCad for quick access.""" + return update_pinned_libraries( + kicad_config_dir, + symbol_libs=symbol_libs, + footprint_libs=footprint_libs, + dry_run=dry_run, + max_backups=max_backups, + ) + + def unpin_libraries( + self, + symbol_libs: List[str], + footprint_libs: List[str], + kicad_config_dir: Path, + dry_run: bool = False, + max_backups: int = 5, + ) -> bool: + """Unpin libraries in KiCad.""" + # This would need to be implemented in utils/env_vars.py + # For now, we'll return False as it's not implemented + # TODO: Implement unpin functionality + _ = symbol_libs, footprint_libs, kicad_config_dir, dry_run, max_backups + return False + + def _create_library_structure(self, directory: Path) -> Tuple[List[str], List[str]]: + """Create the required directory structure for a library.""" + required_folders = ["symbols", "footprints", "templates"] + existing_folders = [] + created_folders = [] + + for folder in required_folders: + folder_path = directory / folder + if folder_path.exists(): + existing_folders.append(folder) + else: + folder_path.mkdir(parents=True, exist_ok=True) + created_folders.append(folder) + + return existing_folders, created_folders + + @staticmethod + def add_libraries( + kicad_lib_dir: str, + kicad_config: Path, + kicad_3d_dir: Optional[str] = None, + additional_3d_dirs: Optional[Dict[str, str]] = None, + dry_run: bool = False, + ) -> Tuple[Set[str], bool]: + """ + Add KiCad libraries to the configuration. + + Args: + kicad_lib_dir: Path to the KiCad library directory + kicad_config: Path to the KiCad configuration directory + kicad_3d_dir: Path to the KiCad 3D models directory (optional) + additional_3d_dirs: Dictionary of additional 3D model directories with their + environment variable names as keys (optional) + dry_run: If True, don't actually make any changes + + Returns: + Tuple of (set of libraries added, whether changes were needed) + + Raises: + FileNotFoundError: If the library directory does not exist + ValueError: If the library directory does not contain symbols or footprints + """ + # Check if library directory exists + # First expand any environment variables in the path + if kicad_lib_dir.startswith("${") and kicad_lib_dir.endswith("}"): + env_var = kicad_lib_dir[2:-1] + if env_var in os.environ: + kicad_lib_dir = os.environ[env_var] + else: + raise FileNotFoundError(f"Environment variable {env_var} not found") + # Check if it's NOT an absolute path (Unix/Windows) or UNC path (Windows) + # and treat it as a potential environment variable name if it's not. + elif not ( + kicad_lib_dir.startswith("/") + or ( + len(kicad_lib_dir) > 2 and kicad_lib_dir[1] == ":" + ) # Check for C: style paths + or ( + kicad_lib_dir.startswith("\\\\") + ) # Check for UNC paths like \\server\share + ): + # If it's an environment variable name without ${} + if kicad_lib_dir in os.environ: + kicad_lib_dir = os.environ[kicad_lib_dir] + else: + raise FileNotFoundError( + f"Environment variable {kicad_lib_dir} not found" + ) + + # Now expand any user paths + kicad_lib_dir = expand_user_path(kicad_lib_dir) + lib_dir = Path(kicad_lib_dir) + if not lib_dir.exists(): + raise FileNotFoundError( + f"KiCad library directory not found: {kicad_lib_dir}" + ) + + # Check if 3D models directory exists + if kicad_3d_dir: + kicad_3d_dir = expand_user_path(kicad_3d_dir) + models_dir = Path(kicad_3d_dir) + if not models_dir.exists(): + raise FileNotFoundError( + f"KiCad 3D models directory not found: {kicad_3d_dir}" + ) + + # Check if additional 3D model directories exist + all_3d_dirs = {} + if kicad_3d_dir: + all_3d_dirs["KICAD_3D_LIB"] = kicad_3d_dir + + if additional_3d_dirs: + for env_var, path in additional_3d_dirs.items(): + path = expand_user_path(path) + dir_path = Path(path) + if not dir_path.exists(): + print(f"Warning: 3D models directory not found: {path} (skipping)") + continue + + # Only add if this is a different path than the main 3D models directory + if kicad_3d_dir and os.path.normpath(path) == os.path.normpath( + kicad_3d_dir + ): + continue + + all_3d_dirs[env_var] = path + + # Get list of available libraries + symbols, footprints = list_libraries(kicad_lib_dir) + if not symbols and not footprints: + raise ValueError(f"No libraries found in {kicad_lib_dir}") + + # Check if library tables exist + sym_table = kicad_config / "sym-lib-table" + fp_table = kicad_config / "fp-lib-table" + + # Get existing libraries + sym_libs, fp_libs = list_configured_libraries(kicad_config) + sym_lib_names = {lib["name"] for lib in sym_libs} + fp_lib_names = {lib["name"] for lib in fp_libs} + + # Check for new libraries + new_symbols = [lib for lib in symbols if lib not in sym_lib_names] + new_footprints = [lib for lib in footprints if lib not in fp_lib_names] + + # Generate variable references for 3D model paths + env_var_refs = {} + for env_var, path in all_3d_dirs.items(): + # Convert to format KiCad expects: ${ENV_VAR} + env_var_refs[path] = f"${{{env_var}}}" + + # Add new libraries to symbol table + sym_changes_needed = False + new_sym_entries = [] + for lib in new_symbols: + uri = LibraryService.format_uri(kicad_lib_dir, lib, "symbols") + + # Add the library with UTF-8 encoded description + new_sym_entries.append( + { + "name": lib, + "uri": uri, + "options": "", + "description": LibraryService.get_library_description( + "symbols", lib, kicad_lib_dir + ) + .encode("utf-8") + .decode("utf-8"), + } + ) + sym_changes_needed = True + + # Add new libraries to footprint table + fp_changes_needed = False + new_fp_entries = [] + for lib in new_footprints: + uri = LibraryService.format_uri(kicad_lib_dir, lib, "footprints") + + # Add the library with UTF-8 encoded description + new_fp_entries.append( + { + "name": lib, + "uri": uri, + "options": "", + "description": LibraryService.get_library_description( + "footprints", lib, kicad_lib_dir + ) + .encode("utf-8") + .decode("utf-8"), + } + ) + fp_changes_needed = True + + # Only make changes if needed + changes_needed = sym_changes_needed or fp_changes_needed + if changes_needed and not dry_run: + # Add new entries to symbol table + if sym_changes_needed: + LibraryService.add_entries_to_table(sym_table, new_sym_entries) + + # Add new entries to footprint table + if fp_changes_needed: + LibraryService.add_entries_to_table(fp_table, new_fp_entries) + + # Return the set of added libraries + added_libraries = set(new_symbols + new_footprints) + return added_libraries, changes_needed + + @staticmethod + def find_kicad_config() -> Path: + """ + Find the KiCad configuration directory for the current platform + + Returns: + Path to the KiCad configuration directory + + Raises: + FileNotFoundError: If KiCad configuration directory is not found + """ + system = platform.system() + + if system == "Darwin": # macOS + config_dir = Path.home() / "Library" / "Preferences" / "kicad" + elif system == "Linux": + config_dir = Path.home() / ".config" / "kicad" + elif system == "Windows": + appdata = os.environ.get("APPDATA") + if not appdata: + raise FileNotFoundError("APPDATA environment variable not found") + config_dir = Path(appdata) / "kicad" + else: + raise FileNotFoundError(f"Unsupported platform: {system}") + + if not config_dir.exists(): + raise FileNotFoundError( + f"KiCad configuration directory not found at {config_dir}. " + "Please run KiCad at least once before using this tool." + ) + + # Find the most recent KiCad version directory + version_dirs = [d for d in config_dir.iterdir() if d.is_dir()] + if not version_dirs: + raise FileNotFoundError( + f"No KiCad version directories found in {config_dir}. " + "Please run KiCad at least once before using this tool." + ) + + # Sort directories by version number (assuming directories with numbers are version dirs) + version_dirs = [d for d in version_dirs if any(c.isdigit() for c in d.name)] + if not version_dirs: + raise FileNotFoundError( + f"No KiCad version directories found in {config_dir}. " + "Please run KiCad at least once before using this tool." + ) + + latest_dir = sorted(version_dirs, key=lambda d: d.name)[-1] + + # Check for required files + sym_table = latest_dir / "sym-lib-table" + fp_table = latest_dir / "fp-lib-table" + + if not sym_table.exists() and not fp_table.exists(): + raise FileNotFoundError( + f"KiCad library tables not found in {latest_dir}. " + "Please run KiCad at least once before using this tool." + ) + + return latest_dir + + @staticmethod + def get_library_description( + lib_type: str, lib_name: str, kicad_lib_dir: str + ) -> str: + """ + Get a description for a library from the YAML file or generate a default one + + Args: + lib_type: Either 'symbols' or 'footprints' + lib_name: The name of the library + kicad_lib_dir: The KiCad library directory + + Returns: + A description for the library + """ + yaml_file = Path(kicad_lib_dir) / "library_descriptions.yaml" + + # Check if YAML file exists + if yaml_file.exists(): + try: + with yaml_file.open() as f: + data = yaml.safe_load(f) + + if ( + data + and isinstance(data, dict) + and lib_type in data + and isinstance(data[lib_type], dict) + and lib_name in data[lib_type] + ): + return data[lib_type][lib_name] + except Exception: + pass + + # Default description if YAML file doesn't exist or doesn't contain the library + if lib_type == "symbols": + return f"{lib_name} symbol library" + else: + return f"{lib_name} footprint library" + + @staticmethod + def format_uri(base_path: str, lib_name: str, lib_type: str) -> str: + """ + Format a URI for a KiCad library. + + Args: + base_path: The base path to the library directory + lib_name: The name of the library + lib_type: The type of library (symbols or footprints) + + Returns: + The formatted URI string + + Raises: + ValueError: If base_path is empty, lib_type is invalid, or path format is invalid + """ + if not base_path: + raise ValueError("Base path cannot be empty") + + if lib_type not in ["symbols", "footprints"]: + raise ValueError(f"Invalid library type: {lib_type}") + + # Validate ${...} format if present + if base_path.startswith("${") and not base_path.endswith("}"): + raise ValueError(f"Invalid environment variable format: {base_path}") + + # Helper function to check if a path is absolute + def is_absolute_path(path: str) -> bool: + return ( + path.startswith("/") # Unix-style + or path.startswith("\\") # Windows-style with backslash + or (len(path) > 1 and path[1] == ":") # Windows-style with drive letter + ) + + # Normalize path separators to forward slashes first + base_path = base_path.replace("\\", "/") + + # Check if the path is already in ${...} format + if base_path.startswith("${") and base_path.endswith("}"): + # Extract the path from inside the curly braces + path = base_path[2:-1] + if is_absolute_path(path): + # If it's an absolute path, remove the ${...} wrapper + base_path = path + # Otherwise, keep the ${...} wrapper for environment variables + else: + # If it's not in ${...} format, check if it's an absolute path + if not is_absolute_path(base_path): + # If it's not an absolute path, treat it as an environment variable + base_path = f"${{{base_path}}}" + + # Construct the URI based on library type + if lib_type == "symbols": + return f"{base_path}/symbols/{lib_name}.kicad_sym" + else: + return f"{base_path}/footprints/{lib_name}.pretty" + + @staticmethod + def add_entries_to_table(table_path: Path, entries: List[Dict[str, str]]) -> None: + """ + Add entries to a KiCad library table file + + Args: + table_path: Path to the library table + entries: List of entries to add + """ + # Make sure the table exists and has a valid format + validate_lib_table(table_path, False) + + # Read existing content, ensuring UTF-8 encoding + with table_path.open(encoding="utf-8") as f: + content = f.read() + + # Find the last proper closing parenthesis of the table + closing_paren_index = -1 + lines = content.splitlines() + for i in range(len(lines) - 1, -1, -1): + if lines[i].strip() == ")": + closing_paren_index = i + break + + if closing_paren_index == -1: + raise ValueError( + f"Could not find closing parenthesis in library table: {table_path}" + ) + + # Insert new entries before the closing parenthesis + new_content = "" + for i, line in enumerate(lines): + if i == closing_paren_index: + # Insert entries before the closing parenthesis line + for entry in entries: + # Process the URI to make sure it's properly formatted + uri = entry["uri"] + + # Check if URI starts with ${/ or ${\ - this indicates an improperly formatted path + if uri.startswith("${/") or uri.startswith("${\\"): + # Extract the path from inside the curly braces using a more robust method + try: + # Find the first { and last } + start = uri.find("{") + end = uri.rfind("}") + if start != -1 and end != -1 and end > start: + path = uri[start + 1 : end] + # Replace with the actual path without environment variable syntax + uri = path + uri[end + 1 :] + except Exception: + # If there's any error in processing, keep the original URI + pass + + # Format the entry with proper escaping + entry_str = ( + f" (lib " + f'(name "{entry["name"]}")' + f'(type "KiCad")' + f'(uri "{uri}")' + f'(options "{entry["options"]}")' + f'(descr "{entry["description"]}"))\n' + ) + new_content += entry_str + + new_content += line + "\n" + + # Write updated content, ensuring UTF-8 encoding + with table_path.open("w", encoding="utf-8") as f: + f.write(new_content) diff --git a/kicad_lib_manager/auto_update.py b/kicad_lib_manager/services/update_service.py similarity index 87% rename from kicad_lib_manager/auto_update.py rename to kicad_lib_manager/services/update_service.py index 87ef5d5..cbfe41e 100644 --- a/kicad_lib_manager/auto_update.py +++ b/kicad_lib_manager/services/update_service.py @@ -228,3 +228,34 @@ def perform_update(self) -> Tuple[bool, str]: else: instruction = self.get_update_instruction() return False, f"Unsupported installation method. Run: {instruction}" + + +class UpdateService: + """Service wrapper for KiLM update functionality.""" + + def __init__(self, current_version: str): + self.manager = UpdateManager(current_version) + + def check_for_updates(self) -> Optional[str]: + """Check for available updates.""" + return self.manager.check_latest_version() + + def is_update_available(self, latest_version: str) -> bool: + """Check if an update is available.""" + return self.manager.is_newer_version_available(latest_version) + + def get_installation_method(self) -> str: + """Get detected installation method.""" + return self.manager.installation_method + + def get_update_instructions(self) -> str: + """Get update instructions for current installation method.""" + return self.manager.get_update_instruction() + + def can_auto_update(self) -> bool: + """Check if automatic updates are supported.""" + return self.manager.can_auto_update() + + def perform_update(self) -> Tuple[bool, str]: + """Perform the update.""" + return self.manager.perform_update() diff --git a/kicad_lib_manager/constants.py b/kicad_lib_manager/utils/constants.py similarity index 100% rename from kicad_lib_manager/constants.py rename to kicad_lib_manager/utils/constants.py diff --git a/kicad_lib_manager/utils/env_vars.py b/kicad_lib_manager/utils/env_vars.py index 2544a2a..32467c1 100644 --- a/kicad_lib_manager/utils/env_vars.py +++ b/kicad_lib_manager/utils/env_vars.py @@ -12,7 +12,7 @@ # Import Config here, but only use it when needed to avoid circular imports try: - from ..config import Config + from ..services.config_service import Config except ImportError: Config = None diff --git a/kicad_lib_manager/utils/metadata.py b/kicad_lib_manager/utils/metadata.py index a0e5e4a..a032751 100644 --- a/kicad_lib_manager/utils/metadata.py +++ b/kicad_lib_manager/utils/metadata.py @@ -9,7 +9,7 @@ import yaml -from ..constants import CLOUD_METADATA_FILE, GITHUB_METADATA_FILE +from .constants import CLOUD_METADATA_FILE, GITHUB_METADATA_FILE def read_github_metadata( diff --git a/kicad_lib_manager/utils/template.py b/kicad_lib_manager/utils/template.py index 03b2c8e..fd427b1 100644 --- a/kicad_lib_manager/utils/template.py +++ b/kicad_lib_manager/utils/template.py @@ -17,7 +17,7 @@ import pathspec import yaml -from ..constants import ( +from .constants import ( HOOKS_DIR, TEMPLATE_CONTENT_DIR, TEMPLATE_METADATA, diff --git a/pyproject.toml b/pyproject.toml index 42950fe..889f839 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -73,8 +73,7 @@ Repository = "https://github.com/barisgit/KiLM" "Bug Tracker" = "https://github.com/barisgit/KiLM/issues" [project.scripts] -kilm = "kicad_lib_manager.cli:main" -kilm-typer = "kicad_lib_manager.main:app" +kilm = "kicad_lib_manager.main:app" [tool.hatch.build.targets.wheel] diff --git a/tests/test_config_commands.py b/tests/test_config_commands.py index 7a93100..e961110 100644 --- a/tests/test_config_commands.py +++ b/tests/test_config_commands.py @@ -8,7 +8,7 @@ from click.testing import CliRunner from kicad_lib_manager.cli import main -from kicad_lib_manager.config import Config, LibraryDict +from kicad_lib_manager.services.config_service import Config, LibraryDict # Sample test data TEST_LIBRARIES: List[LibraryDict] = [ diff --git a/tests/test_library_manager.py b/tests/test_library_manager.py index cb77c58..8f64721 100644 --- a/tests/test_library_manager.py +++ b/tests/test_library_manager.py @@ -3,7 +3,7 @@ import pytest -from kicad_lib_manager.library_manager import ( +from kicad_lib_manager.services.library_service import ( add_entries_to_table, add_libraries, format_uri, From ae0b2adcdedd9aadc6e1d20f08e5be450686110a Mon Sep 17 00:00:00 2001 From: barisgit Date: Sat, 6 Sep 2025 22:50:59 +0200 Subject: [PATCH 03/13] Add AI assisted development files --- .claude/commands/plan.md | 37 ++++ .claude/commands/specify.md | 13 ++ .claude/commands/tasks.md | 59 ++++++ .gitignore | 4 +- CLAUDE.md | 264 ++++++++++++++++++++++++ memory/constitution.md | 50 +++++ memory/constitution_update_checklist.md | 85 ++++++++ scripts/check-task-prerequisites.sh | 62 ++++++ scripts/common.sh | 77 +++++++ scripts/create-new-feature.sh | 96 +++++++++ scripts/get-feature-paths.sh | 23 +++ scripts/setup-plan.sh | 44 ++++ scripts/update-agent-context.sh | 234 +++++++++++++++++++++ 13 files changed, 1046 insertions(+), 2 deletions(-) create mode 100644 .claude/commands/plan.md create mode 100644 .claude/commands/specify.md create mode 100644 .claude/commands/tasks.md create mode 100644 CLAUDE.md create mode 100644 memory/constitution.md create mode 100644 memory/constitution_update_checklist.md create mode 100644 scripts/check-task-prerequisites.sh create mode 100644 scripts/common.sh create mode 100644 scripts/create-new-feature.sh create mode 100644 scripts/get-feature-paths.sh create mode 100644 scripts/setup-plan.sh create mode 100644 scripts/update-agent-context.sh diff --git a/.claude/commands/plan.md b/.claude/commands/plan.md new file mode 100644 index 0000000..b86ef5a --- /dev/null +++ b/.claude/commands/plan.md @@ -0,0 +1,37 @@ + +Plan how to implement the specified feature. + +This is the second step in the Spec-Driven Development lifecycle. + +Given the implementation details provided as an argument, do this: + +1. Run `scripts/setup-plan.sh --json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute. +2. Read and analyze the feature specification to understand: + - The feature requirements and user stories + - Functional and non-functional requirements + - Success criteria and acceptance criteria + - Any technical constraints or dependencies mentioned + +3. Read the constitution at `/memory/constitution.md` to understand constitutional requirements. + +4. Execute the implementation plan template: + - Load `/templates/plan-template.md` (already copied to IMPL_PLAN path) + - Set Input path to FEATURE_SPEC + - Run the Execution Flow (main) function steps 1-10 + - The template is self-contained and executable + - Follow error handling and gate checks as specified + - Let the template guide artifact generation in $SPECS_DIR: + * Phase 0 generates research.md + * Phase 1 generates data-model.md, contracts/, quickstart.md + * Phase 2 generates tasks.md + - Incorporate user-provided details from arguments into Technical Context: $ARGUMENTS + - Update Progress Tracking as you complete each phase + +5. Verify execution completed: + - Check Progress Tracking shows all phases complete + - Ensure all required artifacts were generated + - Confirm no ERROR states in execution + +6. Report results with branch name, file paths, and generated artifacts. + +Use absolute paths with the repository root for all file operations to avoid path issues. diff --git a/.claude/commands/specify.md b/.claude/commands/specify.md new file mode 100644 index 0000000..c46f104 --- /dev/null +++ b/.claude/commands/specify.md @@ -0,0 +1,13 @@ + +Start a new feature by creating a specification and feature branch. + +This is the first step in the Spec-Driven Development lifecycle. + +Given the feature description provided as an argument, do this: + +1. Run the script `scripts/create-new-feature.sh --json "$ARGUMENTS"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute. +2. Load `templates/spec-template.md` to understand required sections. +3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings. +4. Report completion with branch name, spec file path, and readiness for the next phase. + +Note: The script creates and checks out the new branch and initializes the spec file before writing. diff --git a/.claude/commands/tasks.md b/.claude/commands/tasks.md new file mode 100644 index 0000000..1fd64be --- /dev/null +++ b/.claude/commands/tasks.md @@ -0,0 +1,59 @@ + +Break down the plan into executable tasks. + +This is the third step in the Spec-Driven Development lifecycle. + +Given the context provided as an argument, do this: + +1. Run `scripts/check-task-prerequisites.sh --json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute. +2. Load and analyze available design documents: + - Always read plan.md for tech stack and libraries + - IF EXISTS: Read data-model.md for entities + - IF EXISTS: Read contracts/ for API endpoints + - IF EXISTS: Read research.md for technical decisions + - IF EXISTS: Read quickstart.md for test scenarios + + Note: Not all projects have all documents. For example: + - CLI tools might not have contracts/ + - Simple libraries might not need data-model.md + - Generate tasks based on what's available + +3. Generate tasks following the template: + - Use `/templates/tasks-template.md` as the base + - Replace example tasks with actual tasks based on: + * **Setup tasks**: Project init, dependencies, linting + * **Test tasks [P]**: One per contract, one per integration scenario + * **Core tasks**: One per entity, service, CLI command, endpoint + * **Integration tasks**: DB connections, middleware, logging + * **Polish tasks [P]**: Unit tests, performance, docs + +4. Task generation rules: + - Each contract file → contract test task marked [P] + - Each entity in data-model → model creation task marked [P] + - Each endpoint → implementation task (not parallel if shared files) + - Each user story → integration test marked [P] + - Different files = can be parallel [P] + - Same file = sequential (no [P]) + +5. Order tasks by dependencies: + - Setup before everything + - Tests before implementation (TDD) + - Models before services + - Services before endpoints + - Core before integration + - Everything before polish + +6. Include parallel execution examples: + - Group [P] tasks that can run together + - Show actual Task agent commands + +7. Create FEATURE_DIR/tasks.md with: + - Correct feature name from implementation plan + - Numbered tasks (T001, T002, etc.) + - Clear file paths for each task + - Dependency notes + - Parallel execution guidance + +Context for task generation: $ARGUMENTS + +The tasks.md should be immediately executable - each task must be specific enough that an LLM can complete it without additional context. diff --git a/.gitignore b/.gitignore index 823e6aa..04e4832 100644 --- a/.gitignore +++ b/.gitignore @@ -45,6 +45,6 @@ test_lib/ test_template/ TODO.md -CLAUDE.md -.claude/ +.claude/settings.local.json +.claude/doc/ temp*/ \ No newline at end of file diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..f602ec5 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,264 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Core Principles: Simplicity & Type Safety + +KiLM (KiCad Library Manager) prioritizes **professional code standards** and **complete type safety**: + +- **Type-first development**: Everything uses proper type hints - no `Any`, no dynamic typing +- **Professional standards**: No emojis in code, no hardcoded values, proper constants +- **CLI-focused**: Simple, reliable command-line interface for KiCad library management +- **Cross-platform**: Support for Windows, macOS, Linux KiCad installations + +## Architecture Overview + +KiLM is a **command-line tool for managing KiCad libraries** across projects and workstations: + +**Core Functionality**: +- KiCad configuration detection across platforms +- Library management (symbol and footprint libraries) +- Environment variable configuration +- Project template management +- Backup and restore of KiCad configurations + +## Development Commands + +### Python CLI Development +```bash +# Install Python package in development mode +pip install -e ".[dev]" + +# Install pre-commit hooks (once implemented) +pre-commit install + +# Test basic functionality +kilm status +kilm --help +``` + +### Testing & Quality +```bash +# Run tests with coverage +pytest --cov=kicad_lib_manager --cov-report=html + +# Type checking, formatting, and linting +pyrefly # Type check (required - no "any" types allowed) +ruff format . +ruff check . + +# All quality checks +pre-commit run --all-files +``` + +### CI/CD and Releases +```bash +# Create a new release (automated via GitHub Actions) +# 1. Update version in kicad_lib_manager/__init__.py +# 2. Push version tag: +git tag v0.3.1 +git push origin v0.3.1 + +# This triggers: +# - Automated testing and quality checks +# - PyPI publishing with trusted publishing +# - Draft GitHub release with auto-generated notes +# - Multi-platform compatibility verification +``` + +**Release Process:** +1. **Tag-based releases**: Push version tags to trigger automated releases +2. **Draft releases**: GitHub releases created as drafts for manual review +3. **Automatic PyPI**: Publishes to PyPI immediately via trusted publishing +4. **Auto-generated notes**: Release notes include commits, PRs, and install instructions + +## Code Quality Standards + +### Type Safety Requirements +- **No Any types**: All functions must have proper type hints +- **Pydantic models**: Use Pydantic for configuration validation where applicable +- **Type checking**: Must pass pyrefly type checking without errors + +### Professional Code Standards +- **No emojis**: Keep code and output professional - avoid emojis in code, comments, or CLI output +- **No hardcoding**: Use constants, configuration files, or environment variables +- **Proper error handling**: Consistent error patterns with informative messages +- **Cross-platform paths**: Use pathlib.Path for all file operations +- **Context7**: Often use context 7 MCP when dealing with new code and packages + +## CLI Architecture + +### Command Structure +``` +kilm # Main CLI entry point +├── init # Initialize library +├── setup # Configure KiCad to use libraries +├── status # Show current configuration +├── list # List available libraries +├── pin/unpin # Pin/unpin favorite libraries +├── add-3d # Add 3D model libraries +├── config # Configuration management +├── sync # Update/sync library content (was 'update') +├── update # Update KiLM itself (breaking change in 0.4.0) +├── add-hook # Add project hooks +└── template # Project template management +``` + +## BREAKING CHANGES in v0.4.0 + +### Command Restructuring +- **`kilm update`** now updates KiLM itself (self-update functionality) +- **`kilm sync`** updates library content (was `kilm update`) +- Added deprecation banner for transition period +- Full auto-update functionality with installation method detection + +### New Features +- **Self-Update System**: Detects installation method (pip, pipx, conda, uv, homebrew) +- **PyPI Integration**: Checks for latest versions with proper caching +- **Update Preferences**: Configurable update checking and frequency +- **Professional UX**: Non-intrusive notifications with method-specific guidance + +### Core Modules +- **CLI Layer** (`cli.py`): Click-based command interface +- **Commands** (`commands/`): Individual command implementations +- **Library Manager** (`library_manager.py`): Core library management logic +- **Configuration** (`config.py`): KiCad configuration handling with update preferences +- **Auto-Update** (`auto_update.py`): Self-update functionality with installation detection +- **Utilities** (`utils/`): File operations, backups, metadata, templates + +## Development Workflow - MANDATORY + +### Task Documentation +- **ALWAYS create task file**: For ANY work request, immediately create `.claude/doc/tasks/[date]-[seq]-[task-name].md` +- **Update throughout**: Document progress, decisions, blockers in real-time +- **Include context**: Always pass current task file path to agents for context sharing + +### Code Quality Workflow +- **After completing ANY code changes**: Prompt user "Should I run the code-reviewer to check for quality issues?" +- **Never assume**: Don't run code-reviewer automatically without asking +- **Update task file**: Document review results and any issues found + +### Agent Management +- **Use agents for all complex tasks**: Code reviews, documentation, analysis, implementation planning +- **Always provide task context**: Give agents the current task file path when applicable +- **Delegate, don't duplicate**: Use specialized agents instead of handling complex tasks directly +- **Give quality context to agents**: Point them to current task, tell them to use linters and type checkers + +### Agent Context Management (Required) + +- **Persist context in repo (important)**: Agents MUST save context under `.claude/doc/` to ensure continuity across runs. + - Tasks: `.claude/doc/tasks/YYYY-MM-DD-SEQ-slug.md` (SEQ is a 3-digit daily sequence starting at `001`. Agents only have the date—remember to increment SEQ if multiple tasks are created on the same day.) + - Decisions/ADR: `.claude/doc/adr/ADR-####-short-title.md` + - General agent reports: `.claude/doc/agent-reports/YYYY-MM-DD-SEQ-agent-report.md` +- **Pass context to agents (including general agents)**: When invoking any agent, ALWAYS include the path to the current task file. If the agent has no repo-specific instructions, explicitly tell it to save an `agent-report` (and append a short update to the task) using the same naming scheme. +- **Round-trip updates**: After each agent step, append a concise update (what changed, why, next) to the active task file. +- **Minimal duplication**: Reference prior notes; keep canonical decisions in ADRs and link from task files. +- **Example context**: + - Current task: `.claude/doc/tasks/YYYY-MM-DD-SEQ-task-name.md` + - Agent should also write: `.claude/doc/agent-reports/YYYY-MM-DD-SEQ-agent-report.md` + - Instruction: "Always provide current task path and increment SEQ for same-day tasks." + +## Key Implementation Patterns + +### KiCad Configuration Management +```python +# Professional, type-safe configuration handling +from pathlib import Path +from typing import Dict, List, Optional +from pydantic import BaseModel + +class KiCadConfig(BaseModel): + """Type-safe KiCad configuration model.""" + libraries: List[str] + environment_vars: Dict[str, str] + backup_enabled: bool = True + +def detect_kicad_config_path() -> Optional[Path]: + """Detect KiCad configuration path across platforms.""" + # Cross-platform detection logic + pass +``` + +### Library Management +```python +# Type-safe library operations +from typing import Protocol + +class LibraryManager(Protocol): + """Protocol for library management operations.""" + + def add_library(self, library_path: Path, library_type: str) -> bool: + """Add library to KiCad configuration.""" + ... + + def remove_library(self, library_name: str) -> bool: + """Remove library from KiCad configuration.""" + ... +``` + +## SOLID Principles for CLI Tools + +- **S**ingle Responsibility: Each command does one thing well +- **O**pen/Closed: Extensible for new KiCad features without modifying core +- **L**iskov Substitution: All library types implement consistent interfaces +- **I**nterface Segregation: Small, focused command interfaces +- **D**ependency Inversion: Depend on abstractions, not concrete implementations + +## Integration with KiCad + +### KiCad Version Support +- **KiCad 9.x**: Primary support target +- **KiCad 8.x**: Full compatibility + +### Configuration Files +- **Symbol libraries**: `.kicad_sym` files in symbol table +- **Footprint libraries**: `.pretty` directories in footprint table +- **Environment variables**: `kicad_common.json` configuration +- **Project templates**: Template directory management + +## Adding New Commands + +**Step 1**: Create command module +```python +# commands/new_command.py +import click +from typing import Optional + +@click.command() +@click.option('--option', help='Command option') +def new_command(option: Optional[str]) -> None: + """New command description.""" + # Implementation with proper type hints + pass +``` + +**Step 2**: Register in CLI +```python +# cli.py +from .commands.new_command import new_command + +main.add_command(new_command) +``` + +**Step 3**: Add tests +```python +# tests/test_new_command.py +def test_new_command(): + """Test new command functionality.""" + # Comprehensive test coverage + pass +``` + +## Modernization Roadmap + +### Phase 1: Infrastructure +- Modern build system (pyproject.toml with hatchling) +- Complete type safety (zero Any types, pyrefly validation) +- Professional code standards (no emojis, constants extracted) +- Comprehensive documentation structure + +### Phase 2: Enhancement +- Modern CLI framework (Typer + Rich for better UX) +- Development tooling (pre-commit hooks, quality pipeline) +- Enhanced error handling and user experience +- Cross-platform support improvements \ No newline at end of file diff --git a/memory/constitution.md b/memory/constitution.md new file mode 100644 index 0000000..1ed8d77 --- /dev/null +++ b/memory/constitution.md @@ -0,0 +1,50 @@ +# [PROJECT_NAME] Constitution + + +## Core Principles + +### [PRINCIPLE_1_NAME] + +[PRINCIPLE_1_DESCRIPTION] + + +### [PRINCIPLE_2_NAME] + +[PRINCIPLE_2_DESCRIPTION] + + +### [PRINCIPLE_3_NAME] + +[PRINCIPLE_3_DESCRIPTION] + + +### [PRINCIPLE_4_NAME] + +[PRINCIPLE_4_DESCRIPTION] + + +### [PRINCIPLE_5_NAME] + +[PRINCIPLE_5_DESCRIPTION] + + +## [SECTION_2_NAME] + + +[SECTION_2_CONTENT] + + +## [SECTION_3_NAME] + + +[SECTION_3_CONTENT] + + +## Governance + + +[GOVERNANCE_RULES] + + +**Version**: [CONSTITUTION_VERSION] | **Ratified**: [RATIFICATION_DATE] | **Last Amended**: [LAST_AMENDED_DATE] + \ No newline at end of file diff --git a/memory/constitution_update_checklist.md b/memory/constitution_update_checklist.md new file mode 100644 index 0000000..7f15d7f --- /dev/null +++ b/memory/constitution_update_checklist.md @@ -0,0 +1,85 @@ +# Constitution Update Checklist + +When amending the constitution (`/memory/constitution.md`), ensure all dependent documents are updated to maintain consistency. + +## Templates to Update + +### When adding/modifying ANY article: +- [ ] `/templates/plan-template.md` - Update Constitution Check section +- [ ] `/templates/spec-template.md` - Update if requirements/scope affected +- [ ] `/templates/tasks-template.md` - Update if new task types needed +- [ ] `/.claude/commands/plan.md` - Update if planning process changes +- [ ] `/.claude/commands/tasks.md` - Update if task generation affected +- [ ] `/CLAUDE.md` - Update runtime development guidelines + +### Article-specific updates: + +#### Article I (Library-First): +- [ ] Ensure templates emphasize library creation +- [ ] Update CLI command examples +- [ ] Add llms.txt documentation requirements + +#### Article II (CLI Interface): +- [ ] Update CLI flag requirements in templates +- [ ] Add text I/O protocol reminders + +#### Article III (Test-First): +- [ ] Update test order in all templates +- [ ] Emphasize TDD requirements +- [ ] Add test approval gates + +#### Article IV (Integration Testing): +- [ ] List integration test triggers +- [ ] Update test type priorities +- [ ] Add real dependency requirements + +#### Article V (Observability): +- [ ] Add logging requirements to templates +- [ ] Include multi-tier log streaming +- [ ] Update performance monitoring sections + +#### Article VI (Versioning): +- [ ] Add version increment reminders +- [ ] Include breaking change procedures +- [ ] Update migration requirements + +#### Article VII (Simplicity): +- [ ] Update project count limits +- [ ] Add pattern prohibition examples +- [ ] Include YAGNI reminders + +## Validation Steps + +1. **Before committing constitution changes:** + - [ ] All templates reference new requirements + - [ ] Examples updated to match new rules + - [ ] No contradictions between documents + +2. **After updating templates:** + - [ ] Run through a sample implementation plan + - [ ] Verify all constitution requirements addressed + - [ ] Check that templates are self-contained (readable without constitution) + +3. **Version tracking:** + - [ ] Update constitution version number + - [ ] Note version in template footers + - [ ] Add amendment to constitution history + +## Common Misses + +Watch for these often-forgotten updates: +- Command documentation (`/commands/*.md`) +- Checklist items in templates +- Example code/commands +- Domain-specific variations (web vs mobile vs CLI) +- Cross-references between documents + +## Template Sync Status + +Last sync check: 2025-07-16 +- Constitution version: 2.1.1 +- Templates aligned: ❌ (missing versioning, observability details) + +--- + +*This checklist ensures the constitution's principles are consistently applied across all project documentation.* \ No newline at end of file diff --git a/scripts/check-task-prerequisites.sh b/scripts/check-task-prerequisites.sh new file mode 100644 index 0000000..87fca37 --- /dev/null +++ b/scripts/check-task-prerequisites.sh @@ -0,0 +1,62 @@ +#!/bin/bash +# Check that implementation plan exists and find optional design documents +# Usage: ./check-task-prerequisites.sh [--json] + +set -e + +JSON_MODE=false +for arg in "$@"; do + case "$arg" in + --json) JSON_MODE=true ;; + --help|-h) echo "Usage: $0 [--json]"; exit 0 ;; + esac +done + +# Source common functions +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/common.sh" + +# Get all paths +eval $(get_feature_paths) + +# Check if on feature branch +check_feature_branch "$CURRENT_BRANCH" || exit 1 + +# Check if feature directory exists +if [[ ! -d "$FEATURE_DIR" ]]; then + echo "ERROR: Feature directory not found: $FEATURE_DIR" + echo "Run /specify first to create the feature structure." + exit 1 +fi + +# Check for implementation plan (required) +if [[ ! -f "$IMPL_PLAN" ]]; then + echo "ERROR: plan.md not found in $FEATURE_DIR" + echo "Run /plan first to create the plan." + exit 1 +fi + +if $JSON_MODE; then + # Build JSON array of available docs that actually exist + docs=() + [[ -f "$RESEARCH" ]] && docs+=("research.md") + [[ -f "$DATA_MODEL" ]] && docs+=("data-model.md") + ([[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]) && docs+=("contracts/") + [[ -f "$QUICKSTART" ]] && docs+=("quickstart.md") + # join array into JSON + json_docs=$(printf '"%s",' "${docs[@]}") + json_docs="[${json_docs%,}]" + printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs" +else + # List available design documents (optional) + echo "FEATURE_DIR:$FEATURE_DIR" + echo "AVAILABLE_DOCS:" + + # Use common check functions + check_file "$RESEARCH" "research.md" + check_file "$DATA_MODEL" "data-model.md" + check_dir "$CONTRACTS_DIR" "contracts/" + check_file "$QUICKSTART" "quickstart.md" +fi + +# Always succeed - task generation should work with whatever docs are available \ No newline at end of file diff --git a/scripts/common.sh b/scripts/common.sh new file mode 100644 index 0000000..d636491 --- /dev/null +++ b/scripts/common.sh @@ -0,0 +1,77 @@ +#!/bin/bash +# Common functions and variables for all scripts + +# Get repository root +get_repo_root() { + git rev-parse --show-toplevel +} + +# Get current branch +get_current_branch() { + git rev-parse --abbrev-ref HEAD +} + +# Check if current branch is a feature branch +# Returns 0 if valid, 1 if not +check_feature_branch() { + local branch="$1" + if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then + echo "ERROR: Not on a feature branch. Current branch: $branch" + echo "Feature branches should be named like: 001-feature-name" + return 1 + fi + return 0 +} + +# Get feature directory path +get_feature_dir() { + local repo_root="$1" + local branch="$2" + echo "$repo_root/specs/$branch" +} + +# Get all standard paths for a feature +# Usage: eval $(get_feature_paths) +# Sets: REPO_ROOT, CURRENT_BRANCH, FEATURE_DIR, FEATURE_SPEC, IMPL_PLAN, TASKS +get_feature_paths() { + local repo_root=$(get_repo_root) + local current_branch=$(get_current_branch) + local feature_dir=$(get_feature_dir "$repo_root" "$current_branch") + + echo "REPO_ROOT='$repo_root'" + echo "CURRENT_BRANCH='$current_branch'" + echo "FEATURE_DIR='$feature_dir'" + echo "FEATURE_SPEC='$feature_dir/spec.md'" + echo "IMPL_PLAN='$feature_dir/plan.md'" + echo "TASKS='$feature_dir/tasks.md'" + echo "RESEARCH='$feature_dir/research.md'" + echo "DATA_MODEL='$feature_dir/data-model.md'" + echo "QUICKSTART='$feature_dir/quickstart.md'" + echo "CONTRACTS_DIR='$feature_dir/contracts'" +} + +# Check if a file exists and report +check_file() { + local file="$1" + local description="$2" + if [[ -f "$file" ]]; then + echo " ✓ $description" + return 0 + else + echo " ✗ $description" + return 1 + fi +} + +# Check if a directory exists and has files +check_dir() { + local dir="$1" + local description="$2" + if [[ -d "$dir" ]] && [[ -n "$(ls -A "$dir" 2>/dev/null)" ]]; then + echo " ✓ $description" + return 0 + else + echo " ✗ $description" + return 1 + fi +} \ No newline at end of file diff --git a/scripts/create-new-feature.sh b/scripts/create-new-feature.sh new file mode 100644 index 0000000..69ea3c4 --- /dev/null +++ b/scripts/create-new-feature.sh @@ -0,0 +1,96 @@ +#!/bin/bash +# Create a new feature with branch, directory structure, and template +# Usage: ./create-new-feature.sh "feature description" +# ./create-new-feature.sh --json "feature description" + +set -e + +JSON_MODE=false + +# Collect non-flag args +ARGS=() +for arg in "$@"; do + case "$arg" in + --json) + JSON_MODE=true + ;; + --help|-h) + echo "Usage: $0 [--json] "; exit 0 ;; + *) + ARGS+=("$arg") ;; + esac +done + +FEATURE_DESCRIPTION="${ARGS[*]}" +if [ -z "$FEATURE_DESCRIPTION" ]; then + echo "Usage: $0 [--json] " >&2 + exit 1 +fi + +# Get repository root +REPO_ROOT=$(git rev-parse --show-toplevel) +SPECS_DIR="$REPO_ROOT/specs" + +# Create specs directory if it doesn't exist +mkdir -p "$SPECS_DIR" + +# Find the highest numbered feature directory +HIGHEST=0 +if [ -d "$SPECS_DIR" ]; then + for dir in "$SPECS_DIR"/*; do + if [ -d "$dir" ]; then + dirname=$(basename "$dir") + number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0") + number=$((10#$number)) + if [ "$number" -gt "$HIGHEST" ]; then + HIGHEST=$number + fi + fi + done +fi + +# Generate next feature number with zero padding +NEXT=$((HIGHEST + 1)) +FEATURE_NUM=$(printf "%03d" "$NEXT") + +# Create branch name from description +BRANCH_NAME=$(echo "$FEATURE_DESCRIPTION" | \ + tr '[:upper:]' '[:lower:]' | \ + sed 's/[^a-z0-9]/-/g' | \ + sed 's/-\+/-/g' | \ + sed 's/^-//' | \ + sed 's/-$//') + +# Extract 2-3 meaningful words +WORDS=$(echo "$BRANCH_NAME" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//') + +# Final branch name +BRANCH_NAME="${FEATURE_NUM}-${WORDS}" + +# Create and switch to new branch +git checkout -b "$BRANCH_NAME" + +# Create feature directory +FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME" +mkdir -p "$FEATURE_DIR" + +# Copy template if it exists +TEMPLATE="$REPO_ROOT/templates/spec-template.md" +SPEC_FILE="$FEATURE_DIR/spec.md" + +if [ -f "$TEMPLATE" ]; then + cp "$TEMPLATE" "$SPEC_FILE" +else + echo "Warning: Template not found at $TEMPLATE" >&2 + touch "$SPEC_FILE" +fi + +if $JSON_MODE; then + printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' \ + "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM" +else + # Output results for the LLM to use (legacy key: value format) + echo "BRANCH_NAME: $BRANCH_NAME" + echo "SPEC_FILE: $SPEC_FILE" + echo "FEATURE_NUM: $FEATURE_NUM" +fi \ No newline at end of file diff --git a/scripts/get-feature-paths.sh b/scripts/get-feature-paths.sh new file mode 100644 index 0000000..bfe5087 --- /dev/null +++ b/scripts/get-feature-paths.sh @@ -0,0 +1,23 @@ +#!/bin/bash +# Get paths for current feature branch without creating anything +# Used by commands that need to find existing feature files + +set -e + +# Source common functions +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/common.sh" + +# Get all paths +eval $(get_feature_paths) + +# Check if on feature branch +check_feature_branch "$CURRENT_BRANCH" || exit 1 + +# Output paths (don't create anything) +echo "REPO_ROOT: $REPO_ROOT" +echo "BRANCH: $CURRENT_BRANCH" +echo "FEATURE_DIR: $FEATURE_DIR" +echo "FEATURE_SPEC: $FEATURE_SPEC" +echo "IMPL_PLAN: $IMPL_PLAN" +echo "TASKS: $TASKS" \ No newline at end of file diff --git a/scripts/setup-plan.sh b/scripts/setup-plan.sh new file mode 100644 index 0000000..28bd056 --- /dev/null +++ b/scripts/setup-plan.sh @@ -0,0 +1,44 @@ +#!/bin/bash +# Setup implementation plan structure for current branch +# Returns paths needed for implementation plan generation +# Usage: ./setup-plan.sh [--json] + +set -e + +JSON_MODE=false +for arg in "$@"; do + case "$arg" in + --json) JSON_MODE=true ;; + --help|-h) echo "Usage: $0 [--json]"; exit 0 ;; + esac +done + +# Source common functions +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/common.sh" + +# Get all paths +eval $(get_feature_paths) + +# Check if on feature branch +check_feature_branch "$CURRENT_BRANCH" || exit 1 + +# Create specs directory if it doesn't exist +mkdir -p "$FEATURE_DIR" + +# Copy plan template if it exists +TEMPLATE="$REPO_ROOT/templates/plan-template.md" +if [ -f "$TEMPLATE" ]; then + cp "$TEMPLATE" "$IMPL_PLAN" +fi + +if $JSON_MODE; then + printf '{"FEATURE_SPEC":"%s","IMPL_PLAN":"%s","SPECS_DIR":"%s","BRANCH":"%s"}\n' \ + "$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" +else + # Output all paths for LLM use + echo "FEATURE_SPEC: $FEATURE_SPEC" + echo "IMPL_PLAN: $IMPL_PLAN" + echo "SPECS_DIR: $FEATURE_DIR" + echo "BRANCH: $CURRENT_BRANCH" +fi \ No newline at end of file diff --git a/scripts/update-agent-context.sh b/scripts/update-agent-context.sh new file mode 100644 index 0000000..51fa640 --- /dev/null +++ b/scripts/update-agent-context.sh @@ -0,0 +1,234 @@ +#!/bin/bash +# Incrementally update agent context files based on new feature plan +# Supports: CLAUDE.md, GEMINI.md, and .github/copilot-instructions.md +# O(1) operation - only reads current context file and new plan.md + +set -e + +REPO_ROOT=$(git rev-parse --show-toplevel) +CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD) +FEATURE_DIR="$REPO_ROOT/specs/$CURRENT_BRANCH" +NEW_PLAN="$FEATURE_DIR/plan.md" + +# Determine which agent context files to update +CLAUDE_FILE="$REPO_ROOT/CLAUDE.md" +GEMINI_FILE="$REPO_ROOT/GEMINI.md" +COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md" + +# Allow override via argument +AGENT_TYPE="$1" + +if [ ! -f "$NEW_PLAN" ]; then + echo "ERROR: No plan.md found at $NEW_PLAN" + exit 1 +fi + +echo "=== Updating agent context files for feature $CURRENT_BRANCH ===" + +# Extract tech from new plan +NEW_LANG=$(grep "^**Language/Version**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Language\/Version**: //' | grep -v "NEEDS CLARIFICATION" || echo "") +NEW_FRAMEWORK=$(grep "^**Primary Dependencies**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Primary Dependencies**: //' | grep -v "NEEDS CLARIFICATION" || echo "") +NEW_TESTING=$(grep "^**Testing**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Testing**: //' | grep -v "NEEDS CLARIFICATION" || echo "") +NEW_DB=$(grep "^**Storage**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Storage**: //' | grep -v "N/A" | grep -v "NEEDS CLARIFICATION" || echo "") +NEW_PROJECT_TYPE=$(grep "^**Project Type**: " "$NEW_PLAN" 2>/dev/null | head -1 | sed 's/^**Project Type**: //' || echo "") + +# Function to update a single agent context file +update_agent_file() { + local target_file="$1" + local agent_name="$2" + + echo "Updating $agent_name context file: $target_file" + + # Create temp file for new context + local temp_file=$(mktemp) + + # If file doesn't exist, create from template + if [ ! -f "$target_file" ]; then + echo "Creating new $agent_name context file..." + + # Check if this is the SDD repo itself + if [ -f "$REPO_ROOT/templates/agent-file-template.md" ]; then + cp "$REPO_ROOT/templates/agent-file-template.md" "$temp_file" + else + echo "ERROR: Template not found at $REPO_ROOT/templates/agent-file-template.md" + return 1 + fi + + # Replace placeholders + sed -i.bak "s/\[PROJECT NAME\]/$(basename $REPO_ROOT)/" "$temp_file" + sed -i.bak "s/\[DATE\]/$(date +%Y-%m-%d)/" "$temp_file" + sed -i.bak "s/\[EXTRACTED FROM ALL PLAN.MD FILES\]/- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)/" "$temp_file" + + # Add project structure based on type + if [[ "$NEW_PROJECT_TYPE" == *"web"* ]]; then + sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|backend/\nfrontend/\ntests/|" "$temp_file" + else + sed -i.bak "s|\[ACTUAL STRUCTURE FROM PLANS\]|src/\ntests/|" "$temp_file" + fi + + # Add minimal commands + if [[ "$NEW_LANG" == *"Python"* ]]; then + COMMANDS="cd src && pytest && ruff check ." + elif [[ "$NEW_LANG" == *"Rust"* ]]; then + COMMANDS="cargo test && cargo clippy" + elif [[ "$NEW_LANG" == *"JavaScript"* ]] || [[ "$NEW_LANG" == *"TypeScript"* ]]; then + COMMANDS="npm test && npm run lint" + else + COMMANDS="# Add commands for $NEW_LANG" + fi + sed -i.bak "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$COMMANDS|" "$temp_file" + + # Add code style + sed -i.bak "s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$NEW_LANG: Follow standard conventions|" "$temp_file" + + # Add recent changes + sed -i.bak "s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|- $CURRENT_BRANCH: Added $NEW_LANG + $NEW_FRAMEWORK|" "$temp_file" + + rm "$temp_file.bak" + else + echo "Updating existing $agent_name context file..." + + # Extract manual additions + local manual_start=$(grep -n "" "$target_file" | cut -d: -f1) + local manual_end=$(grep -n "" "$target_file" | cut -d: -f1) + + if [ ! -z "$manual_start" ] && [ ! -z "$manual_end" ]; then + sed -n "${manual_start},${manual_end}p" "$target_file" > /tmp/manual_additions.txt + fi + + # Parse existing file and create updated version + python3 - << EOF +import re +import sys +from datetime import datetime + +# Read existing file +with open("$target_file", 'r') as f: + content = f.read() + +# Check if new tech already exists +tech_section = re.search(r'## Active Technologies\n(.*?)\n\n', content, re.DOTALL) +if tech_section: + existing_tech = tech_section.group(1) + + # Add new tech if not already present + new_additions = [] + if "$NEW_LANG" and "$NEW_LANG" not in existing_tech: + new_additions.append(f"- $NEW_LANG + $NEW_FRAMEWORK ($CURRENT_BRANCH)") + if "$NEW_DB" and "$NEW_DB" not in existing_tech and "$NEW_DB" != "N/A": + new_additions.append(f"- $NEW_DB ($CURRENT_BRANCH)") + + if new_additions: + updated_tech = existing_tech + "\n" + "\n".join(new_additions) + content = content.replace(tech_section.group(0), f"## Active Technologies\n{updated_tech}\n\n") + +# Update project structure if needed +if "$NEW_PROJECT_TYPE" == "web" and "frontend/" not in content: + struct_section = re.search(r'## Project Structure\n\`\`\`\n(.*?)\n\`\`\`', content, re.DOTALL) + if struct_section: + updated_struct = struct_section.group(1) + "\nfrontend/src/ # Web UI" + content = re.sub(r'(## Project Structure\n\`\`\`\n).*?(\n\`\`\`)', + f'\\1{updated_struct}\\2', content, flags=re.DOTALL) + +# Add new commands if language is new +if "$NEW_LANG" and f"# {NEW_LANG}" not in content: + commands_section = re.search(r'## Commands\n\`\`\`bash\n(.*?)\n\`\`\`', content, re.DOTALL) + if not commands_section: + commands_section = re.search(r'## Commands\n(.*?)\n\n', content, re.DOTALL) + + if commands_section: + new_commands = commands_section.group(1) + if "Python" in "$NEW_LANG": + new_commands += "\ncd src && pytest && ruff check ." + elif "Rust" in "$NEW_LANG": + new_commands += "\ncargo test && cargo clippy" + elif "JavaScript" in "$NEW_LANG" or "TypeScript" in "$NEW_LANG": + new_commands += "\nnpm test && npm run lint" + + if "```bash" in content: + content = re.sub(r'(## Commands\n\`\`\`bash\n).*?(\n\`\`\`)', + f'\\1{new_commands}\\2', content, flags=re.DOTALL) + else: + content = re.sub(r'(## Commands\n).*?(\n\n)', + f'\\1{new_commands}\\2', content, flags=re.DOTALL) + +# Update recent changes (keep only last 3) +changes_section = re.search(r'## Recent Changes\n(.*?)(\n\n|$)', content, re.DOTALL) +if changes_section: + changes = changes_section.group(1).strip().split('\n') + changes.insert(0, f"- $CURRENT_BRANCH: Added $NEW_LANG + $NEW_FRAMEWORK") + # Keep only last 3 + changes = changes[:3] + content = re.sub(r'(## Recent Changes\n).*?(\n\n|$)', + f'\\1{chr(10).join(changes)}\\2', content, flags=re.DOTALL) + +# Update date +content = re.sub(r'Last updated: \d{4}-\d{2}-\d{2}', + f'Last updated: {datetime.now().strftime("%Y-%m-%d")}', content) + +# Write to temp file +with open("$temp_file", 'w') as f: + f.write(content) +EOF + + # Restore manual additions if they exist + if [ -f /tmp/manual_additions.txt ]; then + # Remove old manual section from temp file + sed -i.bak '//,//d' "$temp_file" + # Append manual additions + cat /tmp/manual_additions.txt >> "$temp_file" + rm /tmp/manual_additions.txt "$temp_file.bak" + fi + fi + + # Move temp file to final location + mv "$temp_file" "$target_file" + echo "✅ $agent_name context file updated successfully" +} + +# Update files based on argument or detect existing files +case "$AGENT_TYPE" in + "claude") + update_agent_file "$CLAUDE_FILE" "Claude Code" + ;; + "gemini") + update_agent_file "$GEMINI_FILE" "Gemini CLI" + ;; + "copilot") + update_agent_file "$COPILOT_FILE" "GitHub Copilot" + ;; + "") + # Update all existing files + [ -f "$CLAUDE_FILE" ] && update_agent_file "$CLAUDE_FILE" "Claude Code" + [ -f "$GEMINI_FILE" ] && update_agent_file "$GEMINI_FILE" "Gemini CLI" + [ -f "$COPILOT_FILE" ] && update_agent_file "$COPILOT_FILE" "GitHub Copilot" + + # If no files exist, create based on current directory or ask user + if [ ! -f "$CLAUDE_FILE" ] && [ ! -f "$GEMINI_FILE" ] && [ ! -f "$COPILOT_FILE" ]; then + echo "No agent context files found. Creating Claude Code context file by default." + update_agent_file "$CLAUDE_FILE" "Claude Code" + fi + ;; + *) + echo "ERROR: Unknown agent type '$AGENT_TYPE'. Use: claude, gemini, copilot, or leave empty for all." + exit 1 + ;; +esac +echo "" +echo "Summary of changes:" +if [ ! -z "$NEW_LANG" ]; then + echo "- Added language: $NEW_LANG" +fi +if [ ! -z "$NEW_FRAMEWORK" ]; then + echo "- Added framework: $NEW_FRAMEWORK" +fi +if [ ! -z "$NEW_DB" ] && [ "$NEW_DB" != "N/A" ]; then + echo "- Added database: $NEW_DB" +fi + +echo "" +echo "Usage: $0 [claude|gemini|copilot]" +echo " - No argument: Update all existing agent context files" +echo " - claude: Update only CLAUDE.md" +echo " - gemini: Update only GEMINI.md" +echo " - copilot: Update only .github/copilot-instructions.md" \ No newline at end of file From a0f9a84138c1976a00af5f9ad76223527e4dac89 Mon Sep 17 00:00:00 2001 From: barisgit Date: Sun, 7 Sep 2025 19:26:03 +0200 Subject: [PATCH 04/13] Add banner --- kicad_lib_manager/commands/pin/command.py | 6 +- kicad_lib_manager/main.py | 14 ++++- kicad_lib_manager/utils/__init__.py | 4 ++ kicad_lib_manager/utils/banner.py | 68 +++++++++++++++++++++++ 4 files changed, 86 insertions(+), 6 deletions(-) create mode 100644 kicad_lib_manager/utils/banner.py diff --git a/kicad_lib_manager/commands/pin/command.py b/kicad_lib_manager/commands/pin/command.py index a87468e..5560664 100644 --- a/kicad_lib_manager/commands/pin/command.py +++ b/kicad_lib_manager/commands/pin/command.py @@ -112,7 +112,7 @@ def pin( console.print(f"[blue]Found KiCad configuration at:[/blue] {kicad_config}") except Exception as e: console.print(f"[red]Error finding KiCad configuration: {e}[/red]") - raise typer.Exit(1) + raise typer.Exit(1) from e # If --all is specified, get all libraries from the directory if all_libs and not symbols and not footprints: @@ -128,7 +128,7 @@ def pin( ) except Exception as e: console.print(f"[red]Error listing libraries: {e}[/red]") - raise typer.Exit(1) + raise typer.Exit(1) from e # Ensure we have lists (Typer should already provide lists) if not isinstance(symbols, list): @@ -206,4 +206,4 @@ def pin( console.print(table) except Exception as e: console.print(f"[red]Error pinning libraries: {e}[/red]") - raise typer.Exit(1) + raise typer.Exit(1) from e diff --git a/kicad_lib_manager/main.py b/kicad_lib_manager/main.py index fbe7546..4dc47e1 100644 --- a/kicad_lib_manager/main.py +++ b/kicad_lib_manager/main.py @@ -14,6 +14,7 @@ from .commands.list_libraries import list_app from .commands.pin import pin_app from .commands.status import status_app +from .utils.banner import show_banner # Install rich traceback handler for better error display install(show_locals=True) @@ -29,13 +30,16 @@ rich_markup_mode="rich", pretty_exceptions_enable=True, pretty_exceptions_show_locals=False, - no_args_is_help=True, + invoke_without_command=True, ) def version_callback(value: bool) -> None: """Print version information and exit.""" if value: + show_banner(console, justify="left") + console.print() + version = importlib.metadata.version("kilm") console.print(f"KiCad Library Manager (KiLM) version [cyan]{version}[/cyan]") raise typer.Exit() @@ -43,7 +47,7 @@ def version_callback(value: bool) -> None: @app.callback() def main( - version: Annotated[ + _version: Annotated[ Optional[bool], typer.Option( "--version", @@ -66,7 +70,11 @@ def main( • [cyan]kilm list[/cyan] - List available libraries • [cyan]kilm sync[/cyan] - Update library content """ - pass + # Show banner when no arguments are provided, centered + show_banner(console) + console.print() # Add blank line after banner + + console.print("[dim]Use 'kilm --help' to see all commands.[/dim]", justify="center") # Register command apps (migrated to Typer) diff --git a/kicad_lib_manager/utils/__init__.py b/kicad_lib_manager/utils/__init__.py index 53101f1..c6a00df 100644 --- a/kicad_lib_manager/utils/__init__.py +++ b/kicad_lib_manager/utils/__init__.py @@ -1,3 +1,7 @@ """ Utility functions for KiCad Library Manager """ + +from .banner import show_banner + +__all__ = ["show_banner"] diff --git a/kicad_lib_manager/utils/banner.py b/kicad_lib_manager/utils/banner.py new file mode 100644 index 0000000..82f1f41 --- /dev/null +++ b/kicad_lib_manager/utils/banner.py @@ -0,0 +1,68 @@ +""" +Banner utilities for KiCad Library Manager +""" + +from typing import Literal + +from rich.console import Console + + +def show_banner( + console: Console, justify: Literal["center", "left", "right"] = "center" +) -> None: + """ + Display the KiLM banner with colorful ASCII art. + + Front characters (KILM text) and back characters (box drawing) use different colors + to create a layered visual effect. + + Args: + console: Rich console instance to print the banner to + """ + banner_lines = [ + "██╗ ██╗██╗██╗ ███╗ ███╗", + "██║ ██╔╝██║██║ ████╗ ████║", + "█████╔╝ ██║██║ ██╔████╔██║", + "██╔═██╗ ██║██║ ██║╚██╔╝██║", + "██║ ██╗██║███████╗██║ ╚═╝ ██║", + "╚═╝ ╚═╝╚═╝╚══════╝╚═╝ ╚═╝", + ] + + # Colors for front characters (KILM text) - gradient effect + front_colors = [ + "bright_blue", + "bright_blue", + "bright_cyan", + "bright_cyan", + "bright_green", + "bright_white", + ] + + # Colors for back characters (box drawing) - darker, more subtle + back_colors = [ + "white", + "white", + "white", + "white", + "white", + "white", + ] + + # Print each line with different colors for front and back characters + for line, front_color, back_color in zip(banner_lines, front_colors, back_colors): + # Split the line into front characters (KILM) and back characters (box drawing) + # The KILM text is represented by the block characters ██╗, ██║, etc. + # The back characters are the decorative box drawing elements + + # Only the solid block characters ██ are front characters + # All other characters (╗╔╝║═╚ and spaces) are back characters + colored_line = "" + for char in line: + if char == "█": + # Only the solid block character is the front character + colored_line += f"[bold {front_color}]{char}[/]" + else: + # All other characters are back characters + colored_line += f"[{back_color}]{char}[/]" + + console.print(colored_line, justify=justify) From 1defed3c7855b183c4c79b0f829e3c34b6435a95 Mon Sep 17 00:00:00 2001 From: barisgit Date: Sun, 7 Sep 2025 19:26:16 +0200 Subject: [PATCH 05/13] Use uv for workflows --- .github/workflows/python-package.yml | 5 +- uv.lock | 1471 ++++++++++++++++++++++++++ 2 files changed, 1473 insertions(+), 3 deletions(-) create mode 100644 uv.lock diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index fb120b8..55a4809 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -24,10 +24,9 @@ jobs: with: python-version: ${{ matrix.python-version }} - - name: Install dependencies + - name: Install dependencies using uv run: | - python -m pip install --upgrade pip - pip install -e .[dev] + uv sync --extra dev - name: Lint with ruff run: | diff --git a/uv.lock b/uv.lock new file mode 100644 index 0000000..3f373ee --- /dev/null +++ b/uv.lock @@ -0,0 +1,1471 @@ +version = 1 +revision = 3 +requires-python = ">=3.8" +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] + +[[package]] +name = "black" +version = "24.8.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "mypy-extensions", marker = "python_full_version < '3.9'" }, + { name = "packaging", marker = "python_full_version < '3.9'" }, + { name = "pathspec", marker = "python_full_version < '3.9'" }, + { name = "platformdirs", version = "4.3.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "tomli", marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/b0/46fb0d4e00372f4a86a6f8efa3cb193c9f64863615e39010b1477e010578/black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f", size = 644810, upload-time = "2024-08-02T17:43:18.405Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/47/6e/74e29edf1fba3887ed7066930a87f698ffdcd52c5dbc263eabb06061672d/black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6", size = 1632092, upload-time = "2024-08-02T17:47:26.911Z" }, + { url = "https://files.pythonhosted.org/packages/ab/49/575cb6c3faee690b05c9d11ee2e8dba8fbd6d6c134496e644c1feb1b47da/black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb", size = 1457529, upload-time = "2024-08-02T17:47:29.109Z" }, + { url = "https://files.pythonhosted.org/packages/7a/b4/d34099e95c437b53d01c4aa37cf93944b233066eb034ccf7897fa4e5f286/black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42", size = 1757443, upload-time = "2024-08-02T17:46:20.306Z" }, + { url = "https://files.pythonhosted.org/packages/87/a0/6d2e4175ef364b8c4b64f8441ba041ed65c63ea1db2720d61494ac711c15/black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a", size = 1418012, upload-time = "2024-08-02T17:47:20.33Z" }, + { url = "https://files.pythonhosted.org/packages/08/a6/0a3aa89de9c283556146dc6dbda20cd63a9c94160a6fbdebaf0918e4a3e1/black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1", size = 1615080, upload-time = "2024-08-02T17:48:05.467Z" }, + { url = "https://files.pythonhosted.org/packages/db/94/b803d810e14588bb297e565821a947c108390a079e21dbdcb9ab6956cd7a/black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af", size = 1438143, upload-time = "2024-08-02T17:47:30.247Z" }, + { url = "https://files.pythonhosted.org/packages/a5/b5/f485e1bbe31f768e2e5210f52ea3f432256201289fd1a3c0afda693776b0/black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4", size = 1738774, upload-time = "2024-08-02T17:46:17.837Z" }, + { url = "https://files.pythonhosted.org/packages/a8/69/a000fc3736f89d1bdc7f4a879f8aaf516fb03613bb51a0154070383d95d9/black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af", size = 1427503, upload-time = "2024-08-02T17:46:22.654Z" }, + { url = "https://files.pythonhosted.org/packages/a2/a8/05fb14195cfef32b7c8d4585a44b7499c2a4b205e1662c427b941ed87054/black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368", size = 1646132, upload-time = "2024-08-02T17:49:52.843Z" }, + { url = "https://files.pythonhosted.org/packages/41/77/8d9ce42673e5cb9988f6df73c1c5c1d4e9e788053cccd7f5fb14ef100982/black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed", size = 1448665, upload-time = "2024-08-02T17:47:54.479Z" }, + { url = "https://files.pythonhosted.org/packages/cc/94/eff1ddad2ce1d3cc26c162b3693043c6b6b575f538f602f26fe846dfdc75/black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018", size = 1762458, upload-time = "2024-08-02T17:46:19.384Z" }, + { url = "https://files.pythonhosted.org/packages/28/ea/18b8d86a9ca19a6942e4e16759b2fa5fc02bbc0eb33c1b866fcd387640ab/black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2", size = 1436109, upload-time = "2024-08-02T17:46:52.97Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d4/ae03761ddecc1a37d7e743b89cccbcf3317479ff4b88cfd8818079f890d0/black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd", size = 1617322, upload-time = "2024-08-02T17:51:20.203Z" }, + { url = "https://files.pythonhosted.org/packages/14/4b/4dfe67eed7f9b1ddca2ec8e4418ea74f0d1dc84d36ea874d618ffa1af7d4/black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2", size = 1442108, upload-time = "2024-08-02T17:50:40.824Z" }, + { url = "https://files.pythonhosted.org/packages/97/14/95b3f91f857034686cae0e73006b8391d76a8142d339b42970eaaf0416ea/black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e", size = 1745786, upload-time = "2024-08-02T17:46:02.939Z" }, + { url = "https://files.pythonhosted.org/packages/95/54/68b8883c8aa258a6dde958cd5bdfada8382bec47c5162f4a01e66d839af1/black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920", size = 1426754, upload-time = "2024-08-02T17:46:38.603Z" }, + { url = "https://files.pythonhosted.org/packages/13/b2/b3f24fdbb46f0e7ef6238e131f13572ee8279b70f237f221dd168a9dba1a/black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c", size = 1631706, upload-time = "2024-08-02T17:49:57.606Z" }, + { url = "https://files.pythonhosted.org/packages/d9/35/31010981e4a05202a84a3116423970fd1a59d2eda4ac0b3570fbb7029ddc/black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e", size = 1457429, upload-time = "2024-08-02T17:49:12.764Z" }, + { url = "https://files.pythonhosted.org/packages/27/25/3f706b4f044dd569a20a4835c3b733dedea38d83d2ee0beb8178a6d44945/black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47", size = 1756488, upload-time = "2024-08-02T17:46:08.067Z" }, + { url = "https://files.pythonhosted.org/packages/63/72/79375cd8277cbf1c5670914e6bd4c1b15dea2c8f8e906dc21c448d0535f0/black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb", size = 1417721, upload-time = "2024-08-02T17:46:42.637Z" }, + { url = "https://files.pythonhosted.org/packages/27/1e/83fa8a787180e1632c3d831f7e58994d7aaf23a0961320d21e84f922f919/black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed", size = 206504, upload-time = "2024-08-02T17:43:15.747Z" }, +] + +[[package]] +name = "black" +version = "25.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "mypy-extensions", marker = "python_full_version >= '3.9'" }, + { name = "packaging", marker = "python_full_version >= '3.9'" }, + { name = "pathspec", marker = "python_full_version >= '3.9'" }, + { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449, upload-time = "2025-01-29T04:15:40.373Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/4d/3b/4ba3f93ac8d90410423fdd31d7541ada9bcee1df32fb90d26de41ed40e1d/black-25.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:759e7ec1e050a15f89b770cefbf91ebee8917aac5c20483bc2d80a6c3a04df32", size = 1629419, upload-time = "2025-01-29T05:37:06.642Z" }, + { url = "https://files.pythonhosted.org/packages/b4/02/0bde0485146a8a5e694daed47561785e8b77a0466ccc1f3e485d5ef2925e/black-25.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e519ecf93120f34243e6b0054db49c00a35f84f195d5bce7e9f5cfc578fc2da", size = 1461080, upload-time = "2025-01-29T05:37:09.321Z" }, + { url = "https://files.pythonhosted.org/packages/52/0e/abdf75183c830eaca7589144ff96d49bce73d7ec6ad12ef62185cc0f79a2/black-25.1.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:055e59b198df7ac0b7efca5ad7ff2516bca343276c466be72eb04a3bcc1f82d7", size = 1766886, upload-time = "2025-01-29T04:18:24.432Z" }, + { url = "https://files.pythonhosted.org/packages/dc/a6/97d8bb65b1d8a41f8a6736222ba0a334db7b7b77b8023ab4568288f23973/black-25.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:db8ea9917d6f8fc62abd90d944920d95e73c83a5ee3383493e35d271aca872e9", size = 1419404, upload-time = "2025-01-29T04:19:04.296Z" }, + { url = "https://files.pythonhosted.org/packages/7e/4f/87f596aca05c3ce5b94b8663dbfe242a12843caaa82dd3f85f1ffdc3f177/black-25.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a39337598244de4bae26475f77dda852ea00a93bd4c728e09eacd827ec929df0", size = 1614372, upload-time = "2025-01-29T05:37:11.71Z" }, + { url = "https://files.pythonhosted.org/packages/e7/d0/2c34c36190b741c59c901e56ab7f6e54dad8df05a6272a9747ecef7c6036/black-25.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:96c1c7cd856bba8e20094e36e0f948718dc688dba4a9d78c3adde52b9e6c2299", size = 1442865, upload-time = "2025-01-29T05:37:14.309Z" }, + { url = "https://files.pythonhosted.org/packages/21/d4/7518c72262468430ead45cf22bd86c883a6448b9eb43672765d69a8f1248/black-25.1.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bce2e264d59c91e52d8000d507eb20a9aca4a778731a08cfff7e5ac4a4bb7096", size = 1749699, upload-time = "2025-01-29T04:18:17.688Z" }, + { url = "https://files.pythonhosted.org/packages/58/db/4f5beb989b547f79096e035c4981ceb36ac2b552d0ac5f2620e941501c99/black-25.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:172b1dbff09f86ce6f4eb8edf9dede08b1fce58ba194c87d7a4f1a5aa2f5b3c2", size = 1428028, upload-time = "2025-01-29T04:18:51.711Z" }, + { url = "https://files.pythonhosted.org/packages/83/71/3fe4741df7adf015ad8dfa082dd36c94ca86bb21f25608eb247b4afb15b2/black-25.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4b60580e829091e6f9238c848ea6750efed72140b91b048770b64e74fe04908b", size = 1650988, upload-time = "2025-01-29T05:37:16.707Z" }, + { url = "https://files.pythonhosted.org/packages/13/f3/89aac8a83d73937ccd39bbe8fc6ac8860c11cfa0af5b1c96d081facac844/black-25.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1e2978f6df243b155ef5fa7e558a43037c3079093ed5d10fd84c43900f2d8ecc", size = 1453985, upload-time = "2025-01-29T05:37:18.273Z" }, + { url = "https://files.pythonhosted.org/packages/6f/22/b99efca33f1f3a1d2552c714b1e1b5ae92efac6c43e790ad539a163d1754/black-25.1.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b48735872ec535027d979e8dcb20bf4f70b5ac75a8ea99f127c106a7d7aba9f", size = 1783816, upload-time = "2025-01-29T04:18:33.823Z" }, + { url = "https://files.pythonhosted.org/packages/18/7e/a27c3ad3822b6f2e0e00d63d58ff6299a99a5b3aee69fa77cd4b0076b261/black-25.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:ea0213189960bda9cf99be5b8c8ce66bb054af5e9e861249cd23471bd7b0b3ba", size = 1440860, upload-time = "2025-01-29T04:19:12.944Z" }, + { url = "https://files.pythonhosted.org/packages/98/87/0edf98916640efa5d0696e1abb0a8357b52e69e82322628f25bf14d263d1/black-25.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:8f0b18a02996a836cc9c9c78e5babec10930862827b1b724ddfe98ccf2f2fe4f", size = 1650673, upload-time = "2025-01-29T05:37:20.574Z" }, + { url = "https://files.pythonhosted.org/packages/52/e5/f7bf17207cf87fa6e9b676576749c6b6ed0d70f179a3d812c997870291c3/black-25.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:afebb7098bfbc70037a053b91ae8437c3857482d3a690fefc03e9ff7aa9a5fd3", size = 1453190, upload-time = "2025-01-29T05:37:22.106Z" }, + { url = "https://files.pythonhosted.org/packages/e3/ee/adda3d46d4a9120772fae6de454c8495603c37c4c3b9c60f25b1ab6401fe/black-25.1.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:030b9759066a4ee5e5aca28c3c77f9c64789cdd4de8ac1df642c40b708be6171", size = 1782926, upload-time = "2025-01-29T04:18:58.564Z" }, + { url = "https://files.pythonhosted.org/packages/cc/64/94eb5f45dcb997d2082f097a3944cfc7fe87e071907f677e80788a2d7b7a/black-25.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:a22f402b410566e2d1c950708c77ebf5ebd5d0d88a6a2e87c86d9fb48afa0d18", size = 1442613, upload-time = "2025-01-29T04:19:27.63Z" }, + { url = "https://files.pythonhosted.org/packages/d3/b6/ae7507470a4830dbbfe875c701e84a4a5fb9183d1497834871a715716a92/black-25.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a1ee0a0c330f7b5130ce0caed9936a904793576ef4d2b98c40835d6a65afa6a0", size = 1628593, upload-time = "2025-01-29T05:37:23.672Z" }, + { url = "https://files.pythonhosted.org/packages/24/c1/ae36fa59a59f9363017ed397750a0cd79a470490860bc7713967d89cdd31/black-25.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3df5f1bf91d36002b0a75389ca8663510cf0531cca8aa5c1ef695b46d98655f", size = 1460000, upload-time = "2025-01-29T05:37:25.829Z" }, + { url = "https://files.pythonhosted.org/packages/ac/b6/98f832e7a6c49aa3a464760c67c7856363aa644f2f3c74cf7d624168607e/black-25.1.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9e6827d563a2c820772b32ce8a42828dc6790f095f441beef18f96aa6f8294e", size = 1765963, upload-time = "2025-01-29T04:18:38.116Z" }, + { url = "https://files.pythonhosted.org/packages/ce/e9/2cb0a017eb7024f70e0d2e9bdb8c5a5b078c5740c7f8816065d06f04c557/black-25.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:bacabb307dca5ebaf9c118d2d2f6903da0d62c9faa82bd21a33eecc319559355", size = 1419419, upload-time = "2025-01-29T04:18:30.191Z" }, + { url = "https://files.pythonhosted.org/packages/09/71/54e999902aed72baf26bca0d50781b01838251a462612966e9fc4891eadd/black-25.1.0-py3-none-any.whl", hash = "sha256:95e8176dae143ba9097f351d174fdaf0ccd29efb414b362ae3fd72bf0f710717", size = 207646, upload-time = "2025-01-29T04:15:38.082Z" }, +] + +[[package]] +name = "certifi" +version = "2025.8.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/dc/67/960ebe6bf230a96cda2e0abcf73af550ec4f090005363542f0765df162e0/certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407", size = 162386, upload-time = "2025-08-03T03:07:47.08Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/48/1549795ba7742c948d2ad169c1c8cdbae65bc450d6cd753d124b17c8cd32/certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5", size = 161216, upload-time = "2025-08-03T03:07:45.777Z" }, +] + +[[package]] +name = "cfgv" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/11/74/539e56497d9bd1d484fd863dd69cbbfa653cd2aa27abfe35653494d85e94/cfgv-3.4.0.tar.gz", hash = "sha256:e52591d4c5f5dead8e0f673fb16db7949d2cfb3f7da4582893288f0ded8fe560", size = 7114, upload-time = "2023-08-12T20:38:17.776Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c5/55/51844dd50c4fc7a33b653bfaba4c2456f06955289ca770a5dbd5fd267374/cfgv-3.4.0-py2.py3-none-any.whl", hash = "sha256:b7265b1f29fd3316bfcd2b330d63d024f2bfd8bcb8b0272f8e19a504856c48f9", size = 7249, upload-time = "2023-08-12T20:38:16.269Z" }, +] + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/2d/5fd176ceb9b2fc619e63405525573493ca23441330fcdaee6bef9460e924/charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14", size = 122371, upload-time = "2025-08-09T07:57:28.46Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d6/98/f3b8013223728a99b908c9344da3aa04ee6e3fa235f19409033eda92fb78/charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72", size = 207695, upload-time = "2025-08-09T07:55:36.452Z" }, + { url = "https://files.pythonhosted.org/packages/21/40/5188be1e3118c82dcb7c2a5ba101b783822cfb413a0268ed3be0468532de/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe", size = 147153, upload-time = "2025-08-09T07:55:38.467Z" }, + { url = "https://files.pythonhosted.org/packages/37/60/5d0d74bc1e1380f0b72c327948d9c2aca14b46a9efd87604e724260f384c/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601", size = 160428, upload-time = "2025-08-09T07:55:40.072Z" }, + { url = "https://files.pythonhosted.org/packages/85/9a/d891f63722d9158688de58d050c59dc3da560ea7f04f4c53e769de5140f5/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c", size = 157627, upload-time = "2025-08-09T07:55:41.706Z" }, + { url = "https://files.pythonhosted.org/packages/65/1a/7425c952944a6521a9cfa7e675343f83fd82085b8af2b1373a2409c683dc/charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2", size = 152388, upload-time = "2025-08-09T07:55:43.262Z" }, + { url = "https://files.pythonhosted.org/packages/f0/c9/a2c9c2a355a8594ce2446085e2ec97fd44d323c684ff32042e2a6b718e1d/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0", size = 150077, upload-time = "2025-08-09T07:55:44.903Z" }, + { url = "https://files.pythonhosted.org/packages/3b/38/20a1f44e4851aa1c9105d6e7110c9d020e093dfa5836d712a5f074a12bf7/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0", size = 161631, upload-time = "2025-08-09T07:55:46.346Z" }, + { url = "https://files.pythonhosted.org/packages/a4/fa/384d2c0f57edad03d7bec3ebefb462090d8905b4ff5a2d2525f3bb711fac/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0", size = 159210, upload-time = "2025-08-09T07:55:47.539Z" }, + { url = "https://files.pythonhosted.org/packages/33/9e/eca49d35867ca2db336b6ca27617deed4653b97ebf45dfc21311ce473c37/charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a", size = 153739, upload-time = "2025-08-09T07:55:48.744Z" }, + { url = "https://files.pythonhosted.org/packages/2a/91/26c3036e62dfe8de8061182d33be5025e2424002125c9500faff74a6735e/charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f", size = 99825, upload-time = "2025-08-09T07:55:50.305Z" }, + { url = "https://files.pythonhosted.org/packages/e2/c6/f05db471f81af1fa01839d44ae2a8bfeec8d2a8b4590f16c4e7393afd323/charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669", size = 107452, upload-time = "2025-08-09T07:55:51.461Z" }, + { url = "https://files.pythonhosted.org/packages/7f/b5/991245018615474a60965a7c9cd2b4efbaabd16d582a5547c47ee1c7730b/charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b", size = 204483, upload-time = "2025-08-09T07:55:53.12Z" }, + { url = "https://files.pythonhosted.org/packages/c7/2a/ae245c41c06299ec18262825c1569c5d3298fc920e4ddf56ab011b417efd/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64", size = 145520, upload-time = "2025-08-09T07:55:54.712Z" }, + { url = "https://files.pythonhosted.org/packages/3a/a4/b3b6c76e7a635748c4421d2b92c7b8f90a432f98bda5082049af37ffc8e3/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91", size = 158876, upload-time = "2025-08-09T07:55:56.024Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e6/63bb0e10f90a8243c5def74b5b105b3bbbfb3e7bb753915fe333fb0c11ea/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f", size = 156083, upload-time = "2025-08-09T07:55:57.582Z" }, + { url = "https://files.pythonhosted.org/packages/87/df/b7737ff046c974b183ea9aa111b74185ac8c3a326c6262d413bd5a1b8c69/charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07", size = 150295, upload-time = "2025-08-09T07:55:59.147Z" }, + { url = "https://files.pythonhosted.org/packages/61/f1/190d9977e0084d3f1dc169acd060d479bbbc71b90bf3e7bf7b9927dec3eb/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30", size = 148379, upload-time = "2025-08-09T07:56:00.364Z" }, + { url = "https://files.pythonhosted.org/packages/4c/92/27dbe365d34c68cfe0ca76f1edd70e8705d82b378cb54ebbaeabc2e3029d/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14", size = 160018, upload-time = "2025-08-09T07:56:01.678Z" }, + { url = "https://files.pythonhosted.org/packages/99/04/baae2a1ea1893a01635d475b9261c889a18fd48393634b6270827869fa34/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c", size = 157430, upload-time = "2025-08-09T07:56:02.87Z" }, + { url = "https://files.pythonhosted.org/packages/2f/36/77da9c6a328c54d17b960c89eccacfab8271fdaaa228305330915b88afa9/charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae", size = 151600, upload-time = "2025-08-09T07:56:04.089Z" }, + { url = "https://files.pythonhosted.org/packages/64/d4/9eb4ff2c167edbbf08cdd28e19078bf195762e9bd63371689cab5ecd3d0d/charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849", size = 99616, upload-time = "2025-08-09T07:56:05.658Z" }, + { url = "https://files.pythonhosted.org/packages/f4/9c/996a4a028222e7761a96634d1820de8a744ff4327a00ada9c8942033089b/charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c", size = 107108, upload-time = "2025-08-09T07:56:07.176Z" }, + { url = "https://files.pythonhosted.org/packages/e9/5e/14c94999e418d9b87682734589404a25854d5f5d0408df68bc15b6ff54bb/charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1", size = 205655, upload-time = "2025-08-09T07:56:08.475Z" }, + { url = "https://files.pythonhosted.org/packages/7d/a8/c6ec5d389672521f644505a257f50544c074cf5fc292d5390331cd6fc9c3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884", size = 146223, upload-time = "2025-08-09T07:56:09.708Z" }, + { url = "https://files.pythonhosted.org/packages/fc/eb/a2ffb08547f4e1e5415fb69eb7db25932c52a52bed371429648db4d84fb1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018", size = 159366, upload-time = "2025-08-09T07:56:11.326Z" }, + { url = "https://files.pythonhosted.org/packages/82/10/0fd19f20c624b278dddaf83b8464dcddc2456cb4b02bb902a6da126b87a1/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392", size = 157104, upload-time = "2025-08-09T07:56:13.014Z" }, + { url = "https://files.pythonhosted.org/packages/16/ab/0233c3231af734f5dfcf0844aa9582d5a1466c985bbed6cedab85af9bfe3/charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f", size = 151830, upload-time = "2025-08-09T07:56:14.428Z" }, + { url = "https://files.pythonhosted.org/packages/ae/02/e29e22b4e02839a0e4a06557b1999d0a47db3567e82989b5bb21f3fbbd9f/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154", size = 148854, upload-time = "2025-08-09T07:56:16.051Z" }, + { url = "https://files.pythonhosted.org/packages/05/6b/e2539a0a4be302b481e8cafb5af8792da8093b486885a1ae4d15d452bcec/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491", size = 160670, upload-time = "2025-08-09T07:56:17.314Z" }, + { url = "https://files.pythonhosted.org/packages/31/e7/883ee5676a2ef217a40ce0bffcc3d0dfbf9e64cbcfbdf822c52981c3304b/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93", size = 158501, upload-time = "2025-08-09T07:56:18.641Z" }, + { url = "https://files.pythonhosted.org/packages/c1/35/6525b21aa0db614cf8b5792d232021dca3df7f90a1944db934efa5d20bb1/charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f", size = 153173, upload-time = "2025-08-09T07:56:20.289Z" }, + { url = "https://files.pythonhosted.org/packages/50/ee/f4704bad8201de513fdc8aac1cabc87e38c5818c93857140e06e772b5892/charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37", size = 99822, upload-time = "2025-08-09T07:56:21.551Z" }, + { url = "https://files.pythonhosted.org/packages/39/f5/3b3836ca6064d0992c58c7561c6b6eee1b3892e9665d650c803bd5614522/charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc", size = 107543, upload-time = "2025-08-09T07:56:23.115Z" }, + { url = "https://files.pythonhosted.org/packages/65/ca/2135ac97709b400c7654b4b764daf5c5567c2da45a30cdd20f9eefe2d658/charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe", size = 205326, upload-time = "2025-08-09T07:56:24.721Z" }, + { url = "https://files.pythonhosted.org/packages/71/11/98a04c3c97dd34e49c7d247083af03645ca3730809a5509443f3c37f7c99/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8", size = 146008, upload-time = "2025-08-09T07:56:26.004Z" }, + { url = "https://files.pythonhosted.org/packages/60/f5/4659a4cb3c4ec146bec80c32d8bb16033752574c20b1252ee842a95d1a1e/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9", size = 159196, upload-time = "2025-08-09T07:56:27.25Z" }, + { url = "https://files.pythonhosted.org/packages/86/9e/f552f7a00611f168b9a5865a1414179b2c6de8235a4fa40189f6f79a1753/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31", size = 156819, upload-time = "2025-08-09T07:56:28.515Z" }, + { url = "https://files.pythonhosted.org/packages/7e/95/42aa2156235cbc8fa61208aded06ef46111c4d3f0de233107b3f38631803/charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f", size = 151350, upload-time = "2025-08-09T07:56:29.716Z" }, + { url = "https://files.pythonhosted.org/packages/c2/a9/3865b02c56f300a6f94fc631ef54f0a8a29da74fb45a773dfd3dcd380af7/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927", size = 148644, upload-time = "2025-08-09T07:56:30.984Z" }, + { url = "https://files.pythonhosted.org/packages/77/d9/cbcf1a2a5c7d7856f11e7ac2d782aec12bdfea60d104e60e0aa1c97849dc/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9", size = 160468, upload-time = "2025-08-09T07:56:32.252Z" }, + { url = "https://files.pythonhosted.org/packages/f6/42/6f45efee8697b89fda4d50580f292b8f7f9306cb2971d4b53f8914e4d890/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5", size = 158187, upload-time = "2025-08-09T07:56:33.481Z" }, + { url = "https://files.pythonhosted.org/packages/70/99/f1c3bdcfaa9c45b3ce96f70b14f070411366fa19549c1d4832c935d8e2c3/charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc", size = 152699, upload-time = "2025-08-09T07:56:34.739Z" }, + { url = "https://files.pythonhosted.org/packages/a3/ad/b0081f2f99a4b194bcbb1934ef3b12aa4d9702ced80a37026b7607c72e58/charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce", size = 99580, upload-time = "2025-08-09T07:56:35.981Z" }, + { url = "https://files.pythonhosted.org/packages/9a/8f/ae790790c7b64f925e5c953b924aaa42a243fb778fed9e41f147b2a5715a/charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef", size = 107366, upload-time = "2025-08-09T07:56:37.339Z" }, + { url = "https://files.pythonhosted.org/packages/8e/91/b5a06ad970ddc7a0e513112d40113e834638f4ca1120eb727a249fb2715e/charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15", size = 204342, upload-time = "2025-08-09T07:56:38.687Z" }, + { url = "https://files.pythonhosted.org/packages/ce/ec/1edc30a377f0a02689342f214455c3f6c2fbedd896a1d2f856c002fc3062/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db", size = 145995, upload-time = "2025-08-09T07:56:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/17/e5/5e67ab85e6d22b04641acb5399c8684f4d37caf7558a53859f0283a650e9/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d", size = 158640, upload-time = "2025-08-09T07:56:41.311Z" }, + { url = "https://files.pythonhosted.org/packages/f1/e5/38421987f6c697ee3722981289d554957c4be652f963d71c5e46a262e135/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096", size = 156636, upload-time = "2025-08-09T07:56:43.195Z" }, + { url = "https://files.pythonhosted.org/packages/a0/e4/5a075de8daa3ec0745a9a3b54467e0c2967daaaf2cec04c845f73493e9a1/charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa", size = 150939, upload-time = "2025-08-09T07:56:44.819Z" }, + { url = "https://files.pythonhosted.org/packages/02/f7/3611b32318b30974131db62b4043f335861d4d9b49adc6d57c1149cc49d4/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049", size = 148580, upload-time = "2025-08-09T07:56:46.684Z" }, + { url = "https://files.pythonhosted.org/packages/7e/61/19b36f4bd67f2793ab6a99b979b4e4f3d8fc754cbdffb805335df4337126/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0", size = 159870, upload-time = "2025-08-09T07:56:47.941Z" }, + { url = "https://files.pythonhosted.org/packages/06/57/84722eefdd338c04cf3030ada66889298eaedf3e7a30a624201e0cbe424a/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92", size = 157797, upload-time = "2025-08-09T07:56:49.756Z" }, + { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, + { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, + { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, + { url = "https://files.pythonhosted.org/packages/22/82/63a45bfc36f73efe46731a3a71cb84e2112f7e0b049507025ce477f0f052/charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c", size = 198805, upload-time = "2025-08-09T07:56:56.496Z" }, + { url = "https://files.pythonhosted.org/packages/0c/52/8b0c6c3e53f7e546a5e49b9edb876f379725914e1130297f3b423c7b71c5/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b", size = 142862, upload-time = "2025-08-09T07:56:57.751Z" }, + { url = "https://files.pythonhosted.org/packages/59/c0/a74f3bd167d311365e7973990243f32c35e7a94e45103125275b9e6c479f/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4", size = 155104, upload-time = "2025-08-09T07:56:58.984Z" }, + { url = "https://files.pythonhosted.org/packages/1a/79/ae516e678d6e32df2e7e740a7be51dc80b700e2697cb70054a0f1ac2c955/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b", size = 152598, upload-time = "2025-08-09T07:57:00.201Z" }, + { url = "https://files.pythonhosted.org/packages/00/bd/ef9c88464b126fa176f4ef4a317ad9b6f4d30b2cffbc43386062367c3e2c/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9", size = 147391, upload-time = "2025-08-09T07:57:01.441Z" }, + { url = "https://files.pythonhosted.org/packages/7a/03/cbb6fac9d3e57f7e07ce062712ee80d80a5ab46614684078461917426279/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb", size = 145037, upload-time = "2025-08-09T07:57:02.638Z" }, + { url = "https://files.pythonhosted.org/packages/64/d1/f9d141c893ef5d4243bc75c130e95af8fd4bc355beff06e9b1e941daad6e/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a", size = 156425, upload-time = "2025-08-09T07:57:03.898Z" }, + { url = "https://files.pythonhosted.org/packages/c5/35/9c99739250742375167bc1b1319cd1cec2bf67438a70d84b2e1ec4c9daa3/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942", size = 153734, upload-time = "2025-08-09T07:57:05.549Z" }, + { url = "https://files.pythonhosted.org/packages/50/10/c117806094d2c956ba88958dab680574019abc0c02bcf57b32287afca544/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b", size = 148551, upload-time = "2025-08-09T07:57:06.823Z" }, + { url = "https://files.pythonhosted.org/packages/61/c5/dc3ba772489c453621ffc27e8978a98fe7e41a93e787e5e5bde797f1dddb/charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557", size = 98459, upload-time = "2025-08-09T07:57:08.031Z" }, + { url = "https://files.pythonhosted.org/packages/05/35/bb59b1cd012d7196fc81c2f5879113971efc226a63812c9cf7f89fe97c40/charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40", size = 105887, upload-time = "2025-08-09T07:57:09.401Z" }, + { url = "https://files.pythonhosted.org/packages/c2/ca/9a0983dd5c8e9733565cf3db4df2b0a2e9a82659fd8aa2a868ac6e4a991f/charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", size = 207520, upload-time = "2025-08-09T07:57:11.026Z" }, + { url = "https://files.pythonhosted.org/packages/39/c6/99271dc37243a4f925b09090493fb96c9333d7992c6187f5cfe5312008d2/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", size = 147307, upload-time = "2025-08-09T07:57:12.4Z" }, + { url = "https://files.pythonhosted.org/packages/e4/69/132eab043356bba06eb333cc2cc60c6340857d0a2e4ca6dc2b51312886b3/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", size = 160448, upload-time = "2025-08-09T07:57:13.712Z" }, + { url = "https://files.pythonhosted.org/packages/04/9a/914d294daa4809c57667b77470533e65def9c0be1ef8b4c1183a99170e9d/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7", size = 157758, upload-time = "2025-08-09T07:57:14.979Z" }, + { url = "https://files.pythonhosted.org/packages/b0/a8/6f5bcf1bcf63cb45625f7c5cadca026121ff8a6c8a3256d8d8cd59302663/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7", size = 152487, upload-time = "2025-08-09T07:57:16.332Z" }, + { url = "https://files.pythonhosted.org/packages/c4/72/d3d0e9592f4e504f9dea08b8db270821c909558c353dc3b457ed2509f2fb/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19", size = 150054, upload-time = "2025-08-09T07:57:17.576Z" }, + { url = "https://files.pythonhosted.org/packages/20/30/5f64fe3981677fe63fa987b80e6c01042eb5ff653ff7cec1b7bd9268e54e/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312", size = 161703, upload-time = "2025-08-09T07:57:20.012Z" }, + { url = "https://files.pythonhosted.org/packages/e1/ef/dd08b2cac9284fd59e70f7d97382c33a3d0a926e45b15fc21b3308324ffd/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc", size = 159096, upload-time = "2025-08-09T07:57:21.329Z" }, + { url = "https://files.pythonhosted.org/packages/45/8c/dcef87cfc2b3f002a6478f38906f9040302c68aebe21468090e39cde1445/charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34", size = 153852, upload-time = "2025-08-09T07:57:22.608Z" }, + { url = "https://files.pythonhosted.org/packages/63/86/9cbd533bd37883d467fcd1bd491b3547a3532d0fbb46de2b99feeebf185e/charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432", size = 99840, upload-time = "2025-08-09T07:57:23.883Z" }, + { url = "https://files.pythonhosted.org/packages/ce/d6/7e805c8e5c46ff9729c49950acc4ee0aeb55efb8b3a56687658ad10c3216/charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca", size = 107438, upload-time = "2025-08-09T07:57:25.287Z" }, + { url = "https://files.pythonhosted.org/packages/8a/1f/f041989e93b001bc4e44bb1669ccdcf54d3f00e628229a85b08d330615c5/charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a", size = 53175, upload-time = "2025-08-09T07:57:26.864Z" }, +] + +[[package]] +name = "click" +version = "8.1.8" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.9.*'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/b9/2e/0090cbf739cee7d23781ad4b89a9894a41538e4fcf4c31dcdd705b78eb8b/click-8.1.8.tar.gz", hash = "sha256:ed53c9d8990d83c2a27deae68e4ee337473f6330c040a31d4225c9574d16096a", size = 226593, upload-time = "2024-12-21T18:38:44.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/d4/7ebdbd03970677812aac39c869717059dbb71a4cfc033ca6e5221787892c/click-8.1.8-py3-none-any.whl", hash = "sha256:63c132bbbed01578a06712a2d1f497bb62d9c1c0d329b7903a866228027263b2", size = 98188, upload-time = "2024-12-21T18:38:41.666Z" }, +] + +[[package]] +name = "click" +version = "8.2.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/60/6c/8ca2efa64cf75a977a0d7fac081354553ebe483345c734fb6b6515d96bbc/click-8.2.1.tar.gz", hash = "sha256:27c491cc05d968d271d5a1db13e3b5a184636d9d930f148c50b038f0d0646202", size = 286342, upload-time = "2025-05-20T23:19:49.832Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/85/32/10bb5764d90a8eee674e9dc6f4db6a0ab47c8c4d0d83c27f7c39ac415a4d/click-8.2.1-py3-none-any.whl", hash = "sha256:61a3265b914e850b85317d0b3109c7f8cd35a670f963866005d6ef1d5175a12b", size = 102215, upload-time = "2025-05-20T23:19:47.796Z" }, +] + +[[package]] +name = "colorama" +version = "0.4.6" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, +] + +[[package]] +name = "coverage" +version = "7.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/f7/08/7e37f82e4d1aead42a7443ff06a1e406aabf7302c4f00a546e4b320b994c/coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", size = 798791, upload-time = "2024-08-04T19:45:30.9Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7e/61/eb7ce5ed62bacf21beca4937a90fe32545c91a3c8a42a30c6616d48fc70d/coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", size = 206690, upload-time = "2024-08-04T19:43:07.695Z" }, + { url = "https://files.pythonhosted.org/packages/7d/73/041928e434442bd3afde5584bdc3f932fb4562b1597629f537387cec6f3d/coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", size = 207127, upload-time = "2024-08-04T19:43:10.15Z" }, + { url = "https://files.pythonhosted.org/packages/c7/c8/6ca52b5147828e45ad0242388477fdb90df2c6cbb9a441701a12b3c71bc8/coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", size = 235654, upload-time = "2024-08-04T19:43:12.405Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/9ac2b62557f4340270942011d6efeab9833648380109e897d48ab7c1035d/coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc", size = 233598, upload-time = "2024-08-04T19:43:14.078Z" }, + { url = "https://files.pythonhosted.org/packages/53/23/9e2c114d0178abc42b6d8d5281f651a8e6519abfa0ef460a00a91f80879d/coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", size = 234732, upload-time = "2024-08-04T19:43:16.632Z" }, + { url = "https://files.pythonhosted.org/packages/0f/7e/a0230756fb133343a52716e8b855045f13342b70e48e8ad41d8a0d60ab98/coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", size = 233816, upload-time = "2024-08-04T19:43:19.049Z" }, + { url = "https://files.pythonhosted.org/packages/28/7c/3753c8b40d232b1e5eeaed798c875537cf3cb183fb5041017c1fdb7ec14e/coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", size = 232325, upload-time = "2024-08-04T19:43:21.246Z" }, + { url = "https://files.pythonhosted.org/packages/57/e3/818a2b2af5b7573b4b82cf3e9f137ab158c90ea750a8f053716a32f20f06/coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", size = 233418, upload-time = "2024-08-04T19:43:22.945Z" }, + { url = "https://files.pythonhosted.org/packages/c8/fb/4532b0b0cefb3f06d201648715e03b0feb822907edab3935112b61b885e2/coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", size = 209343, upload-time = "2024-08-04T19:43:25.121Z" }, + { url = "https://files.pythonhosted.org/packages/5a/25/af337cc7421eca1c187cc9c315f0a755d48e755d2853715bfe8c418a45fa/coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", size = 210136, upload-time = "2024-08-04T19:43:26.851Z" }, + { url = "https://files.pythonhosted.org/packages/ad/5f/67af7d60d7e8ce61a4e2ddcd1bd5fb787180c8d0ae0fbd073f903b3dd95d/coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", size = 206796, upload-time = "2024-08-04T19:43:29.115Z" }, + { url = "https://files.pythonhosted.org/packages/e1/0e/e52332389e057daa2e03be1fbfef25bb4d626b37d12ed42ae6281d0a274c/coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", size = 207244, upload-time = "2024-08-04T19:43:31.285Z" }, + { url = "https://files.pythonhosted.org/packages/aa/cd/766b45fb6e090f20f8927d9c7cb34237d41c73a939358bc881883fd3a40d/coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", size = 239279, upload-time = "2024-08-04T19:43:33.581Z" }, + { url = "https://files.pythonhosted.org/packages/70/6c/a9ccd6fe50ddaf13442a1e2dd519ca805cbe0f1fcd377fba6d8339b98ccb/coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", size = 236859, upload-time = "2024-08-04T19:43:35.301Z" }, + { url = "https://files.pythonhosted.org/packages/14/6f/8351b465febb4dbc1ca9929505202db909c5a635c6fdf33e089bbc3d7d85/coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", size = 238549, upload-time = "2024-08-04T19:43:37.578Z" }, + { url = "https://files.pythonhosted.org/packages/68/3c/289b81fa18ad72138e6d78c4c11a82b5378a312c0e467e2f6b495c260907/coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", size = 237477, upload-time = "2024-08-04T19:43:39.92Z" }, + { url = "https://files.pythonhosted.org/packages/ed/1c/aa1efa6459d822bd72c4abc0b9418cf268de3f60eeccd65dc4988553bd8d/coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", size = 236134, upload-time = "2024-08-04T19:43:41.453Z" }, + { url = "https://files.pythonhosted.org/packages/fb/c8/521c698f2d2796565fe9c789c2ee1ccdae610b3aa20b9b2ef980cc253640/coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", size = 236910, upload-time = "2024-08-04T19:43:43.037Z" }, + { url = "https://files.pythonhosted.org/packages/7d/30/033e663399ff17dca90d793ee8a2ea2890e7fdf085da58d82468b4220bf7/coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", size = 209348, upload-time = "2024-08-04T19:43:44.787Z" }, + { url = "https://files.pythonhosted.org/packages/20/05/0d1ccbb52727ccdadaa3ff37e4d2dc1cd4d47f0c3df9eb58d9ec8508ca88/coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", size = 210230, upload-time = "2024-08-04T19:43:46.707Z" }, + { url = "https://files.pythonhosted.org/packages/7e/d4/300fc921dff243cd518c7db3a4c614b7e4b2431b0d1145c1e274fd99bd70/coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", size = 206983, upload-time = "2024-08-04T19:43:49.082Z" }, + { url = "https://files.pythonhosted.org/packages/e1/ab/6bf00de5327ecb8db205f9ae596885417a31535eeda6e7b99463108782e1/coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", size = 207221, upload-time = "2024-08-04T19:43:52.15Z" }, + { url = "https://files.pythonhosted.org/packages/92/8f/2ead05e735022d1a7f3a0a683ac7f737de14850395a826192f0288703472/coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", size = 240342, upload-time = "2024-08-04T19:43:53.746Z" }, + { url = "https://files.pythonhosted.org/packages/0f/ef/94043e478201ffa85b8ae2d2c79b4081e5a1b73438aafafccf3e9bafb6b5/coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", size = 237371, upload-time = "2024-08-04T19:43:55.993Z" }, + { url = "https://files.pythonhosted.org/packages/1f/0f/c890339dd605f3ebc269543247bdd43b703cce6825b5ed42ff5f2d6122c7/coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", size = 239455, upload-time = "2024-08-04T19:43:57.618Z" }, + { url = "https://files.pythonhosted.org/packages/d1/04/7fd7b39ec7372a04efb0f70c70e35857a99b6a9188b5205efb4c77d6a57a/coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", size = 238924, upload-time = "2024-08-04T19:44:00.012Z" }, + { url = "https://files.pythonhosted.org/packages/ed/bf/73ce346a9d32a09cf369f14d2a06651329c984e106f5992c89579d25b27e/coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", size = 237252, upload-time = "2024-08-04T19:44:01.713Z" }, + { url = "https://files.pythonhosted.org/packages/86/74/1dc7a20969725e917b1e07fe71a955eb34bc606b938316bcc799f228374b/coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", size = 238897, upload-time = "2024-08-04T19:44:03.898Z" }, + { url = "https://files.pythonhosted.org/packages/b6/e9/d9cc3deceb361c491b81005c668578b0dfa51eed02cd081620e9a62f24ec/coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", size = 209606, upload-time = "2024-08-04T19:44:05.532Z" }, + { url = "https://files.pythonhosted.org/packages/47/c8/5a2e41922ea6740f77d555c4d47544acd7dc3f251fe14199c09c0f5958d3/coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", size = 210373, upload-time = "2024-08-04T19:44:07.079Z" }, + { url = "https://files.pythonhosted.org/packages/8c/f9/9aa4dfb751cb01c949c990d136a0f92027fbcc5781c6e921df1cb1563f20/coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", size = 207007, upload-time = "2024-08-04T19:44:09.453Z" }, + { url = "https://files.pythonhosted.org/packages/b9/67/e1413d5a8591622a46dd04ff80873b04c849268831ed5c304c16433e7e30/coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", size = 207269, upload-time = "2024-08-04T19:44:11.045Z" }, + { url = "https://files.pythonhosted.org/packages/14/5b/9dec847b305e44a5634d0fb8498d135ab1d88330482b74065fcec0622224/coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", size = 239886, upload-time = "2024-08-04T19:44:12.83Z" }, + { url = "https://files.pythonhosted.org/packages/7b/b7/35760a67c168e29f454928f51f970342d23cf75a2bb0323e0f07334c85f3/coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", size = 237037, upload-time = "2024-08-04T19:44:15.393Z" }, + { url = "https://files.pythonhosted.org/packages/f7/95/d2fd31f1d638df806cae59d7daea5abf2b15b5234016a5ebb502c2f3f7ee/coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", size = 239038, upload-time = "2024-08-04T19:44:17.466Z" }, + { url = "https://files.pythonhosted.org/packages/6e/bd/110689ff5752b67924efd5e2aedf5190cbbe245fc81b8dec1abaffba619d/coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", size = 238690, upload-time = "2024-08-04T19:44:19.336Z" }, + { url = "https://files.pythonhosted.org/packages/d3/a8/08d7b38e6ff8df52331c83130d0ab92d9c9a8b5462f9e99c9f051a4ae206/coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", size = 236765, upload-time = "2024-08-04T19:44:20.994Z" }, + { url = "https://files.pythonhosted.org/packages/d6/6a/9cf96839d3147d55ae713eb2d877f4d777e7dc5ba2bce227167d0118dfe8/coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", size = 238611, upload-time = "2024-08-04T19:44:22.616Z" }, + { url = "https://files.pythonhosted.org/packages/74/e4/7ff20d6a0b59eeaab40b3140a71e38cf52547ba21dbcf1d79c5a32bba61b/coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", size = 209671, upload-time = "2024-08-04T19:44:24.418Z" }, + { url = "https://files.pythonhosted.org/packages/35/59/1812f08a85b57c9fdb6d0b383d779e47b6f643bc278ed682859512517e83/coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", size = 210368, upload-time = "2024-08-04T19:44:26.276Z" }, + { url = "https://files.pythonhosted.org/packages/9c/15/08913be1c59d7562a3e39fce20661a98c0a3f59d5754312899acc6cb8a2d/coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", size = 207758, upload-time = "2024-08-04T19:44:29.028Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ae/b5d58dff26cade02ada6ca612a76447acd69dccdbb3a478e9e088eb3d4b9/coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", size = 208035, upload-time = "2024-08-04T19:44:30.673Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d7/62095e355ec0613b08dfb19206ce3033a0eedb6f4a67af5ed267a8800642/coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", size = 250839, upload-time = "2024-08-04T19:44:32.412Z" }, + { url = "https://files.pythonhosted.org/packages/7c/1e/c2967cb7991b112ba3766df0d9c21de46b476d103e32bb401b1b2adf3380/coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", size = 246569, upload-time = "2024-08-04T19:44:34.547Z" }, + { url = "https://files.pythonhosted.org/packages/8b/61/a7a6a55dd266007ed3b1df7a3386a0d760d014542d72f7c2c6938483b7bd/coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", size = 248927, upload-time = "2024-08-04T19:44:36.313Z" }, + { url = "https://files.pythonhosted.org/packages/c8/fa/13a6f56d72b429f56ef612eb3bc5ce1b75b7ee12864b3bd12526ab794847/coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", size = 248401, upload-time = "2024-08-04T19:44:38.155Z" }, + { url = "https://files.pythonhosted.org/packages/75/06/0429c652aa0fb761fc60e8c6b291338c9173c6aa0f4e40e1902345b42830/coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", size = 246301, upload-time = "2024-08-04T19:44:39.883Z" }, + { url = "https://files.pythonhosted.org/packages/52/76/1766bb8b803a88f93c3a2d07e30ffa359467810e5cbc68e375ebe6906efb/coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", size = 247598, upload-time = "2024-08-04T19:44:41.59Z" }, + { url = "https://files.pythonhosted.org/packages/66/8b/f54f8db2ae17188be9566e8166ac6df105c1c611e25da755738025708d54/coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", size = 210307, upload-time = "2024-08-04T19:44:43.301Z" }, + { url = "https://files.pythonhosted.org/packages/9f/b0/e0dca6da9170aefc07515cce067b97178cefafb512d00a87a1c717d2efd5/coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", size = 211453, upload-time = "2024-08-04T19:44:45.677Z" }, + { url = "https://files.pythonhosted.org/packages/81/d0/d9e3d554e38beea5a2e22178ddb16587dbcbe9a1ef3211f55733924bf7fa/coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", size = 206674, upload-time = "2024-08-04T19:44:47.694Z" }, + { url = "https://files.pythonhosted.org/packages/38/ea/cab2dc248d9f45b2b7f9f1f596a4d75a435cb364437c61b51d2eb33ceb0e/coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", size = 207101, upload-time = "2024-08-04T19:44:49.32Z" }, + { url = "https://files.pythonhosted.org/packages/ca/6f/f82f9a500c7c5722368978a5390c418d2a4d083ef955309a8748ecaa8920/coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", size = 236554, upload-time = "2024-08-04T19:44:51.631Z" }, + { url = "https://files.pythonhosted.org/packages/a6/94/d3055aa33d4e7e733d8fa309d9adf147b4b06a82c1346366fc15a2b1d5fa/coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", size = 234440, upload-time = "2024-08-04T19:44:53.464Z" }, + { url = "https://files.pythonhosted.org/packages/e4/6e/885bcd787d9dd674de4a7d8ec83faf729534c63d05d51d45d4fa168f7102/coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", size = 235889, upload-time = "2024-08-04T19:44:55.165Z" }, + { url = "https://files.pythonhosted.org/packages/f4/63/df50120a7744492710854860783d6819ff23e482dee15462c9a833cc428a/coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", size = 235142, upload-time = "2024-08-04T19:44:57.269Z" }, + { url = "https://files.pythonhosted.org/packages/3a/5d/9d0acfcded2b3e9ce1c7923ca52ccc00c78a74e112fc2aee661125b7843b/coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", size = 233805, upload-time = "2024-08-04T19:44:59.033Z" }, + { url = "https://files.pythonhosted.org/packages/c4/56/50abf070cb3cd9b1dd32f2c88f083aab561ecbffbcd783275cb51c17f11d/coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", size = 234655, upload-time = "2024-08-04T19:45:01.398Z" }, + { url = "https://files.pythonhosted.org/packages/25/ee/b4c246048b8485f85a2426ef4abab88e48c6e80c74e964bea5cd4cd4b115/coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", size = 209296, upload-time = "2024-08-04T19:45:03.819Z" }, + { url = "https://files.pythonhosted.org/packages/5c/1c/96cf86b70b69ea2b12924cdf7cabb8ad10e6130eab8d767a1099fbd2a44f/coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", size = 210137, upload-time = "2024-08-04T19:45:06.25Z" }, + { url = "https://files.pythonhosted.org/packages/19/d3/d54c5aa83268779d54c86deb39c1c4566e5d45c155369ca152765f8db413/coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", size = 206688, upload-time = "2024-08-04T19:45:08.358Z" }, + { url = "https://files.pythonhosted.org/packages/a5/fe/137d5dca72e4a258b1bc17bb04f2e0196898fe495843402ce826a7419fe3/coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", size = 207120, upload-time = "2024-08-04T19:45:11.526Z" }, + { url = "https://files.pythonhosted.org/packages/78/5b/a0a796983f3201ff5485323b225d7c8b74ce30c11f456017e23d8e8d1945/coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", size = 235249, upload-time = "2024-08-04T19:45:13.202Z" }, + { url = "https://files.pythonhosted.org/packages/4e/e1/76089d6a5ef9d68f018f65411fcdaaeb0141b504587b901d74e8587606ad/coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", size = 233237, upload-time = "2024-08-04T19:45:14.961Z" }, + { url = "https://files.pythonhosted.org/packages/9a/6f/eef79b779a540326fee9520e5542a8b428cc3bfa8b7c8f1022c1ee4fc66c/coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", size = 234311, upload-time = "2024-08-04T19:45:16.924Z" }, + { url = "https://files.pythonhosted.org/packages/75/e1/656d65fb126c29a494ef964005702b012f3498db1a30dd562958e85a4049/coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", size = 233453, upload-time = "2024-08-04T19:45:18.672Z" }, + { url = "https://files.pythonhosted.org/packages/68/6a/45f108f137941a4a1238c85f28fd9d048cc46b5466d6b8dda3aba1bb9d4f/coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", size = 231958, upload-time = "2024-08-04T19:45:20.63Z" }, + { url = "https://files.pythonhosted.org/packages/9b/e7/47b809099168b8b8c72ae311efc3e88c8d8a1162b3ba4b8da3cfcdb85743/coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", size = 232938, upload-time = "2024-08-04T19:45:23.062Z" }, + { url = "https://files.pythonhosted.org/packages/52/80/052222ba7058071f905435bad0ba392cc12006380731c37afaf3fe749b88/coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", size = 209352, upload-time = "2024-08-04T19:45:25.042Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d8/1b92e0b3adcf384e98770a00ca095da1b5f7b483e6563ae4eb5e935d24a1/coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", size = 210153, upload-time = "2024-08-04T19:45:27.079Z" }, + { url = "https://files.pythonhosted.org/packages/a5/2b/0354ed096bca64dc8e32a7cbcae28b34cb5ad0b1fe2125d6d99583313ac0/coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", size = 198926, upload-time = "2024-08-04T19:45:28.875Z" }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version < '3.9'" }, +] + +[[package]] +name = "coverage" +version = "7.10.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/14/70/025b179c993f019105b79575ac6edb5e084fb0f0e63f15cdebef4e454fb5/coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90", size = 823736, upload-time = "2025-08-29T15:35:16.668Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/1d/2e64b43d978b5bd184e0756a41415597dfef30fcbd90b747474bd749d45f/coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356", size = 217025, upload-time = "2025-08-29T15:32:57.169Z" }, + { url = "https://files.pythonhosted.org/packages/23/62/b1e0f513417c02cc10ef735c3ee5186df55f190f70498b3702d516aad06f/coverage-7.10.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e41be6f0f19da64af13403e52f2dec38bbc2937af54df8ecef10850ff8d35301", size = 217419, upload-time = "2025-08-29T15:32:59.908Z" }, + { url = "https://files.pythonhosted.org/packages/e7/16/b800640b7a43e7c538429e4d7223e0a94fd72453a1a048f70bf766f12e96/coverage-7.10.6-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c61fc91ab80b23f5fddbee342d19662f3d3328173229caded831aa0bd7595460", size = 244180, upload-time = "2025-08-29T15:33:01.608Z" }, + { url = "https://files.pythonhosted.org/packages/fb/6f/5e03631c3305cad187eaf76af0b559fff88af9a0b0c180d006fb02413d7a/coverage-7.10.6-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10356fdd33a7cc06e8051413140bbdc6f972137508a3572e3f59f805cd2832fd", size = 245992, upload-time = "2025-08-29T15:33:03.239Z" }, + { url = "https://files.pythonhosted.org/packages/eb/a1/f30ea0fb400b080730125b490771ec62b3375789f90af0bb68bfb8a921d7/coverage-7.10.6-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:80b1695cf7c5ebe7b44bf2521221b9bb8cdf69b1f24231149a7e3eb1ae5fa2fb", size = 247851, upload-time = "2025-08-29T15:33:04.603Z" }, + { url = "https://files.pythonhosted.org/packages/02/8e/cfa8fee8e8ef9a6bb76c7bef039f3302f44e615d2194161a21d3d83ac2e9/coverage-7.10.6-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:2e4c33e6378b9d52d3454bd08847a8651f4ed23ddbb4a0520227bd346382bbc6", size = 245891, upload-time = "2025-08-29T15:33:06.176Z" }, + { url = "https://files.pythonhosted.org/packages/93/a9/51be09b75c55c4f6c16d8d73a6a1d46ad764acca0eab48fa2ffaef5958fe/coverage-7.10.6-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:c8a3ec16e34ef980a46f60dc6ad86ec60f763c3f2fa0db6d261e6e754f72e945", size = 243909, upload-time = "2025-08-29T15:33:07.74Z" }, + { url = "https://files.pythonhosted.org/packages/e9/a6/ba188b376529ce36483b2d585ca7bdac64aacbe5aa10da5978029a9c94db/coverage-7.10.6-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:7d79dabc0a56f5af990cc6da9ad1e40766e82773c075f09cc571e2076fef882e", size = 244786, upload-time = "2025-08-29T15:33:08.965Z" }, + { url = "https://files.pythonhosted.org/packages/d0/4c/37ed872374a21813e0d3215256180c9a382c3f5ced6f2e5da0102fc2fd3e/coverage-7.10.6-cp310-cp310-win32.whl", hash = "sha256:86b9b59f2b16e981906e9d6383eb6446d5b46c278460ae2c36487667717eccf1", size = 219521, upload-time = "2025-08-29T15:33:10.599Z" }, + { url = "https://files.pythonhosted.org/packages/8e/36/9311352fdc551dec5b973b61f4e453227ce482985a9368305880af4f85dd/coverage-7.10.6-cp310-cp310-win_amd64.whl", hash = "sha256:e132b9152749bd33534e5bd8565c7576f135f157b4029b975e15ee184325f528", size = 220417, upload-time = "2025-08-29T15:33:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/d4/16/2bea27e212c4980753d6d563a0803c150edeaaddb0771a50d2afc410a261/coverage-7.10.6-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c706db3cabb7ceef779de68270150665e710b46d56372455cd741184f3868d8f", size = 217129, upload-time = "2025-08-29T15:33:13.575Z" }, + { url = "https://files.pythonhosted.org/packages/2a/51/e7159e068831ab37e31aac0969d47b8c5ee25b7d307b51e310ec34869315/coverage-7.10.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8e0c38dc289e0508ef68ec95834cb5d2e96fdbe792eaccaa1bccac3966bbadcc", size = 217532, upload-time = "2025-08-29T15:33:14.872Z" }, + { url = "https://files.pythonhosted.org/packages/e7/c0/246ccbea53d6099325d25cd208df94ea435cd55f0db38099dd721efc7a1f/coverage-7.10.6-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:752a3005a1ded28f2f3a6e8787e24f28d6abe176ca64677bcd8d53d6fe2ec08a", size = 247931, upload-time = "2025-08-29T15:33:16.142Z" }, + { url = "https://files.pythonhosted.org/packages/7d/fb/7435ef8ab9b2594a6e3f58505cc30e98ae8b33265d844007737946c59389/coverage-7.10.6-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:689920ecfd60f992cafca4f5477d55720466ad2c7fa29bb56ac8d44a1ac2b47a", size = 249864, upload-time = "2025-08-29T15:33:17.434Z" }, + { url = "https://files.pythonhosted.org/packages/51/f8/d9d64e8da7bcddb094d511154824038833c81e3a039020a9d6539bf303e9/coverage-7.10.6-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ec98435796d2624d6905820a42f82149ee9fc4f2d45c2c5bc5a44481cc50db62", size = 251969, upload-time = "2025-08-29T15:33:18.822Z" }, + { url = "https://files.pythonhosted.org/packages/43/28/c43ba0ef19f446d6463c751315140d8f2a521e04c3e79e5c5fe211bfa430/coverage-7.10.6-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b37201ce4a458c7a758ecc4efa92fa8ed783c66e0fa3c42ae19fc454a0792153", size = 249659, upload-time = "2025-08-29T15:33:20.407Z" }, + { url = "https://files.pythonhosted.org/packages/79/3e/53635bd0b72beaacf265784508a0b386defc9ab7fad99ff95f79ce9db555/coverage-7.10.6-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:2904271c80898663c810a6b067920a61dd8d38341244a3605bd31ab55250dad5", size = 247714, upload-time = "2025-08-29T15:33:21.751Z" }, + { url = "https://files.pythonhosted.org/packages/4c/55/0964aa87126624e8c159e32b0bc4e84edef78c89a1a4b924d28dd8265625/coverage-7.10.6-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5aea98383463d6e1fa4e95416d8de66f2d0cb588774ee20ae1b28df826bcb619", size = 248351, upload-time = "2025-08-29T15:33:23.105Z" }, + { url = "https://files.pythonhosted.org/packages/eb/ab/6cfa9dc518c6c8e14a691c54e53a9433ba67336c760607e299bfcf520cb1/coverage-7.10.6-cp311-cp311-win32.whl", hash = "sha256:e3fb1fa01d3598002777dd259c0c2e6d9d5e10e7222976fc8e03992f972a2cba", size = 219562, upload-time = "2025-08-29T15:33:24.717Z" }, + { url = "https://files.pythonhosted.org/packages/5b/18/99b25346690cbc55922e7cfef06d755d4abee803ef335baff0014268eff4/coverage-7.10.6-cp311-cp311-win_amd64.whl", hash = "sha256:f35ed9d945bece26553d5b4c8630453169672bea0050a564456eb88bdffd927e", size = 220453, upload-time = "2025-08-29T15:33:26.482Z" }, + { url = "https://files.pythonhosted.org/packages/d8/ed/81d86648a07ccb124a5cf1f1a7788712b8d7216b593562683cd5c9b0d2c1/coverage-7.10.6-cp311-cp311-win_arm64.whl", hash = "sha256:99e1a305c7765631d74b98bf7dbf54eeea931f975e80f115437d23848ee8c27c", size = 219127, upload-time = "2025-08-29T15:33:27.777Z" }, + { url = "https://files.pythonhosted.org/packages/26/06/263f3305c97ad78aab066d116b52250dd316e74fcc20c197b61e07eb391a/coverage-7.10.6-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:5b2dd6059938063a2c9fee1af729d4f2af28fd1a545e9b7652861f0d752ebcea", size = 217324, upload-time = "2025-08-29T15:33:29.06Z" }, + { url = "https://files.pythonhosted.org/packages/e9/60/1e1ded9a4fe80d843d7d53b3e395c1db3ff32d6c301e501f393b2e6c1c1f/coverage-7.10.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:388d80e56191bf846c485c14ae2bc8898aa3124d9d35903fef7d907780477634", size = 217560, upload-time = "2025-08-29T15:33:30.748Z" }, + { url = "https://files.pythonhosted.org/packages/b8/25/52136173c14e26dfed8b106ed725811bb53c30b896d04d28d74cb64318b3/coverage-7.10.6-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:90cb5b1a4670662719591aa92d0095bb41714970c0b065b02a2610172dbf0af6", size = 249053, upload-time = "2025-08-29T15:33:32.041Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1d/ae25a7dc58fcce8b172d42ffe5313fc267afe61c97fa872b80ee72d9515a/coverage-7.10.6-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:961834e2f2b863a0e14260a9a273aff07ff7818ab6e66d2addf5628590c628f9", size = 251802, upload-time = "2025-08-29T15:33:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/f5/7a/1f561d47743710fe996957ed7c124b421320f150f1d38523d8d9102d3e2a/coverage-7.10.6-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf9a19f5012dab774628491659646335b1928cfc931bf8d97b0d5918dd58033c", size = 252935, upload-time = "2025-08-29T15:33:34.909Z" }, + { url = "https://files.pythonhosted.org/packages/6c/ad/8b97cd5d28aecdfde792dcbf646bac141167a5cacae2cd775998b45fabb5/coverage-7.10.6-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:99c4283e2a0e147b9c9cc6bc9c96124de9419d6044837e9799763a0e29a7321a", size = 250855, upload-time = "2025-08-29T15:33:36.922Z" }, + { url = "https://files.pythonhosted.org/packages/33/6a/95c32b558d9a61858ff9d79580d3877df3eb5bc9eed0941b1f187c89e143/coverage-7.10.6-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:282b1b20f45df57cc508c1e033403f02283adfb67d4c9c35a90281d81e5c52c5", size = 248974, upload-time = "2025-08-29T15:33:38.175Z" }, + { url = "https://files.pythonhosted.org/packages/0d/9c/8ce95dee640a38e760d5b747c10913e7a06554704d60b41e73fdea6a1ffd/coverage-7.10.6-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8cdbe264f11afd69841bd8c0d83ca10b5b32853263ee62e6ac6a0ab63895f972", size = 250409, upload-time = "2025-08-29T15:33:39.447Z" }, + { url = "https://files.pythonhosted.org/packages/04/12/7a55b0bdde78a98e2eb2356771fd2dcddb96579e8342bb52aa5bc52e96f0/coverage-7.10.6-cp312-cp312-win32.whl", hash = "sha256:a517feaf3a0a3eca1ee985d8373135cfdedfbba3882a5eab4362bda7c7cf518d", size = 219724, upload-time = "2025-08-29T15:33:41.172Z" }, + { url = "https://files.pythonhosted.org/packages/36/4a/32b185b8b8e327802c9efce3d3108d2fe2d9d31f153a0f7ecfd59c773705/coverage-7.10.6-cp312-cp312-win_amd64.whl", hash = "sha256:856986eadf41f52b214176d894a7de05331117f6035a28ac0016c0f63d887629", size = 220536, upload-time = "2025-08-29T15:33:42.524Z" }, + { url = "https://files.pythonhosted.org/packages/08/3a/d5d8dc703e4998038c3099eaf77adddb00536a3cec08c8dcd556a36a3eb4/coverage-7.10.6-cp312-cp312-win_arm64.whl", hash = "sha256:acf36b8268785aad739443fa2780c16260ee3fa09d12b3a70f772ef100939d80", size = 219171, upload-time = "2025-08-29T15:33:43.974Z" }, + { url = "https://files.pythonhosted.org/packages/bd/e7/917e5953ea29a28c1057729c1d5af9084ab6d9c66217523fd0e10f14d8f6/coverage-7.10.6-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ffea0575345e9ee0144dfe5701aa17f3ba546f8c3bb48db62ae101afb740e7d6", size = 217351, upload-time = "2025-08-29T15:33:45.438Z" }, + { url = "https://files.pythonhosted.org/packages/eb/86/2e161b93a4f11d0ea93f9bebb6a53f113d5d6e416d7561ca41bb0a29996b/coverage-7.10.6-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:95d91d7317cde40a1c249d6b7382750b7e6d86fad9d8eaf4fa3f8f44cf171e80", size = 217600, upload-time = "2025-08-29T15:33:47.269Z" }, + { url = "https://files.pythonhosted.org/packages/0e/66/d03348fdd8df262b3a7fb4ee5727e6e4936e39e2f3a842e803196946f200/coverage-7.10.6-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3e23dd5408fe71a356b41baa82892772a4cefcf758f2ca3383d2aa39e1b7a003", size = 248600, upload-time = "2025-08-29T15:33:48.953Z" }, + { url = "https://files.pythonhosted.org/packages/73/dd/508420fb47d09d904d962f123221bc249f64b5e56aa93d5f5f7603be475f/coverage-7.10.6-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0f3f56e4cb573755e96a16501a98bf211f100463d70275759e73f3cbc00d4f27", size = 251206, upload-time = "2025-08-29T15:33:50.697Z" }, + { url = "https://files.pythonhosted.org/packages/e9/1f/9020135734184f439da85c70ea78194c2730e56c2d18aee6e8ff1719d50d/coverage-7.10.6-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:db4a1d897bbbe7339946ffa2fe60c10cc81c43fab8b062d3fcb84188688174a4", size = 252478, upload-time = "2025-08-29T15:33:52.303Z" }, + { url = "https://files.pythonhosted.org/packages/a4/a4/3d228f3942bb5a2051fde28c136eea23a761177dc4ff4ef54533164ce255/coverage-7.10.6-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d8fd7879082953c156d5b13c74aa6cca37f6a6f4747b39538504c3f9c63d043d", size = 250637, upload-time = "2025-08-29T15:33:53.67Z" }, + { url = "https://files.pythonhosted.org/packages/36/e3/293dce8cdb9a83de971637afc59b7190faad60603b40e32635cbd15fbf61/coverage-7.10.6-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:28395ca3f71cd103b8c116333fa9db867f3a3e1ad6a084aa3725ae002b6583bc", size = 248529, upload-time = "2025-08-29T15:33:55.022Z" }, + { url = "https://files.pythonhosted.org/packages/90/26/64eecfa214e80dd1d101e420cab2901827de0e49631d666543d0e53cf597/coverage-7.10.6-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:61c950fc33d29c91b9e18540e1aed7d9f6787cc870a3e4032493bbbe641d12fc", size = 250143, upload-time = "2025-08-29T15:33:56.386Z" }, + { url = "https://files.pythonhosted.org/packages/3e/70/bd80588338f65ea5b0d97e424b820fb4068b9cfb9597fbd91963086e004b/coverage-7.10.6-cp313-cp313-win32.whl", hash = "sha256:160c00a5e6b6bdf4e5984b0ef21fc860bc94416c41b7df4d63f536d17c38902e", size = 219770, upload-time = "2025-08-29T15:33:58.063Z" }, + { url = "https://files.pythonhosted.org/packages/a7/14/0b831122305abcc1060c008f6c97bbdc0a913ab47d65070a01dc50293c2b/coverage-7.10.6-cp313-cp313-win_amd64.whl", hash = "sha256:628055297f3e2aa181464c3808402887643405573eb3d9de060d81531fa79d32", size = 220566, upload-time = "2025-08-29T15:33:59.766Z" }, + { url = "https://files.pythonhosted.org/packages/83/c6/81a83778c1f83f1a4a168ed6673eeedc205afb562d8500175292ca64b94e/coverage-7.10.6-cp313-cp313-win_arm64.whl", hash = "sha256:df4ec1f8540b0bcbe26ca7dd0f541847cc8a108b35596f9f91f59f0c060bfdd2", size = 219195, upload-time = "2025-08-29T15:34:01.191Z" }, + { url = "https://files.pythonhosted.org/packages/d7/1c/ccccf4bf116f9517275fa85047495515add43e41dfe8e0bef6e333c6b344/coverage-7.10.6-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:c9a8b7a34a4de3ed987f636f71881cd3b8339f61118b1aa311fbda12741bff0b", size = 218059, upload-time = "2025-08-29T15:34:02.91Z" }, + { url = "https://files.pythonhosted.org/packages/92/97/8a3ceff833d27c7492af4f39d5da6761e9ff624831db9e9f25b3886ddbca/coverage-7.10.6-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd5af36092430c2b075cee966719898f2ae87b636cefb85a653f1d0ba5d5393", size = 218287, upload-time = "2025-08-29T15:34:05.106Z" }, + { url = "https://files.pythonhosted.org/packages/92/d8/50b4a32580cf41ff0423777a2791aaf3269ab60c840b62009aec12d3970d/coverage-7.10.6-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:b0353b0f0850d49ada66fdd7d0c7cdb0f86b900bb9e367024fd14a60cecc1e27", size = 259625, upload-time = "2025-08-29T15:34:06.575Z" }, + { url = "https://files.pythonhosted.org/packages/7e/7e/6a7df5a6fb440a0179d94a348eb6616ed4745e7df26bf2a02bc4db72c421/coverage-7.10.6-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d6b9ae13d5d3e8aeca9ca94198aa7b3ebbc5acfada557d724f2a1f03d2c0b0df", size = 261801, upload-time = "2025-08-29T15:34:08.006Z" }, + { url = "https://files.pythonhosted.org/packages/3a/4c/a270a414f4ed5d196b9d3d67922968e768cd971d1b251e1b4f75e9362f75/coverage-7.10.6-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:675824a363cc05781b1527b39dc2587b8984965834a748177ee3c37b64ffeafb", size = 264027, upload-time = "2025-08-29T15:34:09.806Z" }, + { url = "https://files.pythonhosted.org/packages/9c/8b/3210d663d594926c12f373c5370bf1e7c5c3a427519a8afa65b561b9a55c/coverage-7.10.6-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:692d70ea725f471a547c305f0d0fc6a73480c62fb0da726370c088ab21aed282", size = 261576, upload-time = "2025-08-29T15:34:11.585Z" }, + { url = "https://files.pythonhosted.org/packages/72/d0/e1961eff67e9e1dba3fc5eb7a4caf726b35a5b03776892da8d79ec895775/coverage-7.10.6-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:851430a9a361c7a8484a36126d1d0ff8d529d97385eacc8dfdc9bfc8c2d2cbe4", size = 259341, upload-time = "2025-08-29T15:34:13.159Z" }, + { url = "https://files.pythonhosted.org/packages/3a/06/d6478d152cd189b33eac691cba27a40704990ba95de49771285f34a5861e/coverage-7.10.6-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d9369a23186d189b2fc95cc08b8160ba242057e887d766864f7adf3c46b2df21", size = 260468, upload-time = "2025-08-29T15:34:14.571Z" }, + { url = "https://files.pythonhosted.org/packages/ed/73/737440247c914a332f0b47f7598535b29965bf305e19bbc22d4c39615d2b/coverage-7.10.6-cp313-cp313t-win32.whl", hash = "sha256:92be86fcb125e9bda0da7806afd29a3fd33fdf58fba5d60318399adf40bf37d0", size = 220429, upload-time = "2025-08-29T15:34:16.394Z" }, + { url = "https://files.pythonhosted.org/packages/bd/76/b92d3214740f2357ef4a27c75a526eb6c28f79c402e9f20a922c295c05e2/coverage-7.10.6-cp313-cp313t-win_amd64.whl", hash = "sha256:6b3039e2ca459a70c79523d39347d83b73f2f06af5624905eba7ec34d64d80b5", size = 221493, upload-time = "2025-08-29T15:34:17.835Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8e/6dcb29c599c8a1f654ec6cb68d76644fe635513af16e932d2d4ad1e5ac6e/coverage-7.10.6-cp313-cp313t-win_arm64.whl", hash = "sha256:3fb99d0786fe17b228eab663d16bee2288e8724d26a199c29325aac4b0319b9b", size = 219757, upload-time = "2025-08-29T15:34:19.248Z" }, + { url = "https://files.pythonhosted.org/packages/d3/aa/76cf0b5ec00619ef208da4689281d48b57f2c7fde883d14bf9441b74d59f/coverage-7.10.6-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:6008a021907be8c4c02f37cdc3ffb258493bdebfeaf9a839f9e71dfdc47b018e", size = 217331, upload-time = "2025-08-29T15:34:20.846Z" }, + { url = "https://files.pythonhosted.org/packages/65/91/8e41b8c7c505d398d7730206f3cbb4a875a35ca1041efc518051bfce0f6b/coverage-7.10.6-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:5e75e37f23eb144e78940b40395b42f2321951206a4f50e23cfd6e8a198d3ceb", size = 217607, upload-time = "2025-08-29T15:34:22.433Z" }, + { url = "https://files.pythonhosted.org/packages/87/7f/f718e732a423d442e6616580a951b8d1ec3575ea48bcd0e2228386805e79/coverage-7.10.6-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0f7cb359a448e043c576f0da00aa8bfd796a01b06aa610ca453d4dde09cc1034", size = 248663, upload-time = "2025-08-29T15:34:24.425Z" }, + { url = "https://files.pythonhosted.org/packages/e6/52/c1106120e6d801ac03e12b5285e971e758e925b6f82ee9b86db3aa10045d/coverage-7.10.6-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:c68018e4fc4e14b5668f1353b41ccf4bc83ba355f0e1b3836861c6f042d89ac1", size = 251197, upload-time = "2025-08-29T15:34:25.906Z" }, + { url = "https://files.pythonhosted.org/packages/3d/ec/3a8645b1bb40e36acde9c0609f08942852a4af91a937fe2c129a38f2d3f5/coverage-7.10.6-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cd4b2b0707fc55afa160cd5fc33b27ccbf75ca11d81f4ec9863d5793fc6df56a", size = 252551, upload-time = "2025-08-29T15:34:27.337Z" }, + { url = "https://files.pythonhosted.org/packages/a1/70/09ecb68eeb1155b28a1d16525fd3a9b65fbe75337311a99830df935d62b6/coverage-7.10.6-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4cec13817a651f8804a86e4f79d815b3b28472c910e099e4d5a0e8a3b6a1d4cb", size = 250553, upload-time = "2025-08-29T15:34:29.065Z" }, + { url = "https://files.pythonhosted.org/packages/c6/80/47df374b893fa812e953b5bc93dcb1427a7b3d7a1a7d2db33043d17f74b9/coverage-7.10.6-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:f2a6a8e06bbda06f78739f40bfb56c45d14eb8249d0f0ea6d4b3d48e1f7c695d", size = 248486, upload-time = "2025-08-29T15:34:30.897Z" }, + { url = "https://files.pythonhosted.org/packages/4a/65/9f98640979ecee1b0d1a7164b589de720ddf8100d1747d9bbdb84be0c0fb/coverage-7.10.6-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:081b98395ced0d9bcf60ada7661a0b75f36b78b9d7e39ea0790bb4ed8da14747", size = 249981, upload-time = "2025-08-29T15:34:32.365Z" }, + { url = "https://files.pythonhosted.org/packages/1f/55/eeb6603371e6629037f47bd25bef300387257ed53a3c5fdb159b7ac8c651/coverage-7.10.6-cp314-cp314-win32.whl", hash = "sha256:6937347c5d7d069ee776b2bf4e1212f912a9f1f141a429c475e6089462fcecc5", size = 220054, upload-time = "2025-08-29T15:34:34.124Z" }, + { url = "https://files.pythonhosted.org/packages/15/d1/a0912b7611bc35412e919a2cd59ae98e7ea3b475e562668040a43fb27897/coverage-7.10.6-cp314-cp314-win_amd64.whl", hash = "sha256:adec1d980fa07e60b6ef865f9e5410ba760e4e1d26f60f7e5772c73b9a5b0713", size = 220851, upload-time = "2025-08-29T15:34:35.651Z" }, + { url = "https://files.pythonhosted.org/packages/ef/2d/11880bb8ef80a45338e0b3e0725e4c2d73ffbb4822c29d987078224fd6a5/coverage-7.10.6-cp314-cp314-win_arm64.whl", hash = "sha256:a80f7aef9535442bdcf562e5a0d5a5538ce8abe6bb209cfbf170c462ac2c2a32", size = 219429, upload-time = "2025-08-29T15:34:37.16Z" }, + { url = "https://files.pythonhosted.org/packages/83/c0/1f00caad775c03a700146f55536ecd097a881ff08d310a58b353a1421be0/coverage-7.10.6-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:0de434f4fbbe5af4fa7989521c655c8c779afb61c53ab561b64dcee6149e4c65", size = 218080, upload-time = "2025-08-29T15:34:38.919Z" }, + { url = "https://files.pythonhosted.org/packages/a9/c4/b1c5d2bd7cc412cbeb035e257fd06ed4e3e139ac871d16a07434e145d18d/coverage-7.10.6-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6e31b8155150c57e5ac43ccd289d079eb3f825187d7c66e755a055d2c85794c6", size = 218293, upload-time = "2025-08-29T15:34:40.425Z" }, + { url = "https://files.pythonhosted.org/packages/3f/07/4468d37c94724bf6ec354e4ec2f205fda194343e3e85fd2e59cec57e6a54/coverage-7.10.6-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:98cede73eb83c31e2118ae8d379c12e3e42736903a8afcca92a7218e1f2903b0", size = 259800, upload-time = "2025-08-29T15:34:41.996Z" }, + { url = "https://files.pythonhosted.org/packages/82/d8/f8fb351be5fee31690cd8da768fd62f1cfab33c31d9f7baba6cd8960f6b8/coverage-7.10.6-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f863c08f4ff6b64fa8045b1e3da480f5374779ef187f07b82e0538c68cb4ff8e", size = 261965, upload-time = "2025-08-29T15:34:43.61Z" }, + { url = "https://files.pythonhosted.org/packages/e8/70/65d4d7cfc75c5c6eb2fed3ee5cdf420fd8ae09c4808723a89a81d5b1b9c3/coverage-7.10.6-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2b38261034fda87be356f2c3f42221fdb4171c3ce7658066ae449241485390d5", size = 264220, upload-time = "2025-08-29T15:34:45.387Z" }, + { url = "https://files.pythonhosted.org/packages/98/3c/069df106d19024324cde10e4ec379fe2fb978017d25e97ebee23002fbadf/coverage-7.10.6-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:0e93b1476b79eae849dc3872faeb0bf7948fd9ea34869590bc16a2a00b9c82a7", size = 261660, upload-time = "2025-08-29T15:34:47.288Z" }, + { url = "https://files.pythonhosted.org/packages/fc/8a/2974d53904080c5dc91af798b3a54a4ccb99a45595cc0dcec6eb9616a57d/coverage-7.10.6-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:ff8a991f70f4c0cf53088abf1e3886edcc87d53004c7bb94e78650b4d3dac3b5", size = 259417, upload-time = "2025-08-29T15:34:48.779Z" }, + { url = "https://files.pythonhosted.org/packages/30/38/9616a6b49c686394b318974d7f6e08f38b8af2270ce7488e879888d1e5db/coverage-7.10.6-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ac765b026c9f33044419cbba1da913cfb82cca1b60598ac1c7a5ed6aac4621a0", size = 260567, upload-time = "2025-08-29T15:34:50.718Z" }, + { url = "https://files.pythonhosted.org/packages/76/16/3ed2d6312b371a8cf804abf4e14895b70e4c3491c6e53536d63fd0958a8d/coverage-7.10.6-cp314-cp314t-win32.whl", hash = "sha256:441c357d55f4936875636ef2cfb3bee36e466dcf50df9afbd398ce79dba1ebb7", size = 220831, upload-time = "2025-08-29T15:34:52.653Z" }, + { url = "https://files.pythonhosted.org/packages/d5/e5/d38d0cb830abede2adb8b147770d2a3d0e7fecc7228245b9b1ae6c24930a/coverage-7.10.6-cp314-cp314t-win_amd64.whl", hash = "sha256:073711de3181b2e204e4870ac83a7c4853115b42e9cd4d145f2231e12d670930", size = 221950, upload-time = "2025-08-29T15:34:54.212Z" }, + { url = "https://files.pythonhosted.org/packages/f4/51/e48e550f6279349895b0ffcd6d2a690e3131ba3a7f4eafccc141966d4dea/coverage-7.10.6-cp314-cp314t-win_arm64.whl", hash = "sha256:137921f2bac5559334ba66122b753db6dc5d1cf01eb7b64eb412bb0d064ef35b", size = 219969, upload-time = "2025-08-29T15:34:55.83Z" }, + { url = "https://files.pythonhosted.org/packages/91/70/f73ad83b1d2fd2d5825ac58c8f551193433a7deaf9b0d00a8b69ef61cd9a/coverage-7.10.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:90558c35af64971d65fbd935c32010f9a2f52776103a259f1dee865fe8259352", size = 217009, upload-time = "2025-08-29T15:34:57.381Z" }, + { url = "https://files.pythonhosted.org/packages/01/e8/099b55cd48922abbd4b01ddd9ffa352408614413ebfc965501e981aced6b/coverage-7.10.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:8953746d371e5695405806c46d705a3cd170b9cc2b9f93953ad838f6c1e58612", size = 217400, upload-time = "2025-08-29T15:34:58.985Z" }, + { url = "https://files.pythonhosted.org/packages/ee/d1/c6bac7c9e1003110a318636fef3b5c039df57ab44abcc41d43262a163c28/coverage-7.10.6-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:c83f6afb480eae0313114297d29d7c295670a41c11b274e6bca0c64540c1ce7b", size = 243835, upload-time = "2025-08-29T15:35:00.541Z" }, + { url = "https://files.pythonhosted.org/packages/01/f9/82c6c061838afbd2172e773156c0aa84a901d59211b4975a4e93accf5c89/coverage-7.10.6-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:7eb68d356ba0cc158ca535ce1381dbf2037fa8cb5b1ae5ddfc302e7317d04144", size = 245658, upload-time = "2025-08-29T15:35:02.135Z" }, + { url = "https://files.pythonhosted.org/packages/81/6a/35674445b1d38161148558a3ff51b0aa7f0b54b1def3abe3fbd34efe05bc/coverage-7.10.6-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5b15a87265e96307482746d86995f4bff282f14b027db75469c446da6127433b", size = 247433, upload-time = "2025-08-29T15:35:03.777Z" }, + { url = "https://files.pythonhosted.org/packages/18/27/98c99e7cafb288730a93535092eb433b5503d529869791681c4f2e2012a8/coverage-7.10.6-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fc53ba868875bfbb66ee447d64d6413c2db91fddcfca57025a0e7ab5b07d5862", size = 245315, upload-time = "2025-08-29T15:35:05.629Z" }, + { url = "https://files.pythonhosted.org/packages/09/05/123e0dba812408c719c319dea05782433246f7aa7b67e60402d90e847545/coverage-7.10.6-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:efeda443000aa23f276f4df973cb82beca682fd800bb119d19e80504ffe53ec2", size = 243385, upload-time = "2025-08-29T15:35:07.494Z" }, + { url = "https://files.pythonhosted.org/packages/67/52/d57a42502aef05c6325f28e2e81216c2d9b489040132c18725b7a04d1448/coverage-7.10.6-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9702b59d582ff1e184945d8b501ffdd08d2cee38d93a2206aa5f1365ce0b8d78", size = 244343, upload-time = "2025-08-29T15:35:09.55Z" }, + { url = "https://files.pythonhosted.org/packages/6b/22/7f6fad7dbb37cf99b542c5e157d463bd96b797078b1ec506691bc836f476/coverage-7.10.6-cp39-cp39-win32.whl", hash = "sha256:2195f8e16ba1a44651ca684db2ea2b2d4b5345da12f07d9c22a395202a05b23c", size = 219530, upload-time = "2025-08-29T15:35:11.167Z" }, + { url = "https://files.pythonhosted.org/packages/62/30/e2fda29bfe335026027e11e6a5e57a764c9df13127b5cf42af4c3e99b937/coverage-7.10.6-cp39-cp39-win_amd64.whl", hash = "sha256:f32ff80e7ef6a5b5b606ea69a36e97b219cd9dc799bcf2963018a4d8f788cfbf", size = 220432, upload-time = "2025-08-29T15:35:12.902Z" }, + { url = "https://files.pythonhosted.org/packages/44/0c/50db5379b615854b5cf89146f8f5bd1d5a9693d7f3a987e269693521c404/coverage-7.10.6-py3-none-any.whl", hash = "sha256:92c4ecf6bf11b2e85fd4d8204814dc26e6a19f0c9d938c207c5cb0eadfcabbe3", size = 208986, upload-time = "2025-08-29T15:35:14.506Z" }, +] + +[package.optional-dependencies] +toml = [ + { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version <= '3.11'" }, +] + +[[package]] +name = "distlib" +version = "0.4.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/96/8e/709914eb2b5749865801041647dc7f4e6d00b549cfe88b65ca192995f07c/distlib-0.4.0.tar.gz", hash = "sha256:feec40075be03a04501a973d81f633735b4b69f98b05450592310c0f401a4e0d", size = 614605, upload-time = "2025-07-17T16:52:00.465Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/33/6b/e0547afaf41bf2c42e52430072fa5658766e3d65bd4b03a563d1b6336f57/distlib-0.4.0-py2.py3-none-any.whl", hash = "sha256:9659f7d87e46584a30b5780e43ac7a2143098441670ff0a49d5f9034c54a6c16", size = 469047, upload-time = "2025-07-17T16:51:58.613Z" }, +] + +[[package]] +name = "exceptiongroup" +version = "1.3.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.13'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, +] + +[[package]] +name = "filelock" +version = "3.16.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037, upload-time = "2024-09-17T19:02:01.779Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163, upload-time = "2024-09-17T19:02:00.268Z" }, +] + +[[package]] +name = "filelock" +version = "3.19.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, +] + +[[package]] +name = "flake8" +version = "5.0.4" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "mccabe", marker = "python_full_version < '3.8.1'" }, + { name = "pycodestyle", version = "2.9.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8.1'" }, + { name = "pyflakes", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8.1'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ad/00/9808c62b2d529cefc69ce4e4a1ea42c0f855effa55817b7327ec5b75e60a/flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", size = 145862, upload-time = "2022-08-03T23:21:27.108Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cf/a0/b881b63a17a59d9d07f5c0cc91a29182c8e8a9aa2bde5b3b2b16519c02f4/flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248", size = 61897, upload-time = "2022-08-03T23:21:25.027Z" }, +] + +[[package]] +name = "flake8" +version = "7.1.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", +] +dependencies = [ + { name = "mccabe", marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, + { name = "pycodestyle", version = "2.12.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, + { name = "pyflakes", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/58/16/3f2a0bb700ad65ac9663262905a025917c020a3f92f014d2ba8964b4602c/flake8-7.1.2.tar.gz", hash = "sha256:c586ffd0b41540951ae41af572e6790dbd49fc12b3aa2541685d253d9bd504bd", size = 48119, upload-time = "2025-02-16T18:45:44.296Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/35/f8/08d37b2cd89da306e3520bd27f8a85692122b42b56c0c2c3784ff09c022f/flake8-7.1.2-py2.py3-none-any.whl", hash = "sha256:1cbc62e65536f65e6d754dfe6f1bada7f5cf392d6f5db3c2b85892466c3e7c1a", size = 57745, upload-time = "2025-02-16T18:45:42.351Z" }, +] + +[[package]] +name = "flake8" +version = "7.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "mccabe", marker = "python_full_version >= '3.9'" }, + { name = "pycodestyle", version = "2.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pyflakes", version = "3.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872", size = 48326, upload-time = "2025-06-20T19:31:35.838Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", size = 57922, upload-time = "2025-06-20T19:31:34.425Z" }, +] + +[[package]] +name = "identify" +version = "2.6.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/29/bb/25024dbcc93516c492b75919e76f389bac754a3e4248682fba32b250c880/identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98", size = 99097, upload-time = "2024-09-14T23:50:32.513Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7d/0c/4ef72754c050979fdcc06c744715ae70ea37e734816bb6514f79df77a42f/identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0", size = 98972, upload-time = "2024-09-14T23:50:30.747Z" }, +] + +[[package]] +name = "identify" +version = "2.6.14" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/52/c4/62963f25a678f6a050fb0505a65e9e726996171e6dbe1547f79619eefb15/identify-2.6.14.tar.gz", hash = "sha256:663494103b4f717cb26921c52f8751363dc89db64364cd836a9bf1535f53cd6a", size = 99283, upload-time = "2025-09-06T19:30:52.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e5/ae/2ad30f4652712c82f1c23423d79136fbce338932ad166d70c1efb86a5998/identify-2.6.14-py2.py3-none-any.whl", hash = "sha256:11a073da82212c6646b1f39bb20d4483bfb9543bd5566fec60053c4bb309bf2e", size = 99172, upload-time = "2025-09-06T19:30:51.759Z" }, +] + +[[package]] +name = "idna" +version = "3.10" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f1/70/7703c29685631f5a7590aa73f1f1d3fa9a380e654b86af429e0934a32f7d/idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", size = 190490, upload-time = "2024-09-15T18:07:39.745Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/c6/c88e154df9c4e1a2a66ccf0005a88dfb2650c1dffb6f5ce603dfbd452ce3/idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3", size = 70442, upload-time = "2024-09-15T18:07:37.964Z" }, +] + +[[package]] +name = "iniconfig" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, +] + +[[package]] +name = "jinja2" +version = "3.1.6" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markupsafe", version = "2.1.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "markupsafe", version = "3.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/62/a1/3d680cbfd5f4b8f15abc1d571870c5fc3e594bb582bc3b64ea099db13e56/jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67", size = 134899, upload-time = "2025-03-05T20:05:00.369Z" }, +] + +[[package]] +name = "kilm" +version = "0.4.2" +source = { editable = "." } +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "jinja2" }, + { name = "packaging" }, + { name = "pathlib" }, + { name = "pathspec" }, + { name = "pyyaml" }, + { name = "questionary", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "questionary", version = "2.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "requests", version = "2.32.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "rich" }, + { name = "typer" }, +] + +[package.optional-dependencies] +dev = [ + { name = "black", version = "24.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "black", version = "25.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "flake8", version = "5.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8.1'" }, + { name = "flake8", version = "7.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, + { name = "flake8", version = "7.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pre-commit", version = "3.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pre-commit", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pyrefly" }, + { name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pytest-cov", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "pytest-cov", version = "6.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "ruff" }, +] + +[package.metadata] +requires-dist = [ + { name = "black", marker = "extra == 'dev'", specifier = ">=22.0.0" }, + { name = "click", specifier = ">=8.0" }, + { name = "flake8", marker = "extra == 'dev'", specifier = ">=4.0.0" }, + { name = "jinja2", specifier = ">=3.1.6" }, + { name = "packaging", specifier = ">=25.0" }, + { name = "pathlib", specifier = ">=1.0.1" }, + { name = "pathspec", specifier = ">=0.12.1" }, + { name = "pre-commit", marker = "extra == 'dev'", specifier = ">=3.5.0" }, + { name = "pyrefly", marker = "extra == 'dev'", specifier = ">=0.31.0" }, + { name = "pytest", marker = "extra == 'dev'", specifier = ">=7.0.0" }, + { name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=4.0.0" }, + { name = "pyyaml", specifier = ">=6.0" }, + { name = "questionary", specifier = ">=1.10.0" }, + { name = "requests", specifier = ">=2.32.4" }, + { name = "rich", specifier = ">=14.0.0" }, + { name = "ruff", marker = "extra == 'dev'", specifier = ">=0.1.0" }, + { name = "typer", specifier = ">=0.17.4" }, +] +provides-extras = ["dev"] + +[[package]] +name = "markdown-it-py" +version = "3.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.9.*'", + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "mdurl", marker = "python_full_version < '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/38/71/3b932df36c1a044d397a1f92d1cf91ee0a503d91e470cbd670aa66b07ed0/markdown-it-py-3.0.0.tar.gz", hash = "sha256:e3f60a94fa066dc52ec76661e37c851cb232d92f9886b15cb560aaada2df8feb", size = 74596, upload-time = "2023-06-03T06:41:14.443Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/42/d7/1ec15b46af6af88f19b8e5ffea08fa375d433c998b8a7639e76935c14f1f/markdown_it_py-3.0.0-py3-none-any.whl", hash = "sha256:355216845c60bd96232cd8d8c40e8f9765cc86f46880e43a8fd22dc1a1a8cab1", size = 87528, upload-time = "2023-06-03T06:41:11.019Z" }, +] + +[[package]] +name = "markdown-it-py" +version = "4.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", +] +dependencies = [ + { name = "mdurl", marker = "python_full_version >= '3.10'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/5b/f5/4ec618ed16cc4f8fb3b701563655a69816155e79e24a17b651541804721d/markdown_it_py-4.0.0.tar.gz", hash = "sha256:cb0a2b4aa34f932c007117b194e945bd74e0ec24133ceb5bac59009cda1cb9f3", size = 73070, upload-time = "2025-08-11T12:57:52.854Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, +] + +[[package]] +name = "markupsafe" +version = "2.1.5" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/87/5b/aae44c6655f3801e81aa3eef09dbbf012431987ba564d7231722f68df02d/MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", size = 19384, upload-time = "2024-02-02T16:31:22.863Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e4/54/ad5eb37bf9d51800010a74e4665425831a9db4e7c4e0fde4352e391e808e/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", size = 18206, upload-time = "2024-02-02T16:30:04.105Z" }, + { url = "https://files.pythonhosted.org/packages/6a/4a/a4d49415e600bacae038c67f9fecc1d5433b9d3c71a4de6f33537b89654c/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", size = 14079, upload-time = "2024-02-02T16:30:06.5Z" }, + { url = "https://files.pythonhosted.org/packages/0a/7b/85681ae3c33c385b10ac0f8dd025c30af83c78cec1c37a6aa3b55e67f5ec/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", size = 26620, upload-time = "2024-02-02T16:30:08.31Z" }, + { url = "https://files.pythonhosted.org/packages/7c/52/2b1b570f6b8b803cef5ac28fdf78c0da318916c7d2fe9402a84d591b394c/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", size = 25818, upload-time = "2024-02-02T16:30:09.577Z" }, + { url = "https://files.pythonhosted.org/packages/29/fe/a36ba8c7ca55621620b2d7c585313efd10729e63ef81e4e61f52330da781/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", size = 25493, upload-time = "2024-02-02T16:30:11.488Z" }, + { url = "https://files.pythonhosted.org/packages/60/ae/9c60231cdfda003434e8bd27282b1f4e197ad5a710c14bee8bea8a9ca4f0/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", size = 30630, upload-time = "2024-02-02T16:30:13.144Z" }, + { url = "https://files.pythonhosted.org/packages/65/dc/1510be4d179869f5dafe071aecb3f1f41b45d37c02329dfba01ff59e5ac5/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", size = 29745, upload-time = "2024-02-02T16:30:14.222Z" }, + { url = "https://files.pythonhosted.org/packages/30/39/8d845dd7d0b0613d86e0ef89549bfb5f61ed781f59af45fc96496e897f3a/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", size = 30021, upload-time = "2024-02-02T16:30:16.032Z" }, + { url = "https://files.pythonhosted.org/packages/c7/5c/356a6f62e4f3c5fbf2602b4771376af22a3b16efa74eb8716fb4e328e01e/MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", size = 16659, upload-time = "2024-02-02T16:30:17.079Z" }, + { url = "https://files.pythonhosted.org/packages/69/48/acbf292615c65f0604a0c6fc402ce6d8c991276e16c80c46a8f758fbd30c/MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", size = 17213, upload-time = "2024-02-02T16:30:18.251Z" }, + { url = "https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", size = 18219, upload-time = "2024-02-02T16:30:19.988Z" }, + { url = "https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", size = 14098, upload-time = "2024-02-02T16:30:21.063Z" }, + { url = "https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", size = 29014, upload-time = "2024-02-02T16:30:22.926Z" }, + { url = "https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", size = 28220, upload-time = "2024-02-02T16:30:24.76Z" }, + { url = "https://files.pythonhosted.org/packages/0c/40/2e73e7d532d030b1e41180807a80d564eda53babaf04d65e15c1cf897e40/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", size = 27756, upload-time = "2024-02-02T16:30:25.877Z" }, + { url = "https://files.pythonhosted.org/packages/18/46/5dca760547e8c59c5311b332f70605d24c99d1303dd9a6e1fc3ed0d73561/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", size = 33988, upload-time = "2024-02-02T16:30:26.935Z" }, + { url = "https://files.pythonhosted.org/packages/6d/c5/27febe918ac36397919cd4a67d5579cbbfa8da027fa1238af6285bb368ea/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", size = 32718, upload-time = "2024-02-02T16:30:28.111Z" }, + { url = "https://files.pythonhosted.org/packages/f8/81/56e567126a2c2bc2684d6391332e357589a96a76cb9f8e5052d85cb0ead8/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", size = 33317, upload-time = "2024-02-02T16:30:29.214Z" }, + { url = "https://files.pythonhosted.org/packages/00/0b/23f4b2470accb53285c613a3ab9ec19dc944eaf53592cb6d9e2af8aa24cc/MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", size = 16670, upload-time = "2024-02-02T16:30:30.915Z" }, + { url = "https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", size = 17224, upload-time = "2024-02-02T16:30:32.09Z" }, + { url = "https://files.pythonhosted.org/packages/53/bd/583bf3e4c8d6a321938c13f49d44024dbe5ed63e0a7ba127e454a66da974/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", size = 18215, upload-time = "2024-02-02T16:30:33.081Z" }, + { url = "https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", size = 14069, upload-time = "2024-02-02T16:30:34.148Z" }, + { url = "https://files.pythonhosted.org/packages/51/b5/5d8ec796e2a08fc814a2c7d2584b55f889a55cf17dd1a90f2beb70744e5c/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", size = 29452, upload-time = "2024-02-02T16:30:35.149Z" }, + { url = "https://files.pythonhosted.org/packages/0a/0d/2454f072fae3b5a137c119abf15465d1771319dfe9e4acbb31722a0fff91/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", size = 28462, upload-time = "2024-02-02T16:30:36.166Z" }, + { url = "https://files.pythonhosted.org/packages/2d/75/fd6cb2e68780f72d47e6671840ca517bda5ef663d30ada7616b0462ad1e3/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", size = 27869, upload-time = "2024-02-02T16:30:37.834Z" }, + { url = "https://files.pythonhosted.org/packages/b0/81/147c477391c2750e8fc7705829f7351cf1cd3be64406edcf900dc633feb2/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", size = 33906, upload-time = "2024-02-02T16:30:39.366Z" }, + { url = "https://files.pythonhosted.org/packages/8b/ff/9a52b71839d7a256b563e85d11050e307121000dcebc97df120176b3ad93/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", size = 32296, upload-time = "2024-02-02T16:30:40.413Z" }, + { url = "https://files.pythonhosted.org/packages/88/07/2dc76aa51b481eb96a4c3198894f38b480490e834479611a4053fbf08623/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", size = 33038, upload-time = "2024-02-02T16:30:42.243Z" }, + { url = "https://files.pythonhosted.org/packages/96/0c/620c1fb3661858c0e37eb3cbffd8c6f732a67cd97296f725789679801b31/MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", size = 16572, upload-time = "2024-02-02T16:30:43.326Z" }, + { url = "https://files.pythonhosted.org/packages/3f/14/c3554d512d5f9100a95e737502f4a2323a1959f6d0d01e0d0997b35f7b10/MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", size = 17127, upload-time = "2024-02-02T16:30:44.418Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ff/2c942a82c35a49df5de3a630ce0a8456ac2969691b230e530ac12314364c/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", size = 18192, upload-time = "2024-02-02T16:30:57.715Z" }, + { url = "https://files.pythonhosted.org/packages/4f/14/6f294b9c4f969d0c801a4615e221c1e084722ea6114ab2114189c5b8cbe0/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", size = 14072, upload-time = "2024-02-02T16:30:58.844Z" }, + { url = "https://files.pythonhosted.org/packages/81/d4/fd74714ed30a1dedd0b82427c02fa4deec64f173831ec716da11c51a50aa/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", size = 26928, upload-time = "2024-02-02T16:30:59.922Z" }, + { url = "https://files.pythonhosted.org/packages/c7/bd/50319665ce81bb10e90d1cf76f9e1aa269ea6f7fa30ab4521f14d122a3df/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", size = 26106, upload-time = "2024-02-02T16:31:01.582Z" }, + { url = "https://files.pythonhosted.org/packages/4c/6f/f2b0f675635b05f6afd5ea03c094557bdb8622fa8e673387444fe8d8e787/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68", size = 25781, upload-time = "2024-02-02T16:31:02.71Z" }, + { url = "https://files.pythonhosted.org/packages/51/e0/393467cf899b34a9d3678e78961c2c8cdf49fb902a959ba54ece01273fb1/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", size = 30518, upload-time = "2024-02-02T16:31:04.392Z" }, + { url = "https://files.pythonhosted.org/packages/f6/02/5437e2ad33047290dafced9df741d9efc3e716b75583bbd73a9984f1b6f7/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", size = 29669, upload-time = "2024-02-02T16:31:05.53Z" }, + { url = "https://files.pythonhosted.org/packages/0e/7d/968284145ffd9d726183ed6237c77938c021abacde4e073020f920e060b2/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", size = 29933, upload-time = "2024-02-02T16:31:06.636Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f3/ecb00fc8ab02b7beae8699f34db9357ae49d9f21d4d3de6f305f34fa949e/MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", size = 16656, upload-time = "2024-02-02T16:31:07.767Z" }, + { url = "https://files.pythonhosted.org/packages/92/21/357205f03514a49b293e214ac39de01fadd0970a6e05e4bf1ddd0ffd0881/MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", size = 17206, upload-time = "2024-02-02T16:31:08.843Z" }, + { url = "https://files.pythonhosted.org/packages/0f/31/780bb297db036ba7b7bbede5e1d7f1e14d704ad4beb3ce53fb495d22bc62/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", size = 18193, upload-time = "2024-02-02T16:31:10.155Z" }, + { url = "https://files.pythonhosted.org/packages/6c/77/d77701bbef72892affe060cdacb7a2ed7fd68dae3b477a8642f15ad3b132/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", size = 14073, upload-time = "2024-02-02T16:31:11.442Z" }, + { url = "https://files.pythonhosted.org/packages/d9/a7/1e558b4f78454c8a3a0199292d96159eb4d091f983bc35ef258314fe7269/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", size = 26486, upload-time = "2024-02-02T16:31:12.488Z" }, + { url = "https://files.pythonhosted.org/packages/5f/5a/360da85076688755ea0cceb92472923086993e86b5613bbae9fbc14136b0/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", size = 25685, upload-time = "2024-02-02T16:31:13.726Z" }, + { url = "https://files.pythonhosted.org/packages/6a/18/ae5a258e3401f9b8312f92b028c54d7026a97ec3ab20bfaddbdfa7d8cce8/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", size = 25338, upload-time = "2024-02-02T16:31:14.812Z" }, + { url = "https://files.pythonhosted.org/packages/0b/cc/48206bd61c5b9d0129f4d75243b156929b04c94c09041321456fd06a876d/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", size = 30439, upload-time = "2024-02-02T16:31:15.946Z" }, + { url = "https://files.pythonhosted.org/packages/d1/06/a41c112ab9ffdeeb5f77bc3e331fdadf97fa65e52e44ba31880f4e7f983c/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", size = 29531, upload-time = "2024-02-02T16:31:17.13Z" }, + { url = "https://files.pythonhosted.org/packages/02/8c/ab9a463301a50dab04d5472e998acbd4080597abc048166ded5c7aa768c8/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", size = 29823, upload-time = "2024-02-02T16:31:18.247Z" }, + { url = "https://files.pythonhosted.org/packages/bc/29/9bc18da763496b055d8e98ce476c8e718dcfd78157e17f555ce6dd7d0895/MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", size = 16658, upload-time = "2024-02-02T16:31:19.583Z" }, + { url = "https://files.pythonhosted.org/packages/f6/f8/4da07de16f10551ca1f640c92b5f316f9394088b183c6a57183df6de5ae4/MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", size = 17211, upload-time = "2024-02-02T16:31:20.96Z" }, +] + +[[package]] +name = "markupsafe" +version = "3.0.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" }, + { url = "https://files.pythonhosted.org/packages/04/e1/6e2194baeae0bca1fae6629dc0cbbb968d4d941469cbab11a3872edff374/MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", size = 12393, upload-time = "2024-10-18T15:20:52.426Z" }, + { url = "https://files.pythonhosted.org/packages/1d/69/35fa85a8ece0a437493dc61ce0bb6d459dcba482c34197e3efc829aa357f/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", size = 21732, upload-time = "2024-10-18T15:20:53.578Z" }, + { url = "https://files.pythonhosted.org/packages/22/35/137da042dfb4720b638d2937c38a9c2df83fe32d20e8c8f3185dbfef05f7/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", size = 20866, upload-time = "2024-10-18T15:20:55.06Z" }, + { url = "https://files.pythonhosted.org/packages/29/28/6d029a903727a1b62edb51863232152fd335d602def598dade38996887f0/MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", size = 20964, upload-time = "2024-10-18T15:20:55.906Z" }, + { url = "https://files.pythonhosted.org/packages/cc/cd/07438f95f83e8bc028279909d9c9bd39e24149b0d60053a97b2bc4f8aa51/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", size = 21977, upload-time = "2024-10-18T15:20:57.189Z" }, + { url = "https://files.pythonhosted.org/packages/29/01/84b57395b4cc062f9c4c55ce0df7d3108ca32397299d9df00fedd9117d3d/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", size = 21366, upload-time = "2024-10-18T15:20:58.235Z" }, + { url = "https://files.pythonhosted.org/packages/bd/6e/61ebf08d8940553afff20d1fb1ba7294b6f8d279df9fd0c0db911b4bbcfd/MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", size = 21091, upload-time = "2024-10-18T15:20:59.235Z" }, + { url = "https://files.pythonhosted.org/packages/11/23/ffbf53694e8c94ebd1e7e491de185124277964344733c45481f32ede2499/MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50", size = 15065, upload-time = "2024-10-18T15:21:00.307Z" }, + { url = "https://files.pythonhosted.org/packages/44/06/e7175d06dd6e9172d4a69a72592cb3f7a996a9c396eee29082826449bbc3/MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", size = 15514, upload-time = "2024-10-18T15:21:01.122Z" }, + { url = "https://files.pythonhosted.org/packages/6b/28/bbf83e3f76936960b850435576dd5e67034e200469571be53f69174a2dfd/MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", size = 14353, upload-time = "2024-10-18T15:21:02.187Z" }, + { url = "https://files.pythonhosted.org/packages/6c/30/316d194b093cde57d448a4c3209f22e3046c5bb2fb0820b118292b334be7/MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", size = 12392, upload-time = "2024-10-18T15:21:02.941Z" }, + { url = "https://files.pythonhosted.org/packages/f2/96/9cdafba8445d3a53cae530aaf83c38ec64c4d5427d975c974084af5bc5d2/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", size = 23984, upload-time = "2024-10-18T15:21:03.953Z" }, + { url = "https://files.pythonhosted.org/packages/f1/a4/aefb044a2cd8d7334c8a47d3fb2c9f328ac48cb349468cc31c20b539305f/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", size = 23120, upload-time = "2024-10-18T15:21:06.495Z" }, + { url = "https://files.pythonhosted.org/packages/8d/21/5e4851379f88f3fad1de30361db501300d4f07bcad047d3cb0449fc51f8c/MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", size = 23032, upload-time = "2024-10-18T15:21:07.295Z" }, + { url = "https://files.pythonhosted.org/packages/00/7b/e92c64e079b2d0d7ddf69899c98842f3f9a60a1ae72657c89ce2655c999d/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", size = 24057, upload-time = "2024-10-18T15:21:08.073Z" }, + { url = "https://files.pythonhosted.org/packages/f9/ac/46f960ca323037caa0a10662ef97d0a4728e890334fc156b9f9e52bcc4ca/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", size = 23359, upload-time = "2024-10-18T15:21:09.318Z" }, + { url = "https://files.pythonhosted.org/packages/69/84/83439e16197337b8b14b6a5b9c2105fff81d42c2a7c5b58ac7b62ee2c3b1/MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", size = 23306, upload-time = "2024-10-18T15:21:10.185Z" }, + { url = "https://files.pythonhosted.org/packages/9a/34/a15aa69f01e2181ed8d2b685c0d2f6655d5cca2c4db0ddea775e631918cd/MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", size = 15094, upload-time = "2024-10-18T15:21:11.005Z" }, + { url = "https://files.pythonhosted.org/packages/da/b8/3a3bd761922d416f3dc5d00bfbed11f66b1ab89a0c2b6e887240a30b0f6b/MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", size = 15521, upload-time = "2024-10-18T15:21:12.911Z" }, + { url = "https://files.pythonhosted.org/packages/22/09/d1f21434c97fc42f09d290cbb6350d44eb12f09cc62c9476effdb33a18aa/MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", size = 14274, upload-time = "2024-10-18T15:21:13.777Z" }, + { url = "https://files.pythonhosted.org/packages/6b/b0/18f76bba336fa5aecf79d45dcd6c806c280ec44538b3c13671d49099fdd0/MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", size = 12348, upload-time = "2024-10-18T15:21:14.822Z" }, + { url = "https://files.pythonhosted.org/packages/e0/25/dd5c0f6ac1311e9b40f4af06c78efde0f3b5cbf02502f8ef9501294c425b/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", size = 24149, upload-time = "2024-10-18T15:21:15.642Z" }, + { url = "https://files.pythonhosted.org/packages/f3/f0/89e7aadfb3749d0f52234a0c8c7867877876e0a20b60e2188e9850794c17/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", size = 23118, upload-time = "2024-10-18T15:21:17.133Z" }, + { url = "https://files.pythonhosted.org/packages/d5/da/f2eeb64c723f5e3777bc081da884b414671982008c47dcc1873d81f625b6/MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", size = 22993, upload-time = "2024-10-18T15:21:18.064Z" }, + { url = "https://files.pythonhosted.org/packages/da/0e/1f32af846df486dce7c227fe0f2398dc7e2e51d4a370508281f3c1c5cddc/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", size = 24178, upload-time = "2024-10-18T15:21:18.859Z" }, + { url = "https://files.pythonhosted.org/packages/c4/f6/bb3ca0532de8086cbff5f06d137064c8410d10779c4c127e0e47d17c0b71/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", size = 23319, upload-time = "2024-10-18T15:21:19.671Z" }, + { url = "https://files.pythonhosted.org/packages/a2/82/8be4c96ffee03c5b4a034e60a31294daf481e12c7c43ab8e34a1453ee48b/MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", size = 23352, upload-time = "2024-10-18T15:21:20.971Z" }, + { url = "https://files.pythonhosted.org/packages/51/ae/97827349d3fcffee7e184bdf7f41cd6b88d9919c80f0263ba7acd1bbcb18/MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", size = 15097, upload-time = "2024-10-18T15:21:22.646Z" }, + { url = "https://files.pythonhosted.org/packages/c1/80/a61f99dc3a936413c3ee4e1eecac96c0da5ed07ad56fd975f1a9da5bc630/MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", size = 15601, upload-time = "2024-10-18T15:21:23.499Z" }, + { url = "https://files.pythonhosted.org/packages/83/0e/67eb10a7ecc77a0c2bbe2b0235765b98d164d81600746914bebada795e97/MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", size = 14274, upload-time = "2024-10-18T15:21:24.577Z" }, + { url = "https://files.pythonhosted.org/packages/2b/6d/9409f3684d3335375d04e5f05744dfe7e9f120062c9857df4ab490a1031a/MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", size = 12352, upload-time = "2024-10-18T15:21:25.382Z" }, + { url = "https://files.pythonhosted.org/packages/d2/f5/6eadfcd3885ea85fe2a7c128315cc1bb7241e1987443d78c8fe712d03091/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", size = 24122, upload-time = "2024-10-18T15:21:26.199Z" }, + { url = "https://files.pythonhosted.org/packages/0c/91/96cf928db8236f1bfab6ce15ad070dfdd02ed88261c2afafd4b43575e9e9/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", size = 23085, upload-time = "2024-10-18T15:21:27.029Z" }, + { url = "https://files.pythonhosted.org/packages/c2/cf/c9d56af24d56ea04daae7ac0940232d31d5a8354f2b457c6d856b2057d69/MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", size = 22978, upload-time = "2024-10-18T15:21:27.846Z" }, + { url = "https://files.pythonhosted.org/packages/2a/9f/8619835cd6a711d6272d62abb78c033bda638fdc54c4e7f4272cf1c0962b/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", size = 24208, upload-time = "2024-10-18T15:21:28.744Z" }, + { url = "https://files.pythonhosted.org/packages/f9/bf/176950a1792b2cd2102b8ffeb5133e1ed984547b75db47c25a67d3359f77/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", size = 23357, upload-time = "2024-10-18T15:21:29.545Z" }, + { url = "https://files.pythonhosted.org/packages/ce/4f/9a02c1d335caabe5c4efb90e1b6e8ee944aa245c1aaaab8e8a618987d816/MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", size = 23344, upload-time = "2024-10-18T15:21:30.366Z" }, + { url = "https://files.pythonhosted.org/packages/ee/55/c271b57db36f748f0e04a759ace9f8f759ccf22b4960c270c78a394f58be/MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", size = 15101, upload-time = "2024-10-18T15:21:31.207Z" }, + { url = "https://files.pythonhosted.org/packages/29/88/07df22d2dd4df40aba9f3e402e6dc1b8ee86297dddbad4872bd5e7b0094f/MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", size = 15603, upload-time = "2024-10-18T15:21:32.032Z" }, + { url = "https://files.pythonhosted.org/packages/62/6a/8b89d24db2d32d433dffcd6a8779159da109842434f1dd2f6e71f32f738c/MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", size = 14510, upload-time = "2024-10-18T15:21:33.625Z" }, + { url = "https://files.pythonhosted.org/packages/7a/06/a10f955f70a2e5a9bf78d11a161029d278eeacbd35ef806c3fd17b13060d/MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", size = 12486, upload-time = "2024-10-18T15:21:34.611Z" }, + { url = "https://files.pythonhosted.org/packages/34/cf/65d4a571869a1a9078198ca28f39fba5fbb910f952f9dbc5220afff9f5e6/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", size = 25480, upload-time = "2024-10-18T15:21:35.398Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e3/90e9651924c430b885468b56b3d597cabf6d72be4b24a0acd1fa0e12af67/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", size = 23914, upload-time = "2024-10-18T15:21:36.231Z" }, + { url = "https://files.pythonhosted.org/packages/66/8c/6c7cf61f95d63bb866db39085150df1f2a5bd3335298f14a66b48e92659c/MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", size = 23796, upload-time = "2024-10-18T15:21:37.073Z" }, + { url = "https://files.pythonhosted.org/packages/bb/35/cbe9238ec3f47ac9a7c8b3df7a808e7cb50fe149dc7039f5f454b3fba218/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", size = 25473, upload-time = "2024-10-18T15:21:37.932Z" }, + { url = "https://files.pythonhosted.org/packages/e6/32/7621a4382488aa283cc05e8984a9c219abad3bca087be9ec77e89939ded9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", size = 24114, upload-time = "2024-10-18T15:21:39.799Z" }, + { url = "https://files.pythonhosted.org/packages/0d/80/0985960e4b89922cb5a0bac0ed39c5b96cbc1a536a99f30e8c220a996ed9/MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", size = 24098, upload-time = "2024-10-18T15:21:40.813Z" }, + { url = "https://files.pythonhosted.org/packages/82/78/fedb03c7d5380df2427038ec8d973587e90561b2d90cd472ce9254cf348b/MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", size = 15208, upload-time = "2024-10-18T15:21:41.814Z" }, + { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, + { url = "https://files.pythonhosted.org/packages/a7/ea/9b1530c3fdeeca613faeb0fb5cbcf2389d816072fab72a71b45749ef6062/MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", size = 14344, upload-time = "2024-10-18T15:21:43.721Z" }, + { url = "https://files.pythonhosted.org/packages/4b/c2/fbdbfe48848e7112ab05e627e718e854d20192b674952d9042ebd8c9e5de/MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", size = 12389, upload-time = "2024-10-18T15:21:44.666Z" }, + { url = "https://files.pythonhosted.org/packages/f0/25/7a7c6e4dbd4f867d95d94ca15449e91e52856f6ed1905d58ef1de5e211d0/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", size = 21607, upload-time = "2024-10-18T15:21:45.452Z" }, + { url = "https://files.pythonhosted.org/packages/53/8f/f339c98a178f3c1e545622206b40986a4c3307fe39f70ccd3d9df9a9e425/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", size = 20728, upload-time = "2024-10-18T15:21:46.295Z" }, + { url = "https://files.pythonhosted.org/packages/1a/03/8496a1a78308456dbd50b23a385c69b41f2e9661c67ea1329849a598a8f9/MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", size = 20826, upload-time = "2024-10-18T15:21:47.134Z" }, + { url = "https://files.pythonhosted.org/packages/e6/cf/0a490a4bd363048c3022f2f475c8c05582179bb179defcee4766fb3dcc18/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", size = 21843, upload-time = "2024-10-18T15:21:48.334Z" }, + { url = "https://files.pythonhosted.org/packages/19/a3/34187a78613920dfd3cdf68ef6ce5e99c4f3417f035694074beb8848cd77/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", size = 21219, upload-time = "2024-10-18T15:21:49.587Z" }, + { url = "https://files.pythonhosted.org/packages/17/d8/5811082f85bb88410ad7e452263af048d685669bbbfb7b595e8689152498/MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", size = 20946, upload-time = "2024-10-18T15:21:50.441Z" }, + { url = "https://files.pythonhosted.org/packages/7c/31/bd635fb5989440d9365c5e3c47556cfea121c7803f5034ac843e8f37c2f2/MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", size = 15063, upload-time = "2024-10-18T15:21:51.385Z" }, + { url = "https://files.pythonhosted.org/packages/b3/73/085399401383ce949f727afec55ec3abd76648d04b9f22e1c0e99cb4bec3/MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", size = 15506, upload-time = "2024-10-18T15:21:52.974Z" }, +] + +[[package]] +name = "mccabe" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e7/ff/0ffefdcac38932a54d2b5eed4e0ba8a408f215002cd178ad1df0f2806ff8/mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", size = 9658, upload-time = "2022-01-24T01:14:51.113Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/27/1a/1f68f9ba0c207934b35b86a8ca3aad8395a3d6dd7921c0686e23853ff5a9/mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e", size = 7350, upload-time = "2022-01-24T01:14:49.62Z" }, +] + +[[package]] +name = "mdurl" +version = "0.1.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/d6/54/cfe61301667036ec958cb99bd3efefba235e65cdeb9c84d24a8293ba1d90/mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba", size = 8729, upload-time = "2022-08-14T12:40:10.846Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b3/38/89ba8ad64ae25be8de66a6d463314cf1eb366222074cfda9ee839c56a4b4/mdurl-0.1.2-py3-none-any.whl", hash = "sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8", size = 9979, upload-time = "2022-08-14T12:40:09.779Z" }, +] + +[[package]] +name = "mypy-extensions" +version = "1.1.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a2/6e/371856a3fb9d31ca8dac321cda606860fa4548858c0cc45d9d1d4ca2628b/mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558", size = 6343, upload-time = "2025-04-22T14:54:24.164Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, +] + +[[package]] +name = "nodeenv" +version = "1.9.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/43/16/fc88b08840de0e0a72a2f9d8c6bae36be573e475a6326ae854bcc549fc45/nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f", size = 47437, upload-time = "2024-06-04T18:44:11.171Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/1d/1b658dbd2b9fa9c4c9f32accbfc0205d532c8c6194dc0f2a4c0428e7128a/nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9", size = 22314, upload-time = "2024-06-04T18:44:08.352Z" }, +] + +[[package]] +name = "packaging" +version = "25.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a1/d4/1fc4078c65507b51b96ca8f8c3ba19e6a61c8253c72794544580a7b6c24d/packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f", size = 165727, upload-time = "2025-04-19T11:48:59.673Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/20/12/38679034af332785aac8774540895e234f4d07f7545804097de4b666afd8/packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", size = 66469, upload-time = "2025-04-19T11:48:57.875Z" }, +] + +[[package]] +name = "pathlib" +version = "1.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ac/aa/9b065a76b9af472437a0059f77e8f962fe350438b927cb80184c32f075eb/pathlib-1.0.1.tar.gz", hash = "sha256:6940718dfc3eff4258203ad5021090933e5c04707d5ca8cc9e73c94a7894ea9f", size = 49298, upload-time = "2014-09-03T15:41:57.18Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/f9/690a8600b93c332de3ab4a344a4ac34f00c8f104917061f779db6a918ed6/pathlib-1.0.1-py3-none-any.whl", hash = "sha256:f35f95ab8b0f59e6d354090350b44a80a80635d22efdedfa84c7ad1cf0a74147", size = 14363, upload-time = "2022-05-04T13:37:20.585Z" }, +] + +[[package]] +name = "pathspec" +version = "0.12.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/ca/bc/f35b8446f4531a7cb215605d100cd88b7ac6f44ab3fc94870c120ab3adbf/pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712", size = 51043, upload-time = "2023-12-10T22:30:45Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.3.6" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302, upload-time = "2024-09-17T19:06:50.688Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439, upload-time = "2024-09-17T19:06:49.212Z" }, +] + +[[package]] +name = "platformdirs" +version = "4.4.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, +] + +[[package]] +name = "pluggy" +version = "1.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, +] + +[[package]] +name = "pluggy" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, +] + +[[package]] +name = "pre-commit" +version = "3.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "cfgv", marker = "python_full_version < '3.9'" }, + { name = "identify", version = "2.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "nodeenv", marker = "python_full_version < '3.9'" }, + { name = "pyyaml", marker = "python_full_version < '3.9'" }, + { name = "virtualenv", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/b3/4ae08d21eb097162f5aad37f4585f8069a86402ed7f5362cc9ae097f9572/pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32", size = 177079, upload-time = "2023-10-13T15:57:48.334Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/6c/75/526915fedf462e05eeb1c75ceaf7e3f9cde7b5ce6f62740fe5f7f19a0050/pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660", size = 203698, upload-time = "2023-10-13T15:57:46.378Z" }, +] + +[[package]] +name = "pre-commit" +version = "4.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "cfgv", marker = "python_full_version >= '3.9'" }, + { name = "identify", version = "2.6.14", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "nodeenv", marker = "python_full_version >= '3.9'" }, + { name = "pyyaml", marker = "python_full_version >= '3.9'" }, + { name = "virtualenv", marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ff/29/7cf5bbc236333876e4b41f56e06857a87937ce4bf91e117a6991a2dbb02a/pre_commit-4.3.0.tar.gz", hash = "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16", size = 193792, upload-time = "2025-08-09T18:56:14.651Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/5b/a5/987a405322d78a73b66e39e4a90e4ef156fd7141bf71df987e50717c321b/pre_commit-4.3.0-py2.py3-none-any.whl", hash = "sha256:2b0747ad7e6e967169136edffee14c16e148a778a54e4f967921aa1ebf2308d8", size = 220965, upload-time = "2025-08-09T18:56:13.192Z" }, +] + +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + +[[package]] +name = "pycodestyle" +version = "2.9.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/b6/83/5bcaedba1f47200f0665ceb07bcb00e2be123192742ee0edfb66b600e5fd/pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", size = 102127, upload-time = "2022-08-03T23:13:29.715Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/e4/fc77f1039c34b3612c4867b69cbb2b8a4e569720b1f19b0637002ee03aff/pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b", size = 41493, upload-time = "2022-08-03T23:13:27.416Z" }, +] + +[[package]] +name = "pycodestyle" +version = "2.12.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/43/aa/210b2c9aedd8c1cbeea31a50e42050ad56187754b34eb214c46709445801/pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521", size = 39232, upload-time = "2024-08-04T20:26:54.576Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3a/d8/a211b3f85e99a0daa2ddec96c949cac6824bd305b040571b82a03dd62636/pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3", size = 31284, upload-time = "2024-08-04T20:26:53.173Z" }, +] + +[[package]] +name = "pycodestyle" +version = "2.14.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" }, +] + +[[package]] +name = "pyflakes" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/07/92/f0cb5381f752e89a598dd2850941e7f570ac3cb8ea4a344854de486db152/pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3", size = 66388, upload-time = "2022-07-30T17:29:05.816Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/dc/13/63178f59f74e53acc2165aee4b002619a3cfa7eeaeac989a9eb41edf364e/pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", size = 66116, upload-time = "2022-07-30T17:29:04.179Z" }, +] + +[[package]] +name = "pyflakes" +version = "3.2.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", +] +sdist = { url = "https://files.pythonhosted.org/packages/57/f9/669d8c9c86613c9d568757c7f5824bd3197d7b1c6c27553bc5618a27cce2/pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f", size = 63788, upload-time = "2024-01-05T00:28:47.703Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d4/d7/f1b7db88d8e4417c5d47adad627a93547f44bdc9028372dbd2313f34a855/pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a", size = 62725, upload-time = "2024-01-05T00:28:45.903Z" }, +] + +[[package]] +name = "pyflakes" +version = "3.4.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/45/dc/fd034dc20b4b264b3d015808458391acbf9df40b1e54750ef175d39180b1/pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", size = 64669, upload-time = "2025-06-20T18:45:27.834Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" }, +] + +[[package]] +name = "pygments" +version = "2.19.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, +] + +[[package]] +name = "pyrefly" +version = "0.31.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/74/c4/4b45120c1af9698909fb5e771170566959bad43530f2f0ac434674789e14/pyrefly-0.31.1.tar.gz", hash = "sha256:79609735d2683c9fda12b14e74a0643477984216297fc8786086cc29f964901d", size = 1342496, upload-time = "2025-09-05T23:06:50.129Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/49/26/1c8699516f2d67456df729df2996a5957e6f27693db00219252e7be514dd/pyrefly-0.31.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:b251a502a3d7c435361fa66449b0d3eaafd9e5b7bd16802e626ae28fa8972e54", size = 6622774, upload-time = "2025-09-05T23:06:33.592Z" }, + { url = "https://files.pythonhosted.org/packages/b4/fe/1d63007e29494894bee8e56a8e3631f5a1ecdbbf99fce233ebbc5c13e6dc/pyrefly-0.31.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:3f9ca929a9a259c3c2d2d10b7639e68a6ec11f227cf0f5525a53ceb720b065ea", size = 6162225, upload-time = "2025-09-05T23:06:35.841Z" }, + { url = "https://files.pythonhosted.org/packages/19/bc/8f67f8a68b1d35c87b170d8c11619d01d7769c7f206d72954ed80c44c675/pyrefly-0.31.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:68cf8e4b4abbdb0f50919caf1310e82fc7f2b09ba5152bfcedd8fda189b0cf42", size = 6410448, upload-time = "2025-09-05T23:06:38.228Z" }, + { url = "https://files.pythonhosted.org/packages/ee/e6/755de7c249a6a497542f21e61e94b3afbfc096fa480678e87e7c02410b4a/pyrefly-0.31.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3f7c67586f506910248cc410b5232418635604c8cc2f4d61d6432418c6a5647", size = 7204044, upload-time = "2025-09-05T23:06:39.859Z" }, + { url = "https://files.pythonhosted.org/packages/39/be/4ca0a3e8f78357e6846fb367ad00790c74c7bc80928171ce0e34d33aabc8/pyrefly-0.31.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c0d809af388144cb148eb11c6ebc33f8e5c6adafc22a7f0da99d9b555123e42", size = 6890396, upload-time = "2025-09-05T23:06:42.137Z" }, + { url = "https://files.pythonhosted.org/packages/01/1a/9c3381910d51d64a26726c6111ac5a1ee90e5de9e92b4827be352610c5b8/pyrefly-0.31.1-py3-none-win32.whl", hash = "sha256:8bde23e37fb68367b691b7491880e0ce95e150d879fe43e3a86e78f3cf911a23", size = 6383610, upload-time = "2025-09-05T23:06:44.159Z" }, + { url = "https://files.pythonhosted.org/packages/c4/ab/f99cf8f7acebc0ddf0718ca4f33786e78353019903e5888de133c67863f5/pyrefly-0.31.1-py3-none-win_amd64.whl", hash = "sha256:bec49618d2574ccd200de515480c4b60740926f3a7a4b1804fdae49b72665719", size = 6800276, upload-time = "2025-09-05T23:06:46.071Z" }, + { url = "https://files.pythonhosted.org/packages/02/53/b02648724846a3bd676410261f2d980a260a16e337fe978028429fc712d1/pyrefly-0.31.1-py3-none-win_arm64.whl", hash = "sha256:370d2b7fab9cab0de937f44638cf6666322e27b6d2c84c4b82cba0e868c6d437", size = 6421184, upload-time = "2025-09-05T23:06:48.218Z" }, +] + +[[package]] +name = "pytest" +version = "8.3.5" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.9' and sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.9'" }, + { name = "iniconfig", marker = "python_full_version < '3.9'" }, + { name = "packaging", marker = "python_full_version < '3.9'" }, + { name = "pluggy", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "tomli", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, +] + +[[package]] +name = "pytest" +version = "8.4.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.9' and sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "iniconfig", marker = "python_full_version >= '3.9'" }, + { name = "packaging", marker = "python_full_version >= '3.9'" }, + { name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pygments", marker = "python_full_version >= '3.9'" }, + { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, +] + +[[package]] +name = "pytest-cov" +version = "5.0.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "coverage", version = "7.6.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.9'" }, + { name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/74/67/00efc8d11b630c56f15f4ad9c7f9223f1e5ec275aaae3fa9118c6a223ad2/pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857", size = 63042, upload-time = "2024-03-24T20:16:34.856Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652", size = 21990, upload-time = "2024-03-24T20:16:32.444Z" }, +] + +[[package]] +name = "pytest-cov" +version = "6.3.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "coverage", version = "7.10.6", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.9'" }, + { name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/30/4c/f883ab8f0daad69f47efdf95f55a66b51a8b939c430dadce0611508d9e99/pytest_cov-6.3.0.tar.gz", hash = "sha256:35c580e7800f87ce892e687461166e1ac2bcb8fb9e13aea79032518d6e503ff2", size = 70398, upload-time = "2025-09-06T15:40:14.361Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/80/b4/bb7263e12aade3842b938bc5c6958cae79c5ee18992f9b9349019579da0f/pytest_cov-6.3.0-py3-none-any.whl", hash = "sha256:440db28156d2468cafc0415b4f8e50856a0d11faefa38f30906048fe490f1749", size = 25115, upload-time = "2025-09-06T15:40:12.44Z" }, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/54/ed/79a089b6be93607fa5cdaedf301d7dfb23af5f25c398d5ead2525b063e17/pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", size = 130631, upload-time = "2024-08-06T20:33:50.674Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/95/a3fac87cb7158e231b5a6012e438c647e1a87f09f8e0d123acec8ab8bf71/PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", size = 184199, upload-time = "2024-08-06T20:31:40.178Z" }, + { url = "https://files.pythonhosted.org/packages/c7/7a/68bd47624dab8fd4afbfd3c48e3b79efe09098ae941de5b58abcbadff5cb/PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", size = 171758, upload-time = "2024-08-06T20:31:42.173Z" }, + { url = "https://files.pythonhosted.org/packages/49/ee/14c54df452143b9ee9f0f29074d7ca5516a36edb0b4cc40c3f280131656f/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", size = 718463, upload-time = "2024-08-06T20:31:44.263Z" }, + { url = "https://files.pythonhosted.org/packages/4d/61/de363a97476e766574650d742205be468921a7b532aa2499fcd886b62530/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", size = 719280, upload-time = "2024-08-06T20:31:50.199Z" }, + { url = "https://files.pythonhosted.org/packages/6b/4e/1523cb902fd98355e2e9ea5e5eb237cbc5f3ad5f3075fa65087aa0ecb669/PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", size = 751239, upload-time = "2024-08-06T20:31:52.292Z" }, + { url = "https://files.pythonhosted.org/packages/b7/33/5504b3a9a4464893c32f118a9cc045190a91637b119a9c881da1cf6b7a72/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", size = 695802, upload-time = "2024-08-06T20:31:53.836Z" }, + { url = "https://files.pythonhosted.org/packages/5c/20/8347dcabd41ef3a3cdc4f7b7a2aff3d06598c8779faa189cdbf878b626a4/PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", size = 720527, upload-time = "2024-08-06T20:31:55.565Z" }, + { url = "https://files.pythonhosted.org/packages/be/aa/5afe99233fb360d0ff37377145a949ae258aaab831bde4792b32650a4378/PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", size = 144052, upload-time = "2024-08-06T20:31:56.914Z" }, + { url = "https://files.pythonhosted.org/packages/b5/84/0fa4b06f6d6c958d207620fc60005e241ecedceee58931bb20138e1e5776/PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", size = 161774, upload-time = "2024-08-06T20:31:58.304Z" }, + { url = "https://files.pythonhosted.org/packages/f8/aa/7af4e81f7acba21a4c6be026da38fd2b872ca46226673c89a758ebdc4fd2/PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", size = 184612, upload-time = "2024-08-06T20:32:03.408Z" }, + { url = "https://files.pythonhosted.org/packages/8b/62/b9faa998fd185f65c1371643678e4d58254add437edb764a08c5a98fb986/PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", size = 172040, upload-time = "2024-08-06T20:32:04.926Z" }, + { url = "https://files.pythonhosted.org/packages/ad/0c/c804f5f922a9a6563bab712d8dcc70251e8af811fce4524d57c2c0fd49a4/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", size = 736829, upload-time = "2024-08-06T20:32:06.459Z" }, + { url = "https://files.pythonhosted.org/packages/51/16/6af8d6a6b210c8e54f1406a6b9481febf9c64a3109c541567e35a49aa2e7/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", size = 764167, upload-time = "2024-08-06T20:32:08.338Z" }, + { url = "https://files.pythonhosted.org/packages/75/e4/2c27590dfc9992f73aabbeb9241ae20220bd9452df27483b6e56d3975cc5/PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", size = 762952, upload-time = "2024-08-06T20:32:14.124Z" }, + { url = "https://files.pythonhosted.org/packages/9b/97/ecc1abf4a823f5ac61941a9c00fe501b02ac3ab0e373c3857f7d4b83e2b6/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4", size = 735301, upload-time = "2024-08-06T20:32:16.17Z" }, + { url = "https://files.pythonhosted.org/packages/45/73/0f49dacd6e82c9430e46f4a027baa4ca205e8b0a9dce1397f44edc23559d/PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", size = 756638, upload-time = "2024-08-06T20:32:18.555Z" }, + { url = "https://files.pythonhosted.org/packages/22/5f/956f0f9fc65223a58fbc14459bf34b4cc48dec52e00535c79b8db361aabd/PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", size = 143850, upload-time = "2024-08-06T20:32:19.889Z" }, + { url = "https://files.pythonhosted.org/packages/ed/23/8da0bbe2ab9dcdd11f4f4557ccaf95c10b9811b13ecced089d43ce59c3c8/PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", size = 161980, upload-time = "2024-08-06T20:32:21.273Z" }, + { url = "https://files.pythonhosted.org/packages/86/0c/c581167fc46d6d6d7ddcfb8c843a4de25bdd27e4466938109ca68492292c/PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", size = 183873, upload-time = "2024-08-06T20:32:25.131Z" }, + { url = "https://files.pythonhosted.org/packages/a8/0c/38374f5bb272c051e2a69281d71cba6fdb983413e6758b84482905e29a5d/PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", size = 173302, upload-time = "2024-08-06T20:32:26.511Z" }, + { url = "https://files.pythonhosted.org/packages/c3/93/9916574aa8c00aa06bbac729972eb1071d002b8e158bd0e83a3b9a20a1f7/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", size = 739154, upload-time = "2024-08-06T20:32:28.363Z" }, + { url = "https://files.pythonhosted.org/packages/95/0f/b8938f1cbd09739c6da569d172531567dbcc9789e0029aa070856f123984/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", size = 766223, upload-time = "2024-08-06T20:32:30.058Z" }, + { url = "https://files.pythonhosted.org/packages/b9/2b/614b4752f2e127db5cc206abc23a8c19678e92b23c3db30fc86ab731d3bd/PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", size = 767542, upload-time = "2024-08-06T20:32:31.881Z" }, + { url = "https://files.pythonhosted.org/packages/d4/00/dd137d5bcc7efea1836d6264f049359861cf548469d18da90cd8216cf05f/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", size = 731164, upload-time = "2024-08-06T20:32:37.083Z" }, + { url = "https://files.pythonhosted.org/packages/c9/1f/4f998c900485e5c0ef43838363ba4a9723ac0ad73a9dc42068b12aaba4e4/PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", size = 756611, upload-time = "2024-08-06T20:32:38.898Z" }, + { url = "https://files.pythonhosted.org/packages/df/d1/f5a275fdb252768b7a11ec63585bc38d0e87c9e05668a139fea92b80634c/PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", size = 140591, upload-time = "2024-08-06T20:32:40.241Z" }, + { url = "https://files.pythonhosted.org/packages/0c/e8/4f648c598b17c3d06e8753d7d13d57542b30d56e6c2dedf9c331ae56312e/PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", size = 156338, upload-time = "2024-08-06T20:32:41.93Z" }, + { url = "https://files.pythonhosted.org/packages/ef/e3/3af305b830494fa85d95f6d95ef7fa73f2ee1cc8ef5b495c7c3269fb835f/PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", size = 181309, upload-time = "2024-08-06T20:32:43.4Z" }, + { url = "https://files.pythonhosted.org/packages/45/9f/3b1c20a0b7a3200524eb0076cc027a970d320bd3a6592873c85c92a08731/PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", size = 171679, upload-time = "2024-08-06T20:32:44.801Z" }, + { url = "https://files.pythonhosted.org/packages/7c/9a/337322f27005c33bcb656c655fa78325b730324c78620e8328ae28b64d0c/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", size = 733428, upload-time = "2024-08-06T20:32:46.432Z" }, + { url = "https://files.pythonhosted.org/packages/a3/69/864fbe19e6c18ea3cc196cbe5d392175b4cf3d5d0ac1403ec3f2d237ebb5/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", size = 763361, upload-time = "2024-08-06T20:32:51.188Z" }, + { url = "https://files.pythonhosted.org/packages/04/24/b7721e4845c2f162d26f50521b825fb061bc0a5afcf9a386840f23ea19fa/PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", size = 759523, upload-time = "2024-08-06T20:32:53.019Z" }, + { url = "https://files.pythonhosted.org/packages/2b/b2/e3234f59ba06559c6ff63c4e10baea10e5e7df868092bf9ab40e5b9c56b6/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", size = 726660, upload-time = "2024-08-06T20:32:54.708Z" }, + { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, + { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, + { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, + { url = "https://files.pythonhosted.org/packages/74/d9/323a59d506f12f498c2097488d80d16f4cf965cee1791eab58b56b19f47a/PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", size = 183218, upload-time = "2024-08-06T20:33:06.411Z" }, + { url = "https://files.pythonhosted.org/packages/74/cc/20c34d00f04d785f2028737e2e2a8254e1425102e730fee1d6396f832577/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", size = 728067, upload-time = "2024-08-06T20:33:07.879Z" }, + { url = "https://files.pythonhosted.org/packages/20/52/551c69ca1501d21c0de51ddafa8c23a0191ef296ff098e98358f69080577/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", size = 757812, upload-time = "2024-08-06T20:33:12.542Z" }, + { url = "https://files.pythonhosted.org/packages/fd/7f/2c3697bba5d4aa5cc2afe81826d73dfae5f049458e44732c7a0938baa673/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", size = 746531, upload-time = "2024-08-06T20:33:14.391Z" }, + { url = "https://files.pythonhosted.org/packages/8c/ab/6226d3df99900e580091bb44258fde77a8433511a86883bd4681ea19a858/PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", size = 800820, upload-time = "2024-08-06T20:33:16.586Z" }, + { url = "https://files.pythonhosted.org/packages/a0/99/a9eb0f3e710c06c5d922026f6736e920d431812ace24aae38228d0d64b04/PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", size = 145514, upload-time = "2024-08-06T20:33:22.414Z" }, + { url = "https://files.pythonhosted.org/packages/75/8a/ee831ad5fafa4431099aa4e078d4c8efd43cd5e48fbc774641d233b683a9/PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", size = 162702, upload-time = "2024-08-06T20:33:23.813Z" }, + { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777, upload-time = "2024-08-06T20:33:25.896Z" }, + { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318, upload-time = "2024-08-06T20:33:27.212Z" }, + { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891, upload-time = "2024-08-06T20:33:28.974Z" }, + { url = "https://files.pythonhosted.org/packages/e9/6c/6e1b7f40181bc4805e2e07f4abc10a88ce4648e7e95ff1abe4ae4014a9b2/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", size = 722614, upload-time = "2024-08-06T20:33:34.157Z" }, + { url = "https://files.pythonhosted.org/packages/3d/32/e7bd8535d22ea2874cef6a81021ba019474ace0d13a4819c2a4bce79bd6a/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", size = 737360, upload-time = "2024-08-06T20:33:35.84Z" }, + { url = "https://files.pythonhosted.org/packages/d7/12/7322c1e30b9be969670b672573d45479edef72c9a0deac3bb2868f5d7469/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", size = 699006, upload-time = "2024-08-06T20:33:37.501Z" }, + { url = "https://files.pythonhosted.org/packages/82/72/04fcad41ca56491995076630c3ec1e834be241664c0c09a64c9a2589b507/PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", size = 723577, upload-time = "2024-08-06T20:33:39.389Z" }, + { url = "https://files.pythonhosted.org/packages/ed/5e/46168b1f2757f1fcd442bc3029cd8767d88a98c9c05770d8b420948743bb/PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", size = 144593, upload-time = "2024-08-06T20:33:46.63Z" }, + { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312, upload-time = "2024-08-06T20:33:49.073Z" }, +] + +[[package]] +name = "questionary" +version = "2.1.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "prompt-toolkit", marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a8/b8/d16eb579277f3de9e56e5ad25280fab52fc5774117fb70362e8c2e016559/questionary-2.1.0.tar.gz", hash = "sha256:6302cdd645b19667d8f6e6634774e9538bfcd1aad9be287e743d96cacaf95587", size = 26775, upload-time = "2024-12-29T11:49:17.802Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ad/3f/11dd4cd4f39e05128bfd20138faea57bec56f9ffba6185d276e3107ba5b2/questionary-2.1.0-py3-none-any.whl", hash = "sha256:44174d237b68bc828e4878c763a9ad6790ee61990e0ae72927694ead57bab8ec", size = 36747, upload-time = "2024-12-29T11:49:16.734Z" }, +] + +[[package]] +name = "questionary" +version = "2.1.1" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "prompt-toolkit", marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/45/eafb0bba0f9988f6a2520f9ca2df2c82ddfa8d67c95d6625452e97b204a5/questionary-2.1.1.tar.gz", hash = "sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d", size = 25845, upload-time = "2025-08-28T19:00:20.851Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59", size = 36753, upload-time = "2025-08-28T19:00:19.56Z" }, +] + +[[package]] +name = "requests" +version = "2.32.4" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +dependencies = [ + { name = "certifi", marker = "python_full_version < '3.9'" }, + { name = "charset-normalizer", marker = "python_full_version < '3.9'" }, + { name = "idna", marker = "python_full_version < '3.9'" }, + { name = "urllib3", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, +] + +[[package]] +name = "requests" +version = "2.32.5" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +dependencies = [ + { name = "certifi", marker = "python_full_version >= '3.9'" }, + { name = "charset-normalizer", marker = "python_full_version >= '3.9'" }, + { name = "idna", marker = "python_full_version >= '3.9'" }, + { name = "urllib3", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/1e/db/4254e3eabe8020b458f1a747140d32277ec7a271daf1d235b70dc0b4e6e3/requests-2.32.5-py3-none-any.whl", hash = "sha256:2462f94637a34fd532264295e186976db0f5d453d1cdd31473c85a6a161affb6", size = 64738, upload-time = "2025-08-18T20:46:00.542Z" }, +] + +[[package]] +name = "rich" +version = "14.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "markdown-it-py", version = "3.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "markdown-it-py", version = "4.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "pygments" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/fe/75/af448d8e52bf1d8fa6a9d089ca6c07ff4453d86c65c145d0a300bb073b9b/rich-14.1.0.tar.gz", hash = "sha256:e497a48b844b0320d45007cdebfeaeed8db2a4f4bcf49f15e455cfc4af11eaa8", size = 224441, upload-time = "2025-07-25T07:32:58.125Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e3/30/3c4d035596d3cf444529e0b2953ad0466f6049528a879d27534700580395/rich-14.1.0-py3-none-any.whl", hash = "sha256:536f5f1785986d6dbdea3c75205c473f970777b4a0d6c6dd1b696aa05a3fa04f", size = 243368, upload-time = "2025-07-25T07:32:56.73Z" }, +] + +[[package]] +name = "ruff" +version = "0.12.12" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/a8/f0/e0965dd709b8cabe6356811c0ee8c096806bb57d20b5019eb4e48a117410/ruff-0.12.12.tar.gz", hash = "sha256:b86cd3415dbe31b3b46a71c598f4c4b2f550346d1ccf6326b347cc0c8fd063d6", size = 5359915, upload-time = "2025-09-04T16:50:18.273Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/09/79/8d3d687224d88367b51c7974cec1040c4b015772bfbeffac95face14c04a/ruff-0.12.12-py3-none-linux_armv6l.whl", hash = "sha256:de1c4b916d98ab289818e55ce481e2cacfaad7710b01d1f990c497edf217dafc", size = 12116602, upload-time = "2025-09-04T16:49:18.892Z" }, + { url = "https://files.pythonhosted.org/packages/c3/c3/6e599657fe192462f94861a09aae935b869aea8a1da07f47d6eae471397c/ruff-0.12.12-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:7acd6045e87fac75a0b0cdedacf9ab3e1ad9d929d149785903cff9bb69ad9727", size = 12868393, upload-time = "2025-09-04T16:49:23.043Z" }, + { url = "https://files.pythonhosted.org/packages/e8/d2/9e3e40d399abc95336b1843f52fc0daaceb672d0e3c9290a28ff1a96f79d/ruff-0.12.12-py3-none-macosx_11_0_arm64.whl", hash = "sha256:abf4073688d7d6da16611f2f126be86523a8ec4343d15d276c614bda8ec44edb", size = 12036967, upload-time = "2025-09-04T16:49:26.04Z" }, + { url = "https://files.pythonhosted.org/packages/e9/03/6816b2ed08836be272e87107d905f0908be5b4a40c14bfc91043e76631b8/ruff-0.12.12-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:968e77094b1d7a576992ac078557d1439df678a34c6fe02fd979f973af167577", size = 12276038, upload-time = "2025-09-04T16:49:29.056Z" }, + { url = "https://files.pythonhosted.org/packages/9f/d5/707b92a61310edf358a389477eabd8af68f375c0ef858194be97ca5b6069/ruff-0.12.12-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:42a67d16e5b1ffc6d21c5f67851e0e769517fb57a8ebad1d0781b30888aa704e", size = 11901110, upload-time = "2025-09-04T16:49:32.07Z" }, + { url = "https://files.pythonhosted.org/packages/9d/3d/f8b1038f4b9822e26ec3d5b49cf2bc313e3c1564cceb4c1a42820bf74853/ruff-0.12.12-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b216ec0a0674e4b1214dcc998a5088e54eaf39417327b19ffefba1c4a1e4971e", size = 13668352, upload-time = "2025-09-04T16:49:35.148Z" }, + { url = "https://files.pythonhosted.org/packages/98/0e/91421368ae6c4f3765dd41a150f760c5f725516028a6be30e58255e3c668/ruff-0.12.12-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:59f909c0fdd8f1dcdbfed0b9569b8bf428cf144bec87d9de298dcd4723f5bee8", size = 14638365, upload-time = "2025-09-04T16:49:38.892Z" }, + { url = "https://files.pythonhosted.org/packages/74/5d/88f3f06a142f58ecc8ecb0c2fe0b82343e2a2b04dcd098809f717cf74b6c/ruff-0.12.12-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9ac93d87047e765336f0c18eacad51dad0c1c33c9df7484c40f98e1d773876f5", size = 14060812, upload-time = "2025-09-04T16:49:42.732Z" }, + { url = "https://files.pythonhosted.org/packages/13/fc/8962e7ddd2e81863d5c92400820f650b86f97ff919c59836fbc4c1a6d84c/ruff-0.12.12-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:01543c137fd3650d322922e8b14cc133b8ea734617c4891c5a9fccf4bfc9aa92", size = 13050208, upload-time = "2025-09-04T16:49:46.434Z" }, + { url = "https://files.pythonhosted.org/packages/53/06/8deb52d48a9a624fd37390555d9589e719eac568c020b27e96eed671f25f/ruff-0.12.12-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2afc2fa864197634e549d87fb1e7b6feb01df0a80fd510d6489e1ce8c0b1cc45", size = 13311444, upload-time = "2025-09-04T16:49:49.931Z" }, + { url = "https://files.pythonhosted.org/packages/2a/81/de5a29af7eb8f341f8140867ffb93f82e4fde7256dadee79016ac87c2716/ruff-0.12.12-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:0c0945246f5ad776cb8925e36af2438e66188d2b57d9cf2eed2c382c58b371e5", size = 13279474, upload-time = "2025-09-04T16:49:53.465Z" }, + { url = "https://files.pythonhosted.org/packages/7f/14/d9577fdeaf791737ada1b4f5c6b59c21c3326f3f683229096cccd7674e0c/ruff-0.12.12-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a0fbafe8c58e37aae28b84a80ba1817f2ea552e9450156018a478bf1fa80f4e4", size = 12070204, upload-time = "2025-09-04T16:49:56.882Z" }, + { url = "https://files.pythonhosted.org/packages/77/04/a910078284b47fad54506dc0af13839c418ff704e341c176f64e1127e461/ruff-0.12.12-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b9c456fb2fc8e1282affa932c9e40f5ec31ec9cbb66751a316bd131273b57c23", size = 11880347, upload-time = "2025-09-04T16:49:59.729Z" }, + { url = "https://files.pythonhosted.org/packages/df/58/30185fcb0e89f05e7ea82e5817b47798f7fa7179863f9d9ba6fd4fe1b098/ruff-0.12.12-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5f12856123b0ad0147d90b3961f5c90e7427f9acd4b40050705499c98983f489", size = 12891844, upload-time = "2025-09-04T16:50:02.591Z" }, + { url = "https://files.pythonhosted.org/packages/21/9c/28a8dacce4855e6703dcb8cdf6c1705d0b23dd01d60150786cd55aa93b16/ruff-0.12.12-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:26a1b5a2bf7dd2c47e3b46d077cd9c0fc3b93e6c6cc9ed750bd312ae9dc302ee", size = 13360687, upload-time = "2025-09-04T16:50:05.8Z" }, + { url = "https://files.pythonhosted.org/packages/c8/fa/05b6428a008e60f79546c943e54068316f32ec8ab5c4f73e4563934fbdc7/ruff-0.12.12-py3-none-win32.whl", hash = "sha256:173be2bfc142af07a01e3a759aba6f7791aa47acf3604f610b1c36db888df7b1", size = 12052870, upload-time = "2025-09-04T16:50:09.121Z" }, + { url = "https://files.pythonhosted.org/packages/85/60/d1e335417804df452589271818749d061b22772b87efda88354cf35cdb7a/ruff-0.12.12-py3-none-win_amd64.whl", hash = "sha256:e99620bf01884e5f38611934c09dd194eb665b0109104acae3ba6102b600fd0d", size = 13178016, upload-time = "2025-09-04T16:50:12.559Z" }, + { url = "https://files.pythonhosted.org/packages/28/7e/61c42657f6e4614a4258f1c3b0c5b93adc4d1f8575f5229d1906b483099b/ruff-0.12.12-py3-none-win_arm64.whl", hash = "sha256:2a8199cab4ce4d72d158319b63370abf60991495fb733db96cd923a34c52d093", size = 12256762, upload-time = "2025-09-04T16:50:15.737Z" }, +] + +[[package]] +name = "shellingham" +version = "1.5.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/58/15/8b3609fd3830ef7b27b655beb4b4e9c62313a4e8da8c676e142cc210d58e/shellingham-1.5.4.tar.gz", hash = "sha256:8dbca0739d487e5bd35ab3ca4b36e11c4078f3a234bfce294b0a0291363404de", size = 10310, upload-time = "2023-10-24T04:13:40.426Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e0/f9/0595336914c5619e5f28a1fb793285925a8cd4b432c9da0a987836c7f822/shellingham-1.5.4-py2.py3-none-any.whl", hash = "sha256:7ecfff8f2fd72616f7481040475a65b2bf8af90a56c89140852d1120324e8686", size = 9755, upload-time = "2023-10-24T04:13:38.866Z" }, +] + +[[package]] +name = "tomli" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/18/87/302344fed471e44a87289cf4967697d07e532f2421fdaf868a303cbae4ff/tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff", size = 17175, upload-time = "2024-11-27T22:38:36.873Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/43/ca/75707e6efa2b37c77dadb324ae7d9571cb424e61ea73fad7c56c2d14527f/tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249", size = 131077, upload-time = "2024-11-27T22:37:54.956Z" }, + { url = "https://files.pythonhosted.org/packages/c7/16/51ae563a8615d472fdbffc43a3f3d46588c264ac4f024f63f01283becfbb/tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6", size = 123429, upload-time = "2024-11-27T22:37:56.698Z" }, + { url = "https://files.pythonhosted.org/packages/f1/dd/4f6cd1e7b160041db83c694abc78e100473c15d54620083dbd5aae7b990e/tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a", size = 226067, upload-time = "2024-11-27T22:37:57.63Z" }, + { url = "https://files.pythonhosted.org/packages/a9/6b/c54ede5dc70d648cc6361eaf429304b02f2871a345bbdd51e993d6cdf550/tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee", size = 236030, upload-time = "2024-11-27T22:37:59.344Z" }, + { url = "https://files.pythonhosted.org/packages/1f/47/999514fa49cfaf7a92c805a86c3c43f4215621855d151b61c602abb38091/tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e", size = 240898, upload-time = "2024-11-27T22:38:00.429Z" }, + { url = "https://files.pythonhosted.org/packages/73/41/0a01279a7ae09ee1573b423318e7934674ce06eb33f50936655071d81a24/tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4", size = 229894, upload-time = "2024-11-27T22:38:02.094Z" }, + { url = "https://files.pythonhosted.org/packages/55/18/5d8bc5b0a0362311ce4d18830a5d28943667599a60d20118074ea1b01bb7/tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106", size = 245319, upload-time = "2024-11-27T22:38:03.206Z" }, + { url = "https://files.pythonhosted.org/packages/92/a3/7ade0576d17f3cdf5ff44d61390d4b3febb8a9fc2b480c75c47ea048c646/tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8", size = 238273, upload-time = "2024-11-27T22:38:04.217Z" }, + { url = "https://files.pythonhosted.org/packages/72/6f/fa64ef058ac1446a1e51110c375339b3ec6be245af9d14c87c4a6412dd32/tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff", size = 98310, upload-time = "2024-11-27T22:38:05.908Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1c/4a2dcde4a51b81be3530565e92eda625d94dafb46dbeb15069df4caffc34/tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b", size = 108309, upload-time = "2024-11-27T22:38:06.812Z" }, + { url = "https://files.pythonhosted.org/packages/52/e1/f8af4c2fcde17500422858155aeb0d7e93477a0d59a98e56cbfe75070fd0/tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea", size = 132762, upload-time = "2024-11-27T22:38:07.731Z" }, + { url = "https://files.pythonhosted.org/packages/03/b8/152c68bb84fc00396b83e7bbddd5ec0bd3dd409db4195e2a9b3e398ad2e3/tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8", size = 123453, upload-time = "2024-11-27T22:38:09.384Z" }, + { url = "https://files.pythonhosted.org/packages/c8/d6/fc9267af9166f79ac528ff7e8c55c8181ded34eb4b0e93daa767b8841573/tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192", size = 233486, upload-time = "2024-11-27T22:38:10.329Z" }, + { url = "https://files.pythonhosted.org/packages/5c/51/51c3f2884d7bab89af25f678447ea7d297b53b5a3b5730a7cb2ef6069f07/tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222", size = 242349, upload-time = "2024-11-27T22:38:11.443Z" }, + { url = "https://files.pythonhosted.org/packages/ab/df/bfa89627d13a5cc22402e441e8a931ef2108403db390ff3345c05253935e/tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77", size = 252159, upload-time = "2024-11-27T22:38:13.099Z" }, + { url = "https://files.pythonhosted.org/packages/9e/6e/fa2b916dced65763a5168c6ccb91066f7639bdc88b48adda990db10c8c0b/tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6", size = 237243, upload-time = "2024-11-27T22:38:14.766Z" }, + { url = "https://files.pythonhosted.org/packages/b4/04/885d3b1f650e1153cbb93a6a9782c58a972b94ea4483ae4ac5cedd5e4a09/tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd", size = 259645, upload-time = "2024-11-27T22:38:15.843Z" }, + { url = "https://files.pythonhosted.org/packages/9c/de/6b432d66e986e501586da298e28ebeefd3edc2c780f3ad73d22566034239/tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e", size = 244584, upload-time = "2024-11-27T22:38:17.645Z" }, + { url = "https://files.pythonhosted.org/packages/1c/9a/47c0449b98e6e7d1be6cbac02f93dd79003234ddc4aaab6ba07a9a7482e2/tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98", size = 98875, upload-time = "2024-11-27T22:38:19.159Z" }, + { url = "https://files.pythonhosted.org/packages/ef/60/9b9638f081c6f1261e2688bd487625cd1e660d0a85bd469e91d8db969734/tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4", size = 109418, upload-time = "2024-11-27T22:38:20.064Z" }, + { url = "https://files.pythonhosted.org/packages/04/90/2ee5f2e0362cb8a0b6499dc44f4d7d48f8fff06d28ba46e6f1eaa61a1388/tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7", size = 132708, upload-time = "2024-11-27T22:38:21.659Z" }, + { url = "https://files.pythonhosted.org/packages/c0/ec/46b4108816de6b385141f082ba99e315501ccd0a2ea23db4a100dd3990ea/tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c", size = 123582, upload-time = "2024-11-27T22:38:22.693Z" }, + { url = "https://files.pythonhosted.org/packages/a0/bd/b470466d0137b37b68d24556c38a0cc819e8febe392d5b199dcd7f578365/tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13", size = 232543, upload-time = "2024-11-27T22:38:24.367Z" }, + { url = "https://files.pythonhosted.org/packages/d9/e5/82e80ff3b751373f7cead2815bcbe2d51c895b3c990686741a8e56ec42ab/tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281", size = 241691, upload-time = "2024-11-27T22:38:26.081Z" }, + { url = "https://files.pythonhosted.org/packages/05/7e/2a110bc2713557d6a1bfb06af23dd01e7dde52b6ee7dadc589868f9abfac/tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272", size = 251170, upload-time = "2024-11-27T22:38:27.921Z" }, + { url = "https://files.pythonhosted.org/packages/64/7b/22d713946efe00e0adbcdfd6d1aa119ae03fd0b60ebed51ebb3fa9f5a2e5/tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140", size = 236530, upload-time = "2024-11-27T22:38:29.591Z" }, + { url = "https://files.pythonhosted.org/packages/38/31/3a76f67da4b0cf37b742ca76beaf819dca0ebef26d78fc794a576e08accf/tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2", size = 258666, upload-time = "2024-11-27T22:38:30.639Z" }, + { url = "https://files.pythonhosted.org/packages/07/10/5af1293da642aded87e8a988753945d0cf7e00a9452d3911dd3bb354c9e2/tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744", size = 243954, upload-time = "2024-11-27T22:38:31.702Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b9/1ed31d167be802da0fc95020d04cd27b7d7065cc6fbefdd2f9186f60d7bd/tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec", size = 98724, upload-time = "2024-11-27T22:38:32.837Z" }, + { url = "https://files.pythonhosted.org/packages/c7/32/b0963458706accd9afcfeb867c0f9175a741bf7b19cd424230714d722198/tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69", size = 109383, upload-time = "2024-11-27T22:38:34.455Z" }, + { url = "https://files.pythonhosted.org/packages/6e/c2/61d3e0f47e2b74ef40a68b9e6ad5984f6241a942f7cd3bbfbdbd03861ea9/tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc", size = 14257, upload-time = "2024-11-27T22:38:35.385Z" }, +] + +[[package]] +name = "typer" +version = "0.17.4" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, + { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, + { name = "rich" }, + { name = "shellingham" }, + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/92/e8/2a73ccf9874ec4c7638f172efc8972ceab13a0e3480b389d6ed822f7a822/typer-0.17.4.tar.gz", hash = "sha256:b77dc07d849312fd2bb5e7f20a7af8985c7ec360c45b051ed5412f64d8dc1580", size = 103734, upload-time = "2025-09-05T18:14:40.746Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/72/6b3e70d32e89a5cbb6a4513726c1ae8762165b027af569289e19ec08edd8/typer-0.17.4-py3-none-any.whl", hash = "sha256:015534a6edaa450e7007eba705d5c18c3349dcea50a6ad79a5ed530967575824", size = 46643, upload-time = "2025-09-05T18:14:39.166Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.13.2" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, +] + +[[package]] +name = "typing-extensions" +version = "4.15.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, +] + +[[package]] +name = "urllib3" +version = "2.2.3" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.8.1' and python_full_version < '3.9'", + "python_full_version < '3.8.1'", +] +sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677, upload-time = "2024-09-12T10:52:18.401Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338, upload-time = "2024-09-12T10:52:16.589Z" }, +] + +[[package]] +name = "urllib3" +version = "2.5.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version >= '3.10'", + "python_full_version == '3.9.*'", +] +sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, +] + +[[package]] +name = "virtualenv" +version = "20.34.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "distlib" }, + { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "filelock", version = "3.19.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "platformdirs", version = "4.3.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/1c/14/37fcdba2808a6c615681cd216fecae00413c9dab44fb2e57805ecf3eaee3/virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a", size = 6003808, upload-time = "2025-08-13T14:24:07.464Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/76/06/04c8e804f813cf972e3262f3f8584c232de64f0cde9f703b46cf53a45090/virtualenv-20.34.0-py3-none-any.whl", hash = "sha256:341f5afa7eee943e4984a9207c025feedd768baff6753cd660c857ceb3e36026", size = 5983279, upload-time = "2025-08-13T14:24:05.111Z" }, +] + +[[package]] +name = "wcwidth" +version = "0.2.13" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/6c/63/53559446a878410fc5a5974feb13d31d78d752eb18aeba59c7fef1af7598/wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5", size = 101301, upload-time = "2024-01-06T02:10:57.829Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/fd/84/fd2ba7aafacbad3c4201d395674fc6348826569da3c0937e75505ead3528/wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", size = 34166, upload-time = "2024-01-06T02:10:55.763Z" }, +] From 7c13549203f5af95a13e7ee9aae97f8be252f7a3 Mon Sep 17 00:00:00 2001 From: barisgit Date: Sun, 7 Sep 2025 22:15:14 +0200 Subject: [PATCH 06/13] Show banner with help --- kicad_lib_manager/main.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/kicad_lib_manager/main.py b/kicad_lib_manager/main.py index 4dc47e1..97a95a7 100644 --- a/kicad_lib_manager/main.py +++ b/kicad_lib_manager/main.py @@ -7,8 +7,11 @@ from typing import Annotated, Optional import typer +from rich.align import Align from rich.console import Console +from rich.text import Text from rich.traceback import install +from typer.core import TyperGroup from .commands.init import init_app from .commands.list_libraries import list_app @@ -16,12 +19,27 @@ from .commands.status import status_app from .utils.banner import show_banner +TAGLINE = "Professional KiCad library management" + # Install rich traceback handler for better error display install(show_locals=True) # Initialize Rich console console = Console() + +class BannerGroup(TyperGroup): + """Custom group that shows banner before help.""" + + def format_help(self, ctx, formatter): + # Show banner before help + show_banner(console, justify="center") + console.print() + console.print(Align.center(Text(TAGLINE, style="italic bright_yellow"))) + console.print() + super().format_help(ctx, formatter) + + # Create main Typer app app = typer.Typer( name="kilm", @@ -31,6 +49,7 @@ pretty_exceptions_enable=True, pretty_exceptions_show_locals=False, invoke_without_command=True, + cls=BannerGroup, ) @@ -72,8 +91,9 @@ def main( """ # Show banner when no arguments are provided, centered show_banner(console) - console.print() # Add blank line after banner - + console.print() + console.print(Align.center(Text(TAGLINE, style="italic bright_yellow"))) + console.print() console.print("[dim]Use 'kilm --help' to see all commands.[/dim]", justify="center") From 22dbb0cca28ccdc34dc64166b8ebcff82b577455 Mon Sep 17 00:00:00 2001 From: barisgit Date: Sun, 7 Sep 2025 23:42:08 +0200 Subject: [PATCH 07/13] Add unpin and setup commands --- kicad_lib_manager/commands/setup/__init__.py | 13 +- kicad_lib_manager/commands/setup/command.py | 258 +++++++++---------- kicad_lib_manager/commands/unpin/__init__.py | 13 +- kicad_lib_manager/commands/unpin/command.py | 171 ++++++------ kicad_lib_manager/main.py | 21 +- 5 files changed, 251 insertions(+), 225 deletions(-) diff --git a/kicad_lib_manager/commands/setup/__init__.py b/kicad_lib_manager/commands/setup/__init__.py index 9142379..f409e05 100644 --- a/kicad_lib_manager/commands/setup/__init__.py +++ b/kicad_lib_manager/commands/setup/__init__.py @@ -1,3 +1,14 @@ +import typer + from .command import setup -__all__ = ["setup"] +# Create Typer app and add the setup command as callback +setup_app = typer.Typer( + name="setup", + help="Configure KiCad to use libraries", + rich_markup_mode="rich", + callback=setup, + invoke_without_command=True, +) + +__all__ = ["setup", "setup_app"] diff --git a/kicad_lib_manager/commands/setup/command.py b/kicad_lib_manager/commands/setup/command.py index 97f4f47..af60858 100644 --- a/kicad_lib_manager/commands/setup/command.py +++ b/kicad_lib_manager/commands/setup/command.py @@ -1,15 +1,14 @@ """ -Setup command implementation for KiCad Library Manager. +Setup command implementation for KiCad Library Manager (Typer version). """ import re -import sys from pathlib import Path -from typing import Dict, List +from typing import Dict, List, Optional -import click +import typer +from rich.console import Console -# TODO: Use full path (kicad_lib_manager...) from ...services.config_service import Config, LibraryDict from ...services.library_service import LibraryService from ...utils.backup import create_backup @@ -22,6 +21,8 @@ from ...utils.file_ops import list_libraries from ...utils.metadata import read_cloud_metadata, read_github_metadata +console = Console() + def fix_invalid_uris( kicad_config: Path, @@ -74,65 +75,49 @@ def fix_invalid_uris( return changes_made -@click.command() -@click.option( - "--kicad-lib-dir", - envvar="KICAD_USER_LIB", - help="KiCad library directory (uses KICAD_USER_LIB env var if not specified)", -) -@click.option( - "--kicad-3d-dir", - envvar="KICAD_3D_LIB", - help="KiCad 3D models directory (uses KICAD_3D_LIB env var if not specified)", -) -@click.option( - "--threed-lib-dirs", - help="Names of 3D model libraries to use (comma-separated, uses all if not specified)", -) -@click.option( - "--symbol-lib-dirs", - help="Names of symbol libraries to use (comma-separated, uses current if not specified)", -) -@click.option( - "--all-libraries", - is_flag=True, - default=False, - help="Set up all configured libraries (both symbols and 3D models)", -) -@click.option( - "--max-backups", - default=5, - show_default=True, - help="Maximum number of backups to keep", -) -@click.option( - "--dry-run", - is_flag=True, - help="Show what would be done without making changes", -) -@click.option( - "--pin-libraries/--no-pin-libraries", - default=True, - show_default=True, - help="Add libraries to KiCad pinned libraries for quick access", -) -@click.option( - "--verbose", - "-v", - is_flag=True, - help="Show more information for debugging", -) def setup( - kicad_lib_dir, - kicad_3d_dir, - threed_lib_dirs, - symbol_lib_dirs, - all_libraries, - max_backups, - dry_run, - pin_libraries, - verbose, -): + kicad_lib_dir: Optional[str] = typer.Option( + None, + "--kicad-lib-dir", + envvar="KICAD_USER_LIB", + help="KiCad library directory (uses KICAD_USER_LIB env var if not specified)", + ), + kicad_3d_dir: Optional[str] = typer.Option( + None, + "--kicad-3d-dir", + envvar="KICAD_3D_LIB", + help="KiCad 3D models directory (uses KICAD_3D_LIB env var if not specified)", + ), + threed_lib_dirs: Optional[str] = typer.Option( + None, + "--threed-lib-dirs", + help="Names of 3D model libraries to use (comma-separated, uses all if not specified)", + ), + symbol_lib_dirs: Optional[str] = typer.Option( + None, + "--symbol-lib-dirs", + help="Names of symbol libraries to use (comma-separated, uses current if not specified)", + ), + all_libraries: bool = typer.Option( + False, + "--all-libraries", + help="Set up all configured libraries (both symbols and 3D models)", + ), + max_backups: int = typer.Option( + 5, "--max-backups", help="Maximum number of backups to keep" + ), + dry_run: bool = typer.Option( + False, "--dry-run", help="Show what would be done without making changes" + ), + pin_libraries: bool = typer.Option( + True, + "--pin-libraries/--no-pin-libraries", + help="Add libraries to KiCad pinned libraries for quick access", + ), + verbose: bool = typer.Option( + False, "--verbose", "-v", help="Show more information for debugging" + ), +) -> None: """Configure KiCad to use libraries in the specified directory This command sets up KiCad to use your configured libraries. It will: @@ -150,25 +135,29 @@ def setup( if kicad_lib_dir: cmd_line_lib_paths["symbols"] = kicad_lib_dir if verbose: - click.echo(f"Symbol library specified on command line: {kicad_lib_dir}") + console.print( + f"Symbol library specified on command line: [blue]{kicad_lib_dir}[/blue]" + ) if kicad_3d_dir: cmd_line_lib_paths["3d"] = kicad_3d_dir if verbose: - click.echo(f"3D model library specified on command line: {kicad_3d_dir}") + console.print( + f"3D model library specified on command line: [blue]{kicad_3d_dir}[/blue]" + ) # Split library names if provided threed_lib_names = None if threed_lib_dirs: threed_lib_names = [name.strip() for name in threed_lib_dirs.split(",")] if verbose: - click.echo(f"Requested 3D model libraries: {threed_lib_names}") + console.print(f"Requested 3D model libraries: {threed_lib_names}") symbol_lib_names = None if symbol_lib_dirs: symbol_lib_names = [name.strip() for name in symbol_lib_dirs.split(",")] if verbose: - click.echo(f"Requested symbol libraries: {symbol_lib_names}") + console.print(f"Requested symbol libraries: {symbol_lib_names}") # Check Config file for library paths config_lib_paths: Dict[str, str] = {} @@ -182,18 +171,18 @@ def setup( # Display configuration file location if verbose if verbose: config_file = config_obj._get_config_file() - click.echo(f"Looking for configuration in: {config_file}") + console.print(f"Looking for configuration in: {config_file}") if config_file.exists(): - click.echo("Configuration file exists") + console.print("Configuration file exists") else: - click.echo("Configuration file does not exist") + console.print("Configuration file does not exist") # Get all configured libraries all_symbol_libs = config_obj.get_libraries("github") all_3d_libs = config_obj.get_libraries("cloud") if verbose: - click.echo( + console.print( f"Found {len(all_symbol_libs)} symbol libraries and {len(all_3d_libs)} 3D model libraries in config" ) @@ -238,11 +227,11 @@ def setup( # Print what we're setting up if config_symbol_libs: - click.echo("\nSetting up symbol libraries:") + console.print("\nSetting up symbol libraries:") for lib in config_symbol_libs: lib_name = lib.get("name", "unnamed") lib_path = lib.get("path", "unknown") - click.echo(f" - {lib_name}: {lib_path}") + console.print(f" - {lib_name}: {lib_path}") # Read metadata to get environment variable name try: @@ -252,14 +241,14 @@ def setup( if env_var and isinstance(env_var, str): # Store all GitHub libraries with their env vars config_lib_paths[env_var] = lib_path - click.echo(f" Using environment variable: {env_var}") + console.print(f" Using environment variable: {env_var}") else: - click.echo(" No environment variable configured") + console.print(" No environment variable configured") else: - click.echo(" No metadata or environment variable found") + console.print(" No metadata or environment variable found") except Exception as e: if verbose: - click.echo(f" Error reading metadata: {e}") + console.print(f" Error reading metadata: {e}") # If we're using the first symbol library as the main library if not kicad_lib_dir and lib == config_symbol_libs[0]: @@ -269,11 +258,11 @@ def setup( config_lib_paths["KICAD_USER_LIB"] = lib_path if config_3d_libs: - click.echo("\nSetting up 3D model libraries:") + console.print("\nSetting up 3D model libraries:") for lib in config_3d_libs: lib_name = lib.get("name", "unnamed") lib_path = lib.get("path", "unknown") - click.echo(f" - {lib_name}: {lib_path}") + console.print(f" - {lib_name}: {lib_path}") # Read metadata to get environment variable name try: @@ -283,14 +272,14 @@ def setup( if env_var and isinstance(env_var, str): # Store all 3D libraries with their env vars config_lib_paths[env_var] = lib_path - click.echo(f" Using environment variable: {env_var}") + console.print(f" Using environment variable: {env_var}") else: - click.echo(" No environment variable configured") + console.print(" No environment variable configured") else: - click.echo(" No metadata or environment variable found") + console.print(" No metadata or environment variable found") except Exception as e: if verbose: - click.echo(f" Error reading metadata: {e}") + console.print(f" Error reading metadata: {e}") # Use the first 3D library as the default if not specified if not kicad_3d_dir and lib == config_3d_libs[0]: @@ -299,10 +288,10 @@ def setup( except Exception as e: # If there's any issue with config, continue with environment variables if verbose: - click.echo(f"Error reading from config: {e}") + console.print(f"Error reading from config: {e}") import traceback - click.echo(traceback.format_exc()) + console.print(traceback.format_exc()) # Fall back to environment variables if still not found env_lib_paths = {} @@ -311,75 +300,74 @@ def setup( if env_var: kicad_lib_dir = env_var env_lib_paths["KICAD_USER_LIB"] = env_var - click.echo( + console.print( f"Using KiCad library from environment variable: {kicad_lib_dir}" ) else: - click.echo("Error: KICAD_USER_LIB not set and not provided", err=True) - click.echo( - "Consider initializing a library with 'kilm init' first.", err=True + console.print("[red]Error: KICAD_USER_LIB not set and not provided[/red]") + console.print( + "[yellow]Consider initializing a library with 'kilm init' first.[/yellow]" ) - sys.exit(1) + raise typer.Exit(1) if not kicad_3d_dir: env_var = find_environment_variables("KICAD_3D_LIB") if env_var: kicad_3d_dir = env_var env_lib_paths["KICAD_3D_LIB"] = env_var - click.echo( + console.print( f"Using 3D model library from environment variable: {kicad_3d_dir}" ) else: - click.echo( - "Warning: KICAD_3D_LIB not set, 3D models might not work correctly", - err=True, + console.print( + "[yellow]Warning: KICAD_3D_LIB not set, 3D models might not work correctly[/yellow]" ) - click.echo( - "Consider adding a 3D model directory with 'kilm add-3d'", err=True + console.print( + "[yellow]Consider adding a 3D model directory with 'kilm add-3d'[/yellow]" ) # Show summary of where libraries are coming from if verbose: - click.echo("\nSummary of library sources:") + console.print("\nSummary of library sources:") if cmd_line_lib_paths: - click.echo(" From command line:") + console.print(" From command line:") for lib_type, path in cmd_line_lib_paths.items(): - click.echo(f" - {lib_type}: {path}") + console.print(f" - {lib_type}: {path}") if config_lib_paths: - click.echo(" From config file:") + console.print(" From config file:") for lib_type, path in config_lib_paths.items(): - click.echo(f" - {lib_type}: {path}") + console.print(f" - {lib_type}: {path}") if env_lib_paths: - click.echo(" From environment variables:") + console.print(" From environment variables:") for lib_type, path in env_lib_paths.items(): - click.echo(f" - {lib_type}: {path}") + console.print(f" - {lib_type}: {path}") # Expand user home directory if needed kicad_lib_dir = expand_user_path(kicad_lib_dir) if kicad_3d_dir: kicad_3d_dir = expand_user_path(kicad_3d_dir) - click.echo(f"\nUsing KiCad symbol library directory: {kicad_lib_dir}") + console.print(f"\nUsing KiCad symbol library directory: {kicad_lib_dir}") if kicad_3d_dir: - click.echo(f"Using KiCad main 3D models directory: {kicad_3d_dir}") + console.print(f"Using KiCad main 3D models directory: {kicad_3d_dir}") # Find KiCad configuration try: kicad_config = LibraryService.find_kicad_config() - click.echo(f"Found KiCad configuration at: {kicad_config}") + console.print(f"Found KiCad configuration at: {kicad_config}") # Fix any invalid URIs in existing library entries uri_changes = fix_invalid_uris(kicad_config, True, max_backups, dry_run) if uri_changes: if dry_run: - click.echo("Would fix invalid library URIs in KiCad configuration") + console.print("Would fix invalid library URIs in KiCad configuration") else: - click.echo("Fixed invalid library URIs in KiCad configuration") + console.print("Fixed invalid library URIs in KiCad configuration") except Exception as e: - click.echo(f"Error finding KiCad configuration: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error finding KiCad configuration: {e}[/red]") + raise typer.Exit(1) # Prepare environment variables dictionary env_vars = {} @@ -406,21 +394,23 @@ def setup( ) if env_changes_needed: if dry_run: - click.echo("Would update environment variables in KiCad configuration") + console.print( + "Would update environment variables in KiCad configuration" + ) else: - click.echo("Updated environment variables in KiCad configuration") - click.echo("Created backup of kicad_common.json") + console.print("Updated environment variables in KiCad configuration") + console.print("Created backup of kicad_common.json") # Show all environment variables that were set - click.echo("\nEnvironment variables set in KiCad:") + console.print("\nEnvironment variables set in KiCad:") for var_name, value in env_vars.items(): - click.echo(f" {var_name} = {value}") + console.print(f" {var_name} = {value}") else: - click.echo( + console.print( "Environment variables already up to date in KiCad configuration" ) except Exception as e: - click.echo(f"Error updating environment variables: {e}", err=True) + console.print(f"[red]Error updating environment variables: {e}[/red]") # Continue with the rest of the setup, but don't set env_changes_needed to True # Add libraries @@ -451,23 +441,23 @@ def setup( if sym_table.exists(): create_backup(sym_table, max_backups) - click.echo("Created backup of symbol library table") + console.print("Created backup of symbol library table") if fp_table.exists(): create_backup(fp_table, max_backups) - click.echo("Created backup of footprint library table") + console.print("Created backup of footprint library table") if added_libraries: if dry_run: - click.echo( + console.print( f"Would add {len(added_libraries)} libraries to KiCad configuration" ) else: - click.echo( + console.print( f"Added {len(added_libraries)} libraries to KiCad configuration" ) else: - click.echo("No new libraries to add") + console.print("No new libraries to add") # Pin libraries if requested pinned_changes_needed = False @@ -483,11 +473,11 @@ def setup( footprint_libs = existing_footprints if verbose: - click.echo( + console.print( f"Found {len(symbol_libs)} symbol libraries and {len(footprint_libs)} footprint libraries to pin" ) except Exception as e: - click.echo(f"Error listing libraries to pin: {e}", err=True) + console.print(f"[red]Error listing libraries to pin: {e}[/red]") try: pinned_changes_needed = update_pinned_libraries( @@ -499,29 +489,29 @@ def setup( if pinned_changes_needed: if dry_run: - click.echo( + console.print( f"Would pin {len(symbol_libs)} symbol and {len(footprint_libs)} footprint libraries in KiCad" ) else: - click.echo( + console.print( f"Pinned {len(symbol_libs)} symbol and {len(footprint_libs)} footprint libraries in KiCad" ) else: - click.echo("All libraries already pinned in KiCad") + console.print("All libraries already pinned in KiCad") except Exception as e: - click.echo(f"Error pinning libraries: {e}", err=True) + console.print(f"[red]Error pinning libraries: {e}[/red]") if not changes_needed and not env_changes_needed and not pinned_changes_needed: - click.echo("No changes needed, configuration is up to date") + console.print("No changes needed, configuration is up to date") elif dry_run: - click.echo("Dry run: No changes were made") + console.print("Dry run: No changes were made") except Exception as e: - click.echo(f"Error adding libraries: {e}", err=True) + console.print(f"[red]Error adding libraries: {e}[/red]") if verbose: import traceback - click.echo(traceback.format_exc()) - sys.exit(1) + console.print(traceback.format_exc()) + raise typer.Exit(1) if not dry_run and (changes_needed or env_changes_needed or pinned_changes_needed): - click.echo("Setup complete! Restart KiCad for changes to take effect.") + console.print("Setup complete! Restart KiCad for changes to take effect.") diff --git a/kicad_lib_manager/commands/unpin/__init__.py b/kicad_lib_manager/commands/unpin/__init__.py index 90604f2..788b895 100644 --- a/kicad_lib_manager/commands/unpin/__init__.py +++ b/kicad_lib_manager/commands/unpin/__init__.py @@ -1,3 +1,14 @@ +import typer + from .command import unpin -__all__ = ["unpin"] +# Create Typer app and add the unpin command as callback +unpin_app = typer.Typer( + name="unpin", + help="Unpin libraries in KiCad for quick access", + rich_markup_mode="rich", + callback=unpin, + invoke_without_command=True, +) + +__all__ = ["unpin", "unpin_app"] diff --git a/kicad_lib_manager/commands/unpin/command.py b/kicad_lib_manager/commands/unpin/command.py index c299ff6..9af1fbb 100644 --- a/kicad_lib_manager/commands/unpin/command.py +++ b/kicad_lib_manager/commands/unpin/command.py @@ -1,76 +1,75 @@ """ -Unpin command implementation for KiCad Library Manager. +Unpin command implementation for KiCad Library Manager (Typer version). """ import json -import sys +from typing import List, Optional -import click +import typer +from rich.console import Console +from rich.panel import Panel from ...services.library_service import LibraryService from ...utils.backup import create_backup - -@click.command() -@click.option( - "--symbols", - "-s", - multiple=True, - help="Symbol libraries to unpin (can be specified multiple times)", -) -@click.option( - "--footprints", - "-f", - multiple=True, - help="Footprint libraries to unpin (can be specified multiple times)", -) -@click.option( - "--all", - is_flag=True, - help="Unpin all libraries", -) -@click.option( - "--dry-run", - is_flag=True, - help="Show what would be done without making changes", -) -@click.option( - "--max-backups", - default=5, - show_default=True, - help="Maximum number of backups to keep", -) -@click.option( - "--verbose", - "-v", - is_flag=True, - help="Show verbose output for debugging", -) -def unpin(symbols, footprints, all, dry_run, max_backups, verbose): +console = Console() + + +def unpin( + symbols: Optional[List[str]] = typer.Option( + None, + "--symbols", + "-s", + help="Symbol libraries to unpin (can be specified multiple times)", + ), + footprints: Optional[List[str]] = typer.Option( + None, + "--footprints", + "-f", + help="Footprint libraries to unpin (can be specified multiple times)", + ), + all_libraries: bool = typer.Option(False, "--all", help="Unpin all libraries"), + dry_run: bool = typer.Option( + False, "--dry-run", help="Show what would be done without making changes" + ), + max_backups: int = typer.Option( + 5, "--max-backups", help="Maximum number of backups to keep" + ), + verbose: bool = typer.Option( + False, "--verbose", "-v", help="Show verbose output for debugging" + ), +) -> None: """Unpin libraries in KiCad""" + # Handle None values from optional parameters + symbols = symbols or [] + footprints = footprints or [] + # Enforce mutual exclusivity of --all with --symbols/--footprints - if all and (symbols or footprints): - raise click.UsageError( - "'--all' cannot be used with '--symbols' or '--footprints'" + if all_libraries and (symbols or footprints): + console.print( + "[red]Error: '--all' cannot be used with '--symbols' or '--footprints'[/red]" ) + raise typer.Exit(1) # Find KiCad configuration try: kicad_config = LibraryService.find_kicad_config() if verbose: - click.echo(f"Found KiCad configuration at: {kicad_config}") + console.print(f"Found KiCad configuration at: [blue]{kicad_config}[/blue]") except Exception as e: - click.echo(f"Error finding KiCad configuration: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error finding KiCad configuration: {e}[/red]") + raise typer.Exit(1) from e # Get the kicad_common.json file kicad_common = kicad_config / "kicad_common.json" if not kicad_common.exists(): - click.echo("KiCad common configuration file not found, nothing to unpin") + console.print( + "[yellow]KiCad common configuration file not found, nothing to unpin[/yellow]" + ) return # If --all is specified, unpin all libraries - if all: + if all_libraries: try: with kicad_common.open() as f: config = json.load(f) @@ -82,38 +81,39 @@ def unpin(symbols, footprints, all, dry_run, max_backups, verbose): if verbose: if symbols: - click.echo(f"Found {len(symbols)} pinned symbol libraries") + console.print( + f"Found [cyan]{len(symbols)}[/cyan] pinned symbol libraries" + ) if footprints: - click.echo( - f"Found {len(footprints)} pinned footprint libraries" + console.print( + f"Found [cyan]{len(footprints)}[/cyan] pinned footprint libraries" ) else: - click.echo( - "No session information found in KiCad configuration, nothing to unpin" + console.print( + "[yellow]No session information found in KiCad configuration, nothing to unpin[/yellow]" ) return if not symbols and not footprints: - click.echo("No pinned libraries found, nothing to unpin") + console.print( + "[yellow]No pinned libraries found, nothing to unpin[/yellow]" + ) return except Exception as e: - click.echo(f"Error reading pinned libraries: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error reading pinned libraries: {e}[/red]") + raise typer.Exit(1) from e # If no libraries are specified, print an error - if not symbols and not footprints and not all: - click.echo("Error: No libraries specified to unpin", err=True) - click.echo( - "Use --symbols, --footprints, or --all to specify libraries to unpin", - err=True, + if not symbols and not footprints and not all_libraries: + console.print("[red]Error: No libraries specified to unpin[/red]") + console.print( + "[yellow]Use --symbols, --footprints, or --all to specify libraries to unpin[/yellow]" ) - sys.exit(1) + raise typer.Exit(1) - # Convert tuples to lists if needed - if isinstance(symbols, tuple): - symbols = list(symbols) - if isinstance(footprints, tuple): - footprints = list(footprints) + # Ensure we have lists (Typer already handles this) + symbols = symbols or [] + footprints = footprints or [] # Unpin the libraries by removing them from the kicad_common.json file try: @@ -124,8 +124,8 @@ def unpin(symbols, footprints, all, dry_run, max_backups, verbose): # Ensure session section exists if "session" not in config: - click.echo( - "No session information found in KiCad configuration, nothing to unpin" + console.print( + "[yellow]No session information found in KiCad configuration, nothing to unpin[/yellow]" ) return @@ -161,29 +161,36 @@ def unpin(symbols, footprints, all, dry_run, max_backups, verbose): if changes_needed: if dry_run: - click.echo( - f"Would unpin {len(symbols) if symbols else 0} symbol and {len(footprints) if footprints else 0} footprint libraries in KiCad" + console.print( + f"[yellow]Would unpin {len(symbols) if symbols else 0} symbol and {len(footprints) if footprints else 0} footprint libraries in KiCad[/yellow]" ) else: - click.echo( - f"Unpinned {len(symbols) if symbols else 0} symbol and {len(footprints) if footprints else 0} footprint libraries in KiCad" + success_msg = f"[green]Unpinned {len(symbols) if symbols else 0} symbol and {len(footprints) if footprints else 0} footprint libraries in KiCad[/green]" + console.print( + Panel( + f"{success_msg}\n\n" + f"[blue]• Created backup of kicad_common.json[/blue]\n" + f"[yellow]• Restart KiCad for changes to take effect[/yellow]", + title="✅ Libraries Unpinned", + border_style="green", + ) ) - click.echo("Created backup of kicad_common.json") - click.echo("Restart KiCad for changes to take effect") else: - click.echo("No changes needed, libraries already unpinned in KiCad") + console.print( + "[yellow]No changes needed, libraries already unpinned in KiCad[/yellow]" + ) if verbose: if symbols: - click.echo("\nUnpinned Symbol Libraries:") + console.print("\n[bold cyan]Unpinned Symbol Libraries:[/bold cyan]") for symbol in sorted(symbols): - click.echo(f" - {symbol}") + console.print(f" • [cyan]{symbol}[/cyan]") if footprints: - click.echo("\nUnpinned Footprint Libraries:") + console.print("\n[bold cyan]Unpinned Footprint Libraries:[/bold cyan]") for footprint in sorted(footprints): - click.echo(f" - {footprint}") + console.print(f" • [cyan]{footprint}[/cyan]") except Exception as e: - click.echo(f"Error unpinning libraries: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error unpinning libraries: {e}[/red]") + raise typer.Exit(1) from e diff --git a/kicad_lib_manager/main.py b/kicad_lib_manager/main.py index 97a95a7..63437b4 100644 --- a/kicad_lib_manager/main.py +++ b/kicad_lib_manager/main.py @@ -16,7 +16,9 @@ from .commands.init import init_app from .commands.list_libraries import list_app from .commands.pin import pin_app +from .commands.setup import setup_app from .commands.status import status_app +from .commands.unpin import unpin_app from .utils.banner import show_banner TAGLINE = "Professional KiCad library management" @@ -90,11 +92,16 @@ def main( • [cyan]kilm sync[/cyan] - Update library content """ # Show banner when no arguments are provided, centered - show_banner(console) - console.print() - console.print(Align.center(Text(TAGLINE, style="italic bright_yellow"))) - console.print() - console.print("[dim]Use 'kilm --help' to see all commands.[/dim]", justify="center") + import sys + + if not sys.argv[1:]: + show_banner(console) + console.print() + console.print(Align.center(Text(TAGLINE, style="italic bright_yellow"))) + console.print() + console.print( + "[dim]Use 'kilm --help' to see all commands.[/dim]", justify="center" + ) # Register command apps (migrated to Typer) @@ -102,10 +109,10 @@ def main( app.add_typer(list_app, name="list", help="List available KiCad libraries") app.add_typer(init_app, name="init", help="Initialize library configuration") app.add_typer(pin_app, name="pin", help="Pin favorite libraries") +app.add_typer(unpin_app, name="unpin", help="Unpin favorite libraries") +app.add_typer(setup_app, name="setup", help="Configure KiCad to use libraries") # TODO: Migrate remaining commands to Typer -# - setup: Configure KiCad to use libraries -# - unpin: Unpin favorite libraries # - add-3d: Add 3D model libraries # - config: Manage configuration settings # - sync: Update/sync library content From 928234f2909bd107b0c7cc16d2e794ec36bec4a6 Mon Sep 17 00:00:00 2001 From: barisgit Date: Mon, 8 Sep 2025 12:07:15 +0200 Subject: [PATCH 08/13] Finish migrating other commands and fix tests to now use typer --- .gitignore | 3 +- kicad_lib_manager/commands/add_3d/__init__.py | 12 +- kicad_lib_manager/commands/add_3d/command.py | 170 +++-- .../commands/add_hook/__init__.py | 13 +- .../commands/add_hook/command.py | 170 +++-- kicad_lib_manager/commands/config/__init__.py | 21 +- kicad_lib_manager/commands/config/command.py | 464 ++++++++----- kicad_lib_manager/commands/setup/command.py | 143 ++-- kicad_lib_manager/commands/status/command.py | 21 +- kicad_lib_manager/commands/sync/__init__.py | 15 +- kicad_lib_manager/commands/sync/command.py | 320 ++++----- .../commands/template/__init__.py | 23 +- .../commands/template/command.py | 635 +++++++++--------- kicad_lib_manager/commands/update/__init__.py | 12 +- kicad_lib_manager/commands/update/command.py | 101 +-- kicad_lib_manager/main.py | 20 +- kicad_lib_manager/utils/file_ops.py | 41 +- tests/test_config_commands.py | 20 +- tests/test_library_manager.py | 57 +- tests/test_sync_command.py | 26 +- tests/test_unpin_command.py | 28 +- 21 files changed, 1344 insertions(+), 971 deletions(-) diff --git a/.gitignore b/.gitignore index 04e4832..27c5b88 100644 --- a/.gitignore +++ b/.gitignore @@ -47,4 +47,5 @@ test_template/ TODO.md .claude/settings.local.json .claude/doc/ -temp*/ \ No newline at end of file +temp/ +templates/ \ No newline at end of file diff --git a/kicad_lib_manager/commands/add_3d/__init__.py b/kicad_lib_manager/commands/add_3d/__init__.py index 8676021..d60f0dd 100644 --- a/kicad_lib_manager/commands/add_3d/__init__.py +++ b/kicad_lib_manager/commands/add_3d/__init__.py @@ -1,3 +1,13 @@ +import typer + from .command import add_3d -__all__ = ["add_3d"] +add_3d_app = typer.Typer( + name="add-3d", + help="Add cloud-based 3D model libraries to KiCad configuration", + rich_markup_mode="rich", + callback=add_3d, + invoke_without_command=True, +) + +__all__ = ["add_3d", "add_3d_app"] diff --git a/kicad_lib_manager/commands/add_3d/command.py b/kicad_lib_manager/commands/add_3d/command.py index 10e94ae..5a008f1 100644 --- a/kicad_lib_manager/commands/add_3d/command.py +++ b/kicad_lib_manager/commands/add_3d/command.py @@ -1,11 +1,12 @@ """ -Add cloud-based 3D models directory command for KiCad Library Manager. +Add cloud-based 3D models directory command for KiCad Library Manager (Typer version). """ -import sys from pathlib import Path +from typing import Annotated, Optional -import click +import typer +from rich.console import Console from ...services.config_service import Config from ...utils.metadata import ( @@ -16,43 +17,46 @@ write_cloud_metadata, ) - -@click.command() -@click.option( - "--name", - help="Name for this 3D models collection (automatic if not provided)", - default=None, -) -@click.option( - "--directory", - help="Directory containing 3D models (default: current directory)", - type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True), -) -@click.option( - "--description", - help="Description for this 3D models collection", - default=None, -) -@click.option( - "--env-var", - help="Custom environment variable name for this 3D model library", - default=None, -) -@click.option( - "--force", - is_flag=True, - default=False, - help="Overwrite existing metadata file if present", - show_default=True, -) -@click.option( - "--no-env-var", - is_flag=True, - default=False, - help="Don't assign an environment variable to this library", - show_default=True, -) -def add_3d(name, directory, description, env_var, force, no_env_var): +console = Console() + + +def add_3d( + name: Annotated[ + Optional[str], + typer.Option( + help="Name for this 3D models collection (automatic if not provided)" + ), + ] = None, + directory: Annotated[ + Optional[Path], + typer.Option( + help="Directory containing 3D models (default: current directory)", + exists=True, + file_okay=False, + dir_okay=True, + resolve_path=True, + ), + ] = None, + description: Annotated[ + Optional[str], typer.Option(help="Description for this 3D models collection") + ] = None, + env_var: Annotated[ + Optional[str], + typer.Option( + "--env-var", + help="Custom environment variable name for this 3D model library", + ), + ] = None, + force: Annotated[ + bool, typer.Option(help="Overwrite existing metadata file if present") + ] = False, + no_env_var: Annotated[ + bool, + typer.Option( + "--no-env-var", help="Don't assign an environment variable to this library" + ), + ] = False, +) -> None: """Add a cloud-based 3D models directory to the configuration. This command registers a directory containing 3D models that are typically @@ -68,41 +72,51 @@ def add_3d(name, directory, description, env_var, force, no_env_var): If no directory is specified, the current directory will be used. """ # Use current directory if not specified - directory = Path.cwd().resolve() if not directory else Path(directory).resolve() + directory = Path.cwd().resolve() if directory is None else directory.resolve() - click.echo(f"Adding cloud-based 3D models directory: {directory}") + console.print( + f"[bold cyan]Adding cloud-based 3D models directory:[/bold cyan] {directory}" + ) # Check for existing metadata metadata = read_cloud_metadata(directory) if metadata and not force: - click.echo(f"Found existing metadata file ({CLOUD_METADATA_FILE}).") + console.print( + f"[green]Found existing metadata file[/green] ({CLOUD_METADATA_FILE})" + ) library_name = metadata.get("name") library_description = metadata.get("description") library_env_var = metadata.get("env_var") - click.echo(f"Using existing name: {library_name}") + console.print(f"Using existing name: [blue]{library_name}[/blue]") # Show environment variable if present if library_env_var and not no_env_var: - click.echo(f"Using existing environment variable: {library_env_var}") + console.print( + f"Using existing environment variable: [yellow]{library_env_var}[/yellow]" + ) # Override with command line parameters if provided if name: library_name = name - click.echo(f"Overriding with provided name: {library_name}") + console.print(f"Overriding with provided name: [blue]{library_name}[/blue]") if description: library_description = description - click.echo(f"Overriding with provided description: {library_description}") + console.print( + f"Overriding with provided description: [blue]{library_description}[/blue]" + ) if env_var: library_env_var = env_var - click.echo( - f"Overriding with provided environment variable: {library_env_var}" + console.print( + f"Overriding with provided environment variable: [yellow]{library_env_var}[/yellow]" ) elif no_env_var: library_env_var = None - click.echo("Disabling environment variable as requested") + console.print( + "[yellow]Disabling environment variable as requested[/yellow]" + ) # Update metadata if command line parameters were provided if name or description or env_var or no_env_var: @@ -114,13 +128,17 @@ def add_3d(name, directory, description, env_var, force, no_env_var): metadata["env_var"] = None metadata["updated_with"] = "kilm" write_cloud_metadata(directory, metadata) - click.echo("Updated metadata file with new information.") + console.print("[green]Updated metadata file with new information[/green]") else: # Create a new metadata file if metadata and force: - click.echo(f"Overwriting existing metadata file ({CLOUD_METADATA_FILE}).") + console.print( + f"[yellow]Overwriting existing metadata file[/yellow] ({CLOUD_METADATA_FILE})" + ) else: - click.echo(f"Creating new metadata file ({CLOUD_METADATA_FILE}).") + console.print( + f"[green]Creating new metadata file[/green] ({CLOUD_METADATA_FILE})" + ) # Generate metadata metadata = get_default_cloud_metadata(directory) @@ -142,7 +160,7 @@ def add_3d(name, directory, description, env_var, force, no_env_var): # Write metadata file write_cloud_metadata(directory, metadata) - click.echo("Metadata file created.") + console.print("[green]Metadata file created[/green]") library_name = metadata["name"] library_env_var = metadata.get("env_var") @@ -158,10 +176,12 @@ def add_3d(name, directory, description, env_var, force, no_env_var): break if not found_models: - click.echo("Warning: No 3D model files found in this directory.") - if not click.confirm("Continue anyway?", default=True): - click.echo("Operation cancelled.") - sys.exit(0) + console.print( + "[yellow]Warning: No 3D model files found in this directory[/yellow]" + ) + if not typer.confirm("Continue anyway?", default=True): + console.print("[red]Operation cancelled[/red]") + raise typer.Exit(0) # Update metadata with actual model count model_count = 0 @@ -179,22 +199,28 @@ def add_3d(name, directory, description, env_var, force, no_env_var): library_name = metadata.get("name", directory.name) config.add_library(library_name, str(directory), "cloud") - click.echo(f"3D models directory '{library_name}' added successfully!") - click.echo(f"Path: {directory}") + console.print( + f"[bold green]3D models directory '{library_name}' added successfully![/bold green]" + ) + console.print(f"[blue]Path:[/blue] {directory}") if model_count > 0: - click.echo(f"Found {model_count} 3D model files.") + console.print(f"[green]Found {model_count} 3D model files[/green]") if library_env_var: - click.echo(f"Assigned environment variable: {library_env_var}") - click.echo("\nYou can use this directory with:") - click.echo(f" kilm setup --3d-lib-dirs '{library_name}'") - click.echo(" # or by setting the environment variable") - click.echo(f" export {library_env_var}='{directory}'") + console.print( + f"[yellow]Assigned environment variable:[/yellow] {library_env_var}" + ) + console.print("\n[bold]You can use this directory with:[/bold]") + console.print(f" [cyan]kilm setup --3d-lib-dirs '{library_name}'[/cyan]") + console.print(" [dim]# or by setting the environment variable[/dim]") + console.print(f" [cyan]export {library_env_var}='{directory}'[/cyan]") # Show current cloud libraries libraries = config.get_libraries("cloud") if len(libraries) > 1: - click.echo("\nAll registered cloud-based 3D model directories:") + console.print( + "\n[bold]All registered cloud-based 3D model directories:[/bold]" + ) for lib in libraries: lib_name = lib.get("name", "unnamed") lib_path = lib.get("path", "unknown") @@ -209,9 +235,11 @@ def add_3d(name, directory, description, env_var, force, no_env_var): pass if lib_env_var: - click.echo(f" - {lib_name}: {lib_path} (ENV: {lib_env_var})") + console.print( + f" - [cyan]{lib_name}[/cyan]: {lib_path} [yellow](ENV: {lib_env_var})[/yellow]" + ) else: - click.echo(f" - {lib_name}: {lib_path}") + console.print(f" - [cyan]{lib_name}[/cyan]: {lib_path}") except Exception as e: - click.echo(f"Error adding 3D models directory: {e}", err=True) - sys.exit(1) + console.print(f"[red]Error adding 3D models directory: {e}[/red]") + raise typer.Exit(1) from e diff --git a/kicad_lib_manager/commands/add_hook/__init__.py b/kicad_lib_manager/commands/add_hook/__init__.py index e802f9f..d7eeab3 100644 --- a/kicad_lib_manager/commands/add_hook/__init__.py +++ b/kicad_lib_manager/commands/add_hook/__init__.py @@ -1,3 +1,14 @@ +import typer + from .command import add_hook -__all__ = ["add_hook"] +# Create Typer app and add the add_hook command as callback +add_hook_app = typer.Typer( + name="add-hook", + help="Add a Git post-merge hook to automatically sync KiCad libraries", + rich_markup_mode="rich", + callback=add_hook, + invoke_without_command=True, +) + +__all__ = ["add_hook", "add_hook_app"] diff --git a/kicad_lib_manager/commands/add_hook/command.py b/kicad_lib_manager/commands/add_hook/command.py index d7194ef..6a001c8 100644 --- a/kicad_lib_manager/commands/add_hook/command.py +++ b/kicad_lib_manager/commands/add_hook/command.py @@ -4,8 +4,10 @@ """ from pathlib import Path +from typing import Annotated, Optional -import click +import typer +from rich.console import Console from ...utils.git_utils import ( backup_existing_hook, @@ -14,22 +16,20 @@ merge_hook_content, ) +console = Console() -@click.command() -@click.option( - "--directory", - help="Target git repository directory (defaults to current directory)", - default=None, - type=click.Path(exists=True, file_okay=False, dir_okay=True, resolve_path=True), -) -@click.option( - "--force", - is_flag=True, - default=False, - help="Overwrite existing hook if present", - show_default=True, -) -def add_hook(directory, force): + +def add_hook( + directory: Annotated[ + Optional[Path], + typer.Option( + help="Target git repository directory (defaults to current directory)" + ), + ] = None, + force: Annotated[ + bool, typer.Option(help="Overwrite existing hook if present") + ] = False, +) -> None: """Add a Git post-merge hook to automatically sync KiCad libraries. This command adds a Git post-merge hook to the specified repository @@ -39,78 +39,100 @@ def add_hook(directory, force): This ensures your KiCad libraries are always up-to-date after pulling changes from remote repositories. """ - # Determine target directory - target_dir = Path(directory) if directory else Path.cwd() - - click.echo(f"Adding Git hook to repository: {target_dir}") - try: - # Get the active hooks directory (handles custom paths, worktrees, etc.) - hooks_dir = get_git_hooks_directory(target_dir) - click.echo(f"Using hooks directory: {hooks_dir}") + # Determine target directory + target_dir = directory if directory else Path.cwd() - except RuntimeError as e: - raise click.ClickException(f"Error: {e}") from e + console.print(f"[cyan]Adding Git hook to repository: {target_dir}[/cyan]") - # Check if post-merge hook already exists - post_merge_hook = hooks_dir / "post-merge" - - if post_merge_hook.exists(): - if not force: - click.echo(f"Post-merge hook already exists at {post_merge_hook}") - if not click.confirm("Overwrite existing hook?", default=False): - click.echo("Hook installation cancelled.") - return + try: + # Get the active hooks directory (handles custom paths, worktrees, etc.) + hooks_dir = get_git_hooks_directory(target_dir) + console.print(f"[blue]Using hooks directory: {hooks_dir}[/blue]") - # Create backup of existing hook - backup_path = backup_existing_hook(post_merge_hook) - click.echo(f"Created backup of existing hook: {backup_path}") + except RuntimeError as e: + console.print(f"[red]Error: {e}[/red]") + raise typer.Exit(1) from e - # Read existing content for potential merging - try: - existing_content = post_merge_hook.read_text(encoding="utf-8") + # Check if post-merge hook already exists + post_merge_hook = hooks_dir / "post-merge" - if force: - # Force overwrite - don't merge, just replace - click.echo("Force overwrite requested, replacing existing hook...") - new_content = create_kilm_hook_content() - else: - # Merge with existing content to preserve user logic - click.echo("Merging KiLM content with existing hook...") - new_content = merge_hook_content( - existing_content, create_kilm_hook_content() + if post_merge_hook.exists(): + if not force: + console.print( + f"[yellow]Post-merge hook already exists at {post_merge_hook}[/yellow]" ) + overwrite = typer.confirm("Overwrite existing hook?", default=False) + if not overwrite: + console.print("[yellow]Hook installation cancelled.[/yellow]") + return + + # Create backup of existing hook + backup_path = backup_existing_hook(post_merge_hook) + console.print( + f"[green]Created backup of existing hook: {backup_path}[/green]" + ) - except (OSError, UnicodeDecodeError): - click.echo("Warning: Could not read existing hook content, overwriting...") + # Read existing content for potential merging + try: + existing_content = post_merge_hook.read_text(encoding="utf-8") + + if force: + # Force overwrite - don't merge, just replace + console.print( + "[yellow]Force overwrite requested, replacing existing hook...[/yellow]" + ) + new_content = create_kilm_hook_content() + else: + # Merge with existing content to preserve user logic + console.print( + "[cyan]Merging KiLM content with existing hook...[/cyan]" + ) + new_content = merge_hook_content( + existing_content, create_kilm_hook_content() + ) + + except (OSError, UnicodeDecodeError): + console.print( + "[yellow]Warning: Could not read existing hook content, overwriting...[/yellow]" + ) + new_content = create_kilm_hook_content() + else: + # No existing hook, create new one new_content = create_kilm_hook_content() - else: - # No existing hook, create new one - new_content = create_kilm_hook_content() - try: - # Write the hook content - with post_merge_hook.open("w") as f: - f.write(new_content) + try: + # Write the hook content + with post_merge_hook.open("w") as f: + f.write(new_content) - # Make the hook executable - post_merge_hook.chmod(0o755) + # Make the hook executable + post_merge_hook.chmod(0o755) - click.echo(f"Successfully installed post-merge hook at {post_merge_hook}") - click.echo( - "The hook will run 'kilm sync' after every 'git pull' or 'git merge' operation." - ) + console.print( + f"[green]Successfully installed post-merge hook at {post_merge_hook}[/green]" + ) + console.print( + "[blue]The hook will run 'kilm sync' after every 'git pull' or 'git merge' operation.[/blue]" + ) + + if post_merge_hook.exists() and "KiLM-managed section" in new_content: + console.print( + "\n[cyan]Note: The hook contains clear markers for KiLM-managed sections,[/cyan]" + ) + console.print("[cyan]making future updates safe and idempotent.[/cyan]") - if post_merge_hook.exists() and "KiLM-managed section" in new_content: - click.echo( - "\nNote: The hook contains clear markers for KiLM-managed sections," + console.print( + "\n[blue]Note: You may need to modify the hook script if you want to customize[/blue]" + ) + console.print( + "[blue]the update behavior or automatically set up libraries.[/blue]" ) - click.echo("making future updates safe and idempotent.") - click.echo( - "\nNote: You may need to modify the hook script if you want to customize" - ) - click.echo("the update behavior or automatically set up libraries.") + except Exception as e: + console.print(f"[red]Error creating hook: {str(e)}[/red]") + raise typer.Exit(1) from e except Exception as e: - raise click.ClickException(f"Error creating hook: {str(e)}") from e + console.print(f"[red]Error: {e}[/red]") + raise typer.Exit(1) from e diff --git a/kicad_lib_manager/commands/config/__init__.py b/kicad_lib_manager/commands/config/__init__.py index 6a0af2a..e5b7a23 100644 --- a/kicad_lib_manager/commands/config/__init__.py +++ b/kicad_lib_manager/commands/config/__init__.py @@ -1,3 +1,20 @@ -from .command import config +import typer -__all__ = ["config"] +from .command import list_config, remove, set_default + +# Create Typer app with subcommands +config_app = typer.Typer( + name="config", + help="Manage KiCad Library Manager configuration", + rich_markup_mode="rich", + no_args_is_help=True, +) + +# Add subcommands +config_app.command("list", help="List all configured libraries in kilm")(list_config) +config_app.command("set-default", help="Set a library as the default for operations")( + set_default +) +config_app.command("remove", help="Remove a library from the configuration")(remove) + +__all__ = ["config_app", "list_config", "set_default", "remove"] diff --git a/kicad_lib_manager/commands/config/command.py b/kicad_lib_manager/commands/config/command.py index 73f32c7..e10191b 100644 --- a/kicad_lib_manager/commands/config/command.py +++ b/kicad_lib_manager/commands/config/command.py @@ -5,8 +5,12 @@ import sys from pathlib import Path +from typing import Annotated, Optional -import click +import typer +from rich.console import Console +from rich.panel import Panel +from rich.table import Table from ...services.config_service import Config from ...utils.metadata import ( @@ -16,33 +20,22 @@ read_github_metadata, ) - -@click.group() -def config(): - """Manage KiCad Library Manager configuration. - - This command group allows you to list, set defaults, and remove - configuration entries for KiCad Library Manager. - """ - pass - - -@config.command() -@click.option( - "--type", - "library_type", - type=click.Choice(["github", "cloud", "all"]), - default="all", - help="Type of libraries to list (github=symbols/footprints, cloud=3D models)", - show_default=True, -) -@click.option( - "--verbose", - "-v", - is_flag=True, - help="Show more information about libraries", -) -def list(library_type, verbose): +console = Console() + + +def list_config( + library_type: Annotated[ + str, + typer.Option( + "--type", + help="Type of libraries to list (github=symbols/footprints, cloud=3D models)", + ), + ] = "all", + verbose: Annotated[ + bool, + typer.Option("-v", "--verbose", help="Show more information about libraries"), + ] = False, +) -> None: """List all configured libraries in kilm. This shows all libraries stored in the kilm configuration file. @@ -66,13 +59,20 @@ def list(library_type, verbose): current_library = config.get_current_library() if not libraries: - click.echo("No libraries configured.") - click.echo("Use 'kilm init' to initialize a GitHub library.") - click.echo("Use 'kilm add-3d' to add a cloud-based 3D model library.") + console.print() + console.print( + Panel( + "[yellow]No libraries configured.[/yellow]\n\n" + "[cyan]Get Started:[/cyan]\n" + "• Initialize GitHub library: [blue]kilm init[/blue]\n" + "• Add 3D model library: [blue]kilm add-3d[/blue]\n" + "• Check status: [blue]kilm status[/blue]", + title="[bold yellow]⚠️ No Libraries[/bold yellow]", + border_style="yellow", + ) + ) return - click.echo("Configured Libraries:") - # Group libraries by type types = {"github": [], "cloud": []} for lib in libraries: @@ -80,127 +80,255 @@ def list(library_type, verbose): if lib_type in types: types[lib_type].append(lib) - # Print libraries grouped by type - if library_type in ["all", "github"] and types["github"]: - click.echo("\nGitHub Libraries (symbols, footprints, templates):") - for lib in types["github"]: - name = lib.get("name", "unnamed") - path = lib.get("path", "unknown") - path_obj = Path(path) + console.print() - # Mark current library - current_marker = "" - if path == current_library: - current_marker = " (current)" + # Display GitHub Libraries + if library_type in ["all", "github"] and types["github"]: + console.print( + "\n[bold cyan]GitHub Libraries[/bold cyan] [dim](symbols, footprints, templates)[/dim]" + ) + console.print() - if verbose: - click.echo(f" - {name}{current_marker}:") - click.echo(f" Path: {path}") + if verbose: + # Verbose mode: Individual panels for each library + for lib in types["github"]: + name = lib.get("name", "unnamed") + path = lib.get("path", "unknown") + path_obj = Path(path) - # Show metadata if available + # Get metadata metadata = read_github_metadata(path_obj) + + # Build content + content = f"[blue]Path:[/blue] {path}\n" + if metadata: - click.echo(f" Metadata: {GITHUB_METADATA_FILE} present") if "description" in metadata: - click.echo(f" Description: {metadata['description']}") + content += f"[green]Description:[/green] {metadata['description']}\n" if "version" in metadata: - click.echo(f" Version: {metadata['version']}") - if "env_var" in metadata and metadata["env_var"]: - click.echo( - f" Environment Variable: {metadata['env_var']}" + content += ( + f"[yellow]Version:[/yellow] {metadata['version']}\n" ) + if "env_var" in metadata and metadata["env_var"]: + content += f"[magenta]Environment Variable:[/magenta] {metadata['env_var']}\n" + + # Capabilities with clear labels if "capabilities" in metadata: caps = metadata["capabilities"] if isinstance(caps, dict): - click.echo( - " Capabilities: " - + f"symbols={'✓' if caps.get('symbols') else '✗'}, " - + f"footprints={'✓' if caps.get('footprints') else '✗'}, " - + f"templates={'✓' if caps.get('templates') else '✗'}" - ) + content += "[white]Features:[/white] " + features = [] + if caps.get("symbols"): + features.append("[green]✓ Symbols[/green]") + else: + features.append("[red]✗ Symbols[/red]") + if caps.get("footprints"): + features.append("[green]✓ Footprints[/green]") + else: + features.append("[red]✗ Footprints[/red]") + if caps.get("templates"): + features.append("[green]✓ Templates[/green]") + else: + features.append("[red]✗ Templates[/red]") + content += " | ".join(features) else: - click.echo(f" Metadata: No {GITHUB_METADATA_FILE} file") - - # Check for existence of key folders - folders = [] - if (path_obj / "symbols").exists(): - folders.append("symbols") - if (path_obj / "footprints").exists(): - folders.append("footprints") - if (path_obj / "templates").exists(): - folders.append("templates") - click.echo( - f" Folders: {', '.join(folders) if folders else 'none'}" + content += ( + f"[dim]No {GITHUB_METADATA_FILE} metadata file found[/dim]" + ) + + # Status indicator + status = ( + "[green]✓ CURRENT[/green]" + if path == current_library + else "[dim]Available[/dim]" ) - else: - click.echo(f" - {name}: {path}{current_marker}") + title = f"[bold cyan]{name}[/bold cyan] [{status}]" - if library_type in ["all", "cloud"] and types["cloud"]: - click.echo("\nCloud Libraries (3D models):") - for lib in types["cloud"]: - name = lib.get("name", "unnamed") - path = lib.get("path", "unknown") - path_obj = Path(path) + console.print( + Panel( + content, + title=title, + border_style="cyan" if path == current_library else "dim", + ) + ) + console.print() + else: + # Compact mode: Simple table + table = Table( + show_header=True, header_style="bold magenta", border_style="cyan" + ) - # Mark current library - current_marker = "" - if path == current_library: - current_marker = " (current)" + table.add_column("Library", style="cyan", no_wrap=True) + table.add_column("Status", justify="center", style="green", width=12) + table.add_column("Path", style="blue") - if verbose: - click.echo(f" - {name}{current_marker}:") - click.echo(f" Path: {path}") + for lib in types["github"]: + name = lib.get("name", "unnamed") + path = lib.get("path", "unknown") - # Show metadata if available + status = ( + "[green]✓ Current[/green]" + if path == current_library + else "[dim]Available[/dim]" + ) + + table.add_row(f"[bold]{name}[/bold]", status, path) + + console.print(table) + console.print() + + # Display Cloud Libraries + if library_type in ["all", "cloud"] and types["cloud"]: + console.print( + "\n[bold cyan]Cloud Libraries[/bold cyan] [dim](3D models)[/dim]" + ) + console.print() + + if verbose: + # Verbose mode: Individual panels for each library + for lib in types["cloud"]: + name = lib.get("name", "unnamed") + path = lib.get("path", "unknown") + path_obj = Path(path) + + # Get metadata metadata = read_cloud_metadata(path_obj) + + # Build content + content = f"[blue]Path:[/blue] {path}\n" + if metadata: - click.echo(f" Metadata: {CLOUD_METADATA_FILE} present") if "description" in metadata: - click.echo(f" Description: {metadata['description']}") + content += f"[green]Description:[/green] {metadata['description']}\n" if "version" in metadata: - click.echo(f" Version: {metadata['version']}") - if "env_var" in metadata and metadata["env_var"]: - click.echo( - f" Environment Variable: {metadata['env_var']}" + content += ( + f"[yellow]Version:[/yellow] {metadata['version']}\n" ) + if "env_var" in metadata and metadata["env_var"]: + content += f"[magenta]Environment Variable:[/magenta] {metadata['env_var']}\n" + + # Model count if "model_count" in metadata: - click.echo(f" 3D Models: {metadata['model_count']}") + content += ( + f"[white]3D Models:[/white] {metadata['model_count']}" + ) + else: + # Count models + count = 0 + for ext in [".step", ".stp", ".wrl", ".wings"]: + count += len(list(path_obj.glob(f"**/*{ext}"))) + content += f"[white]3D Models:[/white] {count} [dim](counted)[/dim]" else: - click.echo(f" Metadata: No {CLOUD_METADATA_FILE} file") - - # Count 3D model files if metadata not available or to verify - if not metadata or "model_count" not in metadata: - model_count = 0 + content += ( + f"[dim]No {CLOUD_METADATA_FILE} metadata file found[/dim]" + ) + # Still count models + count = 0 for ext in [".step", ".stp", ".wrl", ".wings"]: - model_count += len(list(path_obj.glob(f"**/*{ext}"))) - click.echo(f" 3D Models: {model_count} (counted)") - else: - click.echo(f" - {name}: {path}{current_marker}") + count += len(list(path_obj.glob(f"**/*{ext}"))) + content += ( + f"\n[white]3D Models:[/white] {count} [dim](counted)[/dim]" + ) + + # Status indicator + status = ( + "[green]✓ CURRENT[/green]" + if path == current_library + else "[dim]Available[/dim]" + ) + title = f"[bold cyan]{name}[/bold cyan] [{status}]" + + console.print( + Panel( + content, + title=title, + border_style="cyan" if path == current_library else "dim", + ) + ) + console.print() + else: + # Compact mode: Simple table + table = Table( + show_header=True, header_style="bold magenta", border_style="cyan" + ) + + table.add_column("Library", style="cyan", no_wrap=True) + table.add_column("Status", justify="center", style="green", width=12) + table.add_column("Path", style="blue") + + for lib in types["cloud"]: + name = lib.get("name", "unnamed") + path = lib.get("path", "unknown") + + status = ( + "[green]✓ Current[/green]" + if path == current_library + else "[dim]Available[/dim]" + ) + + table.add_row(f"[bold]{name}[/bold]", status, path) + + console.print(table) + console.print() + + # Add summary panel + total_libs = len(libraries) + github_count = len(types["github"]) + cloud_count = len(types["cloud"]) + + summary_content = f"[green]Total Libraries:[/green] {total_libs}\n" + summary_content += ( + f"[cyan]GitHub:[/cyan] {github_count} [blue]Cloud:[/blue] {cloud_count}" + ) + + console.print( + Panel( + summary_content, + title="[bold cyan]Summary[/bold cyan]", + border_style="cyan", + width=35, + ) + ) # Print helpful message if no libraries match the filter if library_type == "github" and not types["github"]: - click.echo("No GitHub libraries configured.") - click.echo("Use 'kilm init' to initialize a GitHub library.") + console.print( + Panel( + "[yellow]No GitHub libraries configured.[/yellow]\n\n" + "[cyan]Get Started:[/cyan]\n" + "• Initialize a GitHub library: [blue]kilm init[/blue]", + title="[bold yellow]⚠️ No GitHub Libraries[/bold yellow]", + border_style="yellow", + ) + ) elif library_type == "cloud" and not types["cloud"]: - click.echo("No cloud libraries configured.") - click.echo("Use 'kilm add-3d' to add a cloud-based 3D model library.") + console.print( + Panel( + "[yellow]No cloud libraries configured.[/yellow]\n\n" + "[cyan]Get Started:[/cyan]\n" + "• Add a 3D model library: [blue]kilm add-3d[/blue]", + title="[bold yellow]⚠️ No Cloud Libraries[/bold yellow]", + border_style="yellow", + ) + ) except Exception as e: - click.echo(f"Error listing configurations: {e}", err=True) + console.print(f"[red]Error listing configurations: {e}[/red]") sys.exit(1) -@config.command() -@click.argument("library_name", required=False) -@click.option( - "--type", - "library_type", - type=click.Choice(["github", "cloud"]), - default="github", - help="Type of library to set as default (github=symbols/footprints, cloud=3D models)", - show_default=True, -) -def set_default(library_name, library_type): +def set_default( + library_name: Annotated[ + Optional[str], typer.Argument(help="Name of library to set as default") + ] = None, + library_type: Annotated[ + str, + typer.Option( + "--type", + help="Type of library to set as default (github=symbols/footprints, cloud=3D models)", + ), + ] = "github", +) -> None: """Set a library as the default for operations. Sets the specified library as the default for future operations. @@ -234,11 +362,13 @@ def set_default(library_name, library_type): libraries = config.get_libraries(library_type) if not libraries: - click.echo(f"No {library_type} libraries configured.") + console.print(f"No {library_type} libraries configured.") if library_type == "github": - click.echo("Use 'kilm init' to initialize a GitHub library.") + console.print("Use 'kilm init' to initialize a GitHub library.") else: - click.echo("Use 'kilm add-3d' to add a cloud-based 3D model library.") + console.print( + "Use 'kilm add-3d' to add a cloud-based 3D model library." + ) sys.exit(1) # Get current library path @@ -246,7 +376,7 @@ def set_default(library_name, library_type): # If library name not provided, prompt for selection if not library_name: - click.echo(f"\nAvailable {library_type} libraries:") + console.print(f"\nAvailable {library_type} libraries:") # Show numbered list of libraries for i, lib in enumerate(libraries): @@ -258,12 +388,12 @@ def set_default(library_name, library_type): if path == current_library: current_marker = " (current)" - click.echo(f"{i + 1}. {name}{current_marker}") + console.print(f"{i + 1}. {name}{current_marker}") # Get selection while True: try: - selection = click.prompt( + selection = typer.prompt( "Select library (number)", type=int, default=1 ) if 1 <= selection <= len(libraries): @@ -272,11 +402,11 @@ def set_default(library_name, library_type): library_path = selected_lib.get("path") break else: - click.echo( + console.print( f"Please enter a number between 1 and {len(libraries)}" ) except ValueError: - click.echo("Please enter a valid number") + console.print("Please enter a valid number") else: # Find the library by name library_path = None @@ -286,41 +416,40 @@ def set_default(library_name, library_type): break if not library_path: - click.echo(f"No {library_type} library named '{library_name}' found.") - click.echo("Use 'kilm config list' to see available libraries.") + console.print( + f"No {library_type} library named '{library_name}' found." + ) + console.print("Use 'kilm config list' to see available libraries.") sys.exit(1) # Set as current library if library_path is None: - click.echo( - f"Error: Could not find path for library '{library_name}'", err=True + console.print( + f"[red]Error: Could not find path for library '{library_name}'[/red]" ) sys.exit(1) config.set_current_library(library_path) - click.echo(f"Set {library_type} library '{library_name}' as default.") - click.echo(f"Path: {library_path}") + console.print(f"Set {library_type} library '{library_name}' as default.") + console.print(f"Path: {library_path}") except Exception as e: - click.echo(f"Error setting default library: {e}", err=True) + console.print(f"[red]Error setting default library: {e}[/red]") sys.exit(1) -@config.command() -@click.argument("library_name", required=True) -@click.option( - "--type", - "library_type", - type=click.Choice(["github", "cloud", "all"]), - default="all", - help="Type of library to remove (all=remove from both types)", - show_default=True, -) -@click.option( - "--force", - is_flag=True, - help="Force removal without confirmation", -) -def remove(library_name, library_type, force): +def remove( + library_name: Annotated[str, typer.Argument(help="Name of library to remove")], + library_type: Annotated[ + str, + typer.Option( + "--type", + help="Type of library to remove (all=remove from both types)", + ), + ] = "all", + force: Annotated[ + bool, typer.Option("--force", help="Force removal without confirmation") + ] = False, +) -> None: """Remove a library from the configuration. Removes the specified library from the KiCad Library Manager configuration. @@ -359,10 +488,12 @@ def remove(library_name, library_type, force): if not matching_libraries: if library_type == "all": - click.echo(f"No library named '{library_name}' found.") + console.print(f"No library named '{library_name}' found.") else: - click.echo(f"No {library_type} library named '{library_name}' found.") - click.echo("Use 'kilm config list' to see available libraries.") + console.print( + f"No {library_type} library named '{library_name}' found." + ) + console.print("Use 'kilm config list' to see available libraries.") sys.exit(1) # Confirm removal @@ -370,16 +501,16 @@ def remove(library_name, library_type, force): for lib in matching_libraries: lib_type = lib.get("type", "unknown") lib_path = lib.get("path", "unknown") - click.echo( + console.print( f"Will remove {lib_type} library '{library_name}' from configuration." ) - click.echo(f"Path: {lib_path}") + console.print(f"Path: {lib_path}") if lib_path == current_library: - click.echo("Warning: This is the current default library.") + console.print("Warning: This is the current default library.") - if not click.confirm("Continue?"): - click.echo("Operation cancelled.") + if not typer.confirm("Continue?"): + console.print("Operation cancelled.") return # Remove libraries @@ -392,26 +523,21 @@ def remove(library_name, library_type, force): if removed_count > 0: if removed_count == 1: - click.echo(f"Removed library '{library_name}' from configuration.") + console.print(f"Removed library '{library_name}' from configuration.") else: - click.echo( + console.print( f"Removed {removed_count} instances of library '{library_name}' from configuration." ) # Check if we removed the current library current_library_new = config.get_current_library() if current_library and current_library != current_library_new: - click.echo( + console.print( "Note: Default library was changed as the previous default was removed." ) else: - click.echo("No libraries were removed.") + console.print("No libraries were removed.") except Exception as e: - click.echo(f"Error removing library: {e}", err=True) + console.print(f"[red]Error removing library: {e}[/red]") sys.exit(1) - - -# Register the config command -if __name__ == "__main__": - config() diff --git a/kicad_lib_manager/commands/setup/command.py b/kicad_lib_manager/commands/setup/command.py index af60858..dc76a13 100644 --- a/kicad_lib_manager/commands/setup/command.py +++ b/kicad_lib_manager/commands/setup/command.py @@ -8,6 +8,8 @@ import typer from rich.console import Console +from rich.panel import Panel +from rich.table import Table from ...services.config_service import Config, LibraryDict from ...services.library_service import LibraryService @@ -227,11 +229,20 @@ def setup( # Print what we're setting up if config_symbol_libs: - console.print("\nSetting up symbol libraries:") + console.print() + table = Table( + title="[bold cyan]Setting up symbol libraries[/bold cyan]", + show_header=True, + header_style="bold magenta", + ) + table.add_column("Library", style="cyan", no_wrap=True) + table.add_column("Path", style="blue") + table.add_column("Environment Variable", style="green") + for lib in config_symbol_libs: lib_name = lib.get("name", "unnamed") lib_path = lib.get("path", "unknown") - console.print(f" - {lib_name}: {lib_path}") + env_var_display = "None" # Read metadata to get environment variable name try: @@ -241,14 +252,15 @@ def setup( if env_var and isinstance(env_var, str): # Store all GitHub libraries with their env vars config_lib_paths[env_var] = lib_path - console.print(f" Using environment variable: {env_var}") + env_var_display = f"[green]{env_var}[/green]" else: - console.print(" No environment variable configured") + env_var_display = "[yellow]Not configured[/yellow]" else: - console.print(" No metadata or environment variable found") + env_var_display = "[yellow]No metadata[/yellow]" except Exception as e: - if verbose: - console.print(f" Error reading metadata: {e}") + env_var_display = ( + f"[red]Error: {e}[/red]" if verbose else "[red]Error[/red]" + ) # If we're using the first symbol library as the main library if not kicad_lib_dir and lib == config_symbol_libs[0]: @@ -257,12 +269,25 @@ def setup( if "KICAD_USER_LIB" not in config_lib_paths: config_lib_paths["KICAD_USER_LIB"] = lib_path + table.add_row(f"[bold]{lib_name}[/bold]", lib_path, env_var_display) + + console.print(table) + if config_3d_libs: - console.print("\nSetting up 3D model libraries:") + console.print() + table = Table( + title="[bold cyan]Setting up 3D model libraries[/bold cyan]", + show_header=True, + header_style="bold magenta", + ) + table.add_column("Library", style="cyan", no_wrap=True) + table.add_column("Path", style="blue") + table.add_column("Environment Variable", style="green") + for lib in config_3d_libs: lib_name = lib.get("name", "unnamed") lib_path = lib.get("path", "unknown") - console.print(f" - {lib_name}: {lib_path}") + env_var_display = "None" # Read metadata to get environment variable name try: @@ -272,19 +297,24 @@ def setup( if env_var and isinstance(env_var, str): # Store all 3D libraries with their env vars config_lib_paths[env_var] = lib_path - console.print(f" Using environment variable: {env_var}") + env_var_display = f"[green]{env_var}[/green]" else: - console.print(" No environment variable configured") + env_var_display = "[yellow]Not configured[/yellow]" else: - console.print(" No metadata or environment variable found") + env_var_display = "[yellow]No metadata[/yellow]" except Exception as e: - if verbose: - console.print(f" Error reading metadata: {e}") + env_var_display = ( + f"[red]Error: {e}[/red]" if verbose else "[red]Error[/red]" + ) # Use the first 3D library as the default if not specified if not kicad_3d_dir and lib == config_3d_libs[0]: kicad_3d_dir = lib_path + table.add_row(f"[bold]{lib_name}[/bold]", lib_path, env_var_display) + + console.print(table) + except Exception as e: # If there's any issue with config, continue with environment variables if verbose: @@ -301,7 +331,7 @@ def setup( kicad_lib_dir = env_var env_lib_paths["KICAD_USER_LIB"] = env_var console.print( - f"Using KiCad library from environment variable: {kicad_lib_dir}" + f"[green]Using KiCad library from environment variable:[/green] [blue]{kicad_lib_dir}[/blue]" ) else: console.print("[red]Error: KICAD_USER_LIB not set and not provided[/red]") @@ -316,7 +346,7 @@ def setup( kicad_3d_dir = env_var env_lib_paths["KICAD_3D_LIB"] = env_var console.print( - f"Using 3D model library from environment variable: {kicad_3d_dir}" + f"[green]Using 3D model library from environment variable:[/green] [blue]{kicad_3d_dir}[/blue]" ) else: console.print( @@ -349,25 +379,47 @@ def setup( if kicad_3d_dir: kicad_3d_dir = expand_user_path(kicad_3d_dir) - console.print(f"\nUsing KiCad symbol library directory: {kicad_lib_dir}") + # Create configuration summary panel + config_content = ( + f"[green]Symbol library directory:[/green] [blue]{kicad_lib_dir}[/blue]\n" + ) if kicad_3d_dir: - console.print(f"Using KiCad main 3D models directory: {kicad_3d_dir}") + config_content += ( + f"[green]3D models directory:[/green]\n[blue]{kicad_3d_dir}[/blue]" + ) + else: + config_content += "[yellow]3D models directory: Not configured[/yellow]" + + console.print() + console.print( + Panel( + config_content, + title="[bold cyan]Configuration Summary[/bold cyan]", + border_style="cyan", + ) + ) # Find KiCad configuration try: kicad_config = LibraryService.find_kicad_config() - console.print(f"Found KiCad configuration at: {kicad_config}") + console.print( + f"[green]Found KiCad configuration at:[/green] [blue]{kicad_config}[/blue]" + ) # Fix any invalid URIs in existing library entries uri_changes = fix_invalid_uris(kicad_config, True, max_backups, dry_run) if uri_changes: if dry_run: - console.print("Would fix invalid library URIs in KiCad configuration") + console.print( + "[yellow]Would fix invalid library URIs in KiCad configuration[/yellow]" + ) else: - console.print("Fixed invalid library URIs in KiCad configuration") + console.print( + "[green]Fixed invalid library URIs in KiCad configuration[/green]" + ) except Exception as e: console.print(f"[red]Error finding KiCad configuration: {e}[/red]") - raise typer.Exit(1) + raise typer.Exit(1) from e # Prepare environment variables dictionary env_vars = {} @@ -395,19 +447,23 @@ def setup( if env_changes_needed: if dry_run: console.print( - "Would update environment variables in KiCad configuration" + "[yellow]Would update environment variables in KiCad configuration[/yellow]" ) else: - console.print("Updated environment variables in KiCad configuration") - console.print("Created backup of kicad_common.json") + console.print( + "[green]Updated environment variables in KiCad configuration[/green]" + ) + console.print("[blue]Created backup of kicad_common.json[/blue]") # Show all environment variables that were set - console.print("\nEnvironment variables set in KiCad:") + console.print( + "\n[bold cyan]Environment variables set in KiCad:[/bold cyan]" + ) for var_name, value in env_vars.items(): - console.print(f" {var_name} = {value}") + console.print(f" [cyan]{var_name}[/cyan] = [blue]{value}[/blue]") else: console.print( - "Environment variables already up to date in KiCad configuration" + "[blue]Environment variables already up to date in KiCad configuration[/blue]" ) except Exception as e: console.print(f"[red]Error updating environment variables: {e}[/red]") @@ -441,23 +497,23 @@ def setup( if sym_table.exists(): create_backup(sym_table, max_backups) - console.print("Created backup of symbol library table") + console.print("[blue]Created backup of symbol library table[/blue]") if fp_table.exists(): create_backup(fp_table, max_backups) - console.print("Created backup of footprint library table") + console.print("[blue]Created backup of footprint library table[/blue]") if added_libraries: if dry_run: console.print( - f"Would add {len(added_libraries)} libraries to KiCad configuration" + f"[yellow]Would add {len(added_libraries)} libraries to KiCad configuration[/yellow]" ) else: console.print( - f"Added {len(added_libraries)} libraries to KiCad configuration" + f"[green]Added {len(added_libraries)} libraries to KiCad configuration[/green]" ) else: - console.print("No new libraries to add") + console.print("[blue]No new libraries to add[/blue]") # Pin libraries if requested pinned_changes_needed = False @@ -490,28 +546,35 @@ def setup( if pinned_changes_needed: if dry_run: console.print( - f"Would pin {len(symbol_libs)} symbol and {len(footprint_libs)} footprint libraries in KiCad" + f"[yellow]Would pin {len(symbol_libs)} symbol and {len(footprint_libs)} footprint libraries in KiCad[/yellow]" ) else: console.print( - f"Pinned {len(symbol_libs)} symbol and {len(footprint_libs)} footprint libraries in KiCad" + f"[green]Pinned {len(symbol_libs)} symbol and {len(footprint_libs)} footprint libraries in KiCad[/green]" ) else: - console.print("All libraries already pinned in KiCad") + console.print("[blue]All libraries already pinned in KiCad[/blue]") except Exception as e: console.print(f"[red]Error pinning libraries: {e}[/red]") if not changes_needed and not env_changes_needed and not pinned_changes_needed: - console.print("No changes needed, configuration is up to date") + console.print("[blue]No changes needed, configuration is up to date[/blue]") elif dry_run: - console.print("Dry run: No changes were made") + console.print("[yellow]Dry run: No changes were made[/yellow]") except Exception as e: console.print(f"[red]Error adding libraries: {e}[/red]") if verbose: import traceback console.print(traceback.format_exc()) - raise typer.Exit(1) + raise typer.Exit(1) from None if not dry_run and (changes_needed or env_changes_needed or pinned_changes_needed): - console.print("Setup complete! Restart KiCad for changes to take effect.") + console.print() + console.print( + Panel( + "[bold green]Setup complete! Restart KiCad for changes to take effect.[/bold green]", + title="[bold green]✅ Success[/bold green]", + border_style="green", + ) + ) diff --git a/kicad_lib_manager/commands/status/command.py b/kicad_lib_manager/commands/status/command.py index bce1e48..bd51c01 100644 --- a/kicad_lib_manager/commands/status/command.py +++ b/kicad_lib_manager/commands/status/command.py @@ -4,6 +4,7 @@ import json from pathlib import Path +from typing import Annotated import typer import yaml @@ -18,7 +19,16 @@ console = Console() -def status() -> None: +def status( + verbose: Annotated[ + bool, + typer.Option( + "--verbose", + "-v", + help="Show detailed configured libraries tables", + ), + ] = False, +) -> None: """Show the current KiCad configuration status""" try: # Initialize services @@ -38,8 +48,9 @@ def status() -> None: # Check pinned libraries _check_pinned_libraries(kicad_config, kicad_service) - # Check configured libraries - _show_configured_libraries(kicad_config, kicad_service) + # Check configured libraries (only in verbose mode) + if verbose: + _show_configured_libraries(kicad_config, kicad_service) except Exception as e: console.print(f"[red]Error getting KiCad configuration: {e}[/red]") @@ -281,7 +292,7 @@ def _show_configured_libraries(kicad_config: Path, kicad_service: KiCadService) table.add_column("URI", style="blue") for lib in sym_libs: - table.add_row(lib["name"], lib["uri"]) + table.add_row(lib.get("name", ""), lib.get("uri", "")) console.print(table) else: @@ -294,7 +305,7 @@ def _show_configured_libraries(kicad_config: Path, kicad_service: KiCadService) table.add_column("URI", style="blue") for lib in fp_libs: - table.add_row(lib["name"], lib["uri"]) + table.add_row(lib.get("name", ""), lib.get("uri", "")) console.print(table) else: diff --git a/kicad_lib_manager/commands/sync/__init__.py b/kicad_lib_manager/commands/sync/__init__.py index 4f15a3d..b6f578f 100644 --- a/kicad_lib_manager/commands/sync/__init__.py +++ b/kicad_lib_manager/commands/sync/__init__.py @@ -1,7 +1,14 @@ -""" -Sync command - Update/sync library content from git repositories -""" +import typer from .command import sync -__all__ = ["sync", "check_for_library_changes"] +# Create Typer app and add the sync command as callback +sync_app = typer.Typer( + name="sync", + help="Update/sync library content from git repositories", + rich_markup_mode="rich", + callback=sync, + invoke_without_command=True, +) + +__all__ = ["sync", "sync_app"] diff --git a/kicad_lib_manager/commands/sync/command.py b/kicad_lib_manager/commands/sync/command.py index 70bdc71..1fdedf0 100644 --- a/kicad_lib_manager/commands/sync/command.py +++ b/kicad_lib_manager/commands/sync/command.py @@ -5,35 +5,28 @@ import subprocess from pathlib import Path +from typing import Annotated, List, Tuple -import click +import typer +from rich.console import Console from ...services.config_service import Config - -@click.command() -@click.option( - "--dry-run", - is_flag=True, - default=False, - help="Show what would be synced without making changes", - show_default=True, -) -@click.option( - "--verbose", - is_flag=True, - default=False, - help="Show detailed output", - show_default=True, -) -@click.option( - "--auto-setup", - is_flag=True, - default=False, - help="Run 'kilm setup' automatically if new libraries are detected", - show_default=True, -) -def sync(dry_run, verbose, auto_setup): +console = Console() + + +def sync( + dry_run: Annotated[ + bool, typer.Option(help="Show what would be synced without making changes") + ] = False, + verbose: Annotated[bool, typer.Option(help="Show detailed output")] = False, + auto_setup: Annotated[ + bool, + typer.Option( + help="Run 'kilm setup' automatically if new libraries are detected" + ), + ] = False, +) -> None: """Sync all configured GitHub libraries with git pull. This command syncs all configured GitHub libraries (symbols/footprints) @@ -44,150 +37,167 @@ def sync(dry_run, verbose, auto_setup): and recommend running 'kilm setup' if needed. Use --auto-setup to run setup automatically when new libraries are detected. """ - config = Config() - - # Get GitHub libraries from config (symbols/footprints) - libraries = config.get_libraries(library_type="github") - - if not libraries: - click.echo("No GitHub libraries configured. Use 'kilm init' to add a library.") - return - - click.echo(f"Syncing {len(libraries)} KiCad GitHub libraries...") - - updated_count = 0 # Actually changed - up_to_date_count = 0 # Already at latest version - skipped_count = 0 # Could not sync (not git, etc.) - failed_count = 0 # Git pull failed - - # Track libraries that have changes that might require setup - libraries_with_changes = [] - - for lib in libraries: - lib_name = lib.get("name", "unnamed") - lib_path = lib.get("path") - - if not lib_path: - click.echo(f" Skipping {lib_name}: No path defined") - skipped_count += 1 - continue - - lib_path = Path(lib_path) - if not lib_path.exists(): - click.echo(f" Skipping {lib_name}: Path does not exist: {lib_path}") - skipped_count += 1 - continue - - git_dir = lib_path / ".git" - if not git_dir.exists() or not git_dir.is_dir(): - click.echo(f" Skipping {lib_name}: Not a git repository: {lib_path}") - skipped_count += 1 - continue - - # Prepare to run git pull - click.echo(f" Syncing {lib_name} at {lib_path}...") - - if dry_run: - click.echo(f" Dry run: would execute 'git pull' in {lib_path}") - updated_count += 1 - continue - - try: - # Run git pull - result = subprocess.run( - ["git", "pull"], - cwd=lib_path, - capture_output=True, - text=True, - check=False, + try: + config = Config() + + # Get GitHub libraries from config (symbols/footprints) + libraries = config.get_libraries(library_type="github") + + if not libraries: + console.print( + "[yellow]No GitHub libraries configured. Use 'kilm init' to add a library.[/yellow]" ) + return + + console.print( + f"[cyan]Syncing {len(libraries)} KiCad GitHub libraries...[/cyan]" + ) - if result.returncode == 0: - output = result.stdout.strip() or "Already up to date." - is_updated = "Already up to date" not in output + updated_count = 0 # Actually changed + up_to_date_count = 0 # Already at latest version + skipped_count = 0 # Could not sync (not git, etc.) + failed_count = 0 # Git pull failed - if verbose: - click.echo(f" Success: {output}") - # Also show the short status for consistency - if is_updated: - click.echo(" Updated") + # Track libraries that have changes that might require setup + libraries_with_changes: List[Tuple[str, Path, List[str]]] = [] + + for lib in libraries: + lib_name = lib.get("name", "unnamed") + lib_path = lib.get("path") + + if not lib_path: + console.print( + f" [yellow]Skipping {lib_name}: No path defined[/yellow]" + ) + skipped_count += 1 + continue + + lib_path = Path(lib_path) + if not lib_path.exists(): + console.print( + f" [yellow]Skipping {lib_name}: Path does not exist: {lib_path}[/yellow]" + ) + skipped_count += 1 + continue + + git_dir = lib_path / ".git" + if not git_dir.exists() or not git_dir.is_dir(): + console.print( + f" [yellow]Skipping {lib_name}: Not a git repository: {lib_path}[/yellow]" + ) + skipped_count += 1 + continue + + # Prepare to run git pull + console.print(f" [cyan]Syncing {lib_name} at {lib_path}...[/cyan]") + + if dry_run: + console.print( + f" [blue]Dry run: would execute 'git pull' in {lib_path}[/blue]" + ) + updated_count += 1 + continue + + try: + # Run git pull + result = subprocess.run( + ["git", "pull"], + cwd=lib_path, + capture_output=True, + text=True, + check=False, + ) + + if result.returncode == 0: + output = result.stdout.strip() or "Already up to date." + is_updated = "Already up to date" not in output + + if verbose: + console.print(f" [green]Success: {output}[/green]") + # Also show the short status for consistency + if is_updated: + console.print(" [green]Updated[/green]") + else: + console.print(" [blue]Up to date[/blue]") else: - click.echo(" Up to date") - else: + if is_updated: + console.print(" [green]Updated[/green]") + else: + console.print(" [blue]Up to date[/blue]") + + # Update counters regardless of verbose flag if is_updated: - click.echo(" Updated") + updated_count += 1 else: - click.echo(" Up to date") + up_to_date_count += 1 - # Update counters regardless of verbose flag - if is_updated: - updated_count += 1 - else: - up_to_date_count += 1 - - # Check if there are new library files that would require setup - if is_updated: - changes_require_setup = check_for_library_changes(lib_path) - if changes_require_setup: - libraries_with_changes.append( - (lib_name, lib_path, changes_require_setup) - ) - if verbose: - click.echo( - f" Detected new library content: {', '.join(changes_require_setup)}" + # Check if there are new library files that would require setup + if is_updated: + changes_require_setup = check_for_library_changes(lib_path) + if changes_require_setup: + libraries_with_changes.append( + (lib_name, lib_path, changes_require_setup) ) - else: - click.echo(f" Failed: {result.stderr.strip()}") - failed_count += 1 + if verbose: + console.print( + f" [yellow]Detected new library content: {', '.join(changes_require_setup)}[/yellow]" + ) + else: + console.print(f" [red]Failed: {result.stderr.strip()}[/red]") + failed_count += 1 - except Exception as e: - click.echo(f" Error: {str(e)}") - failed_count += 1 - - # Summary - click.echo("\nSync Summary:") - click.echo(f" {updated_count} libraries synced") - click.echo(f" {up_to_date_count} libraries up to date") - click.echo(f" {skipped_count} libraries skipped") - click.echo(f" {failed_count} libraries failed") - - # If libraries with changes were detected, suggest running setup - if libraries_with_changes: - click.echo("\nNew library content detected in:") - for lib_name, _lib_path, changes in libraries_with_changes: - click.echo(f" - {lib_name}: {', '.join(changes)}") - - if auto_setup: - click.echo("\nRunning 'kilm setup' to configure new libraries...") - # Import at runtime to avoid circular imports - try: - from ...commands.setup import setup as setup_cmd + except Exception as e: + console.print(f" [red]Error: {str(e)}[/red]") + failed_count += 1 - # Create context using the command's built-in context factory - ctx = setup_cmd.make_context( - "setup", args=[], parent=click.get_current_context() + # Summary + console.print("\n[bold cyan]Sync Summary:[/bold cyan]") + console.print(f" [green]{updated_count}[/green] libraries synced") + console.print(f" [blue]{up_to_date_count}[/blue] libraries up to date") + console.print(f" [yellow]{skipped_count}[/yellow] libraries skipped") + console.print(f" [red]{failed_count}[/red] libraries failed") + + # If libraries with changes were detected, suggest running setup + if libraries_with_changes: + console.print("\n[yellow]New library content detected in:[/yellow]") + for lib_name, _lib_path, changes in libraries_with_changes: + console.print(f" - [cyan]{lib_name}[/cyan]: {', '.join(changes)}") + + if auto_setup: + console.print( + "\n[green]Running 'kilm setup' to configure new libraries...[/green]" ) - setup_cmd.invoke(ctx) - except ImportError: - click.echo( - "Error: Could not import setup command. Please run 'kilm setup' manually." + # Import at runtime to avoid circular imports + try: + from ...commands.setup.command import setup as setup_cmd + + setup_cmd() + except ImportError: + console.print( + "[red]Error: Could not import setup command. Please run 'kilm setup' manually.[/red]" + ) + else: + console.print( + "\n[yellow]You should run 'kilm setup' to configure the new libraries in KiCad.[/yellow]" + ) + console.print( + "[blue]Run 'kilm sync --auto-setup' next time to automatically run setup after sync.[/blue]" ) else: - click.echo( - "\nYou should run 'kilm setup' to configure the new libraries in KiCad." + console.print( + "\n[blue]No new libraries detected that would require running 'kilm setup'.[/blue]" ) - click.echo( - "Run 'kilm sync --auto-setup' next time to automatically run setup after sync." + console.print( + "[blue]Use 'kilm status' to check your current configuration.[/blue]" ) - else: - click.echo( - "\nNo new libraries detected that would require running 'kilm setup'." - ) - click.echo("Use 'kilm status' to check your current configuration.") + + except Exception as e: + console.print(f"[red]Error: {e}[/red]") + raise typer.Exit(1) from e # TODO: Should be in services or utils -def check_for_library_changes(lib_path): +def check_for_library_changes(lib_path: Path) -> List[str]: """ Check if git pull changes indicate new libraries that would require setup. Uses git diff to analyze what files were added/changed in the pull. @@ -252,13 +262,13 @@ def check_for_library_changes(lib_path): return changes -def _is_symbol_library_change(path): +def _is_symbol_library_change(path: str) -> bool: """Check if a path change indicates a symbol library change.""" # Look for .kicad_sym files in symbols directory return path.startswith("symbols/") and path.endswith(".kicad_sym") -def _is_footprint_library_change(path): +def _is_footprint_library_change(path: str) -> bool: """Check if a path change indicates a footprint library change.""" # Look for .pretty directories or files within them return (path.startswith("footprints/") and path.endswith(".pretty")) or ( @@ -266,13 +276,13 @@ def _is_footprint_library_change(path): ) -def _is_template_change(path): +def _is_template_change(path: str) -> bool: """Check if a path change indicates a template change.""" # Look for metadata.yaml files in template directories return path.startswith("templates/") and path.endswith("metadata.yaml") -def _check_current_library_state(lib_path): +def _check_current_library_state(lib_path: Path) -> List[str]: """ Fallback method to check current library state when git diff is not available. This is used when we can't determine what changed in the pull. diff --git a/kicad_lib_manager/commands/template/__init__.py b/kicad_lib_manager/commands/template/__init__.py index 4d98761..0c1fd19 100644 --- a/kicad_lib_manager/commands/template/__init__.py +++ b/kicad_lib_manager/commands/template/__init__.py @@ -1,3 +1,22 @@ -from .command import template +import typer -__all__ = ["template"] +from .command import create, list_templates, main_callback, make + +# Create Typer app with subcommands +template_app = typer.Typer( + name="template", + help="Manage KiCad project templates", + rich_markup_mode="rich", + callback=main_callback, + invoke_without_command=True, + no_args_is_help=True, +) + +# Add subcommands +template_app.command("create", help="Create a new KiCad project from a template")( + create +) +template_app.command("make", help="Create a template from an existing project")(make) +template_app.command("list", help="List all available templates")(list_templates) + +__all__ = ["template_app", "create", "make", "list_templates"] diff --git a/kicad_lib_manager/commands/template/command.py b/kicad_lib_manager/commands/template/command.py index 737ea1e..c3b137f 100644 --- a/kicad_lib_manager/commands/template/command.py +++ b/kicad_lib_manager/commands/template/command.py @@ -9,12 +9,16 @@ import sys import traceback from pathlib import Path +from typing import Annotated, List, Optional -import click import jinja2 import pathspec import questionary +import typer import yaml +from rich.console import Console +from rich.panel import Panel +from rich.table import Table from ...services.config_service import Config from ...utils.template import ( @@ -32,9 +36,11 @@ render_template_string, ) +console = Console() +err_console = Console(stderr=True) -@click.group() -def template(): + +def main_callback() -> None: """Manage KiCad project templates. This command group allows you to create new KiCad projects from templates, @@ -43,39 +49,33 @@ def template(): pass -@template.command() -@click.argument("name", required=False) -@click.argument("directory", required=False, type=click.Path()) -@click.option( - "--template", - help="Name of the template to use", - default=None, -) -@click.option( - "--library", - help="Name of the library containing the template", - default=None, -) -@click.option( - "--set-var", - multiple=True, - help="Set template variable in key=value format", -) -@click.option( - "--dry-run", - is_flag=True, - default=False, - help="Show what would be created without making changes", - show_default=True, -) -@click.option( - "--skip-hooks", - is_flag=True, - default=False, - help="Skip post-creation hooks", - show_default=True, -) -def create(name, directory, template, library, set_var, dry_run, skip_hooks): +def create( + name: Annotated[ + Optional[str], typer.Argument(help="Name of the project to create") + ] = None, + directory: Annotated[ + Optional[str], typer.Argument(help="Directory to create project in") + ] = None, + template: Annotated[ + Optional[str], typer.Option(help="Name of the template to use") + ] = None, + library: Annotated[ + Optional[str], typer.Option(help="Name of the library containing the template") + ] = None, + set_var: Annotated[ + Optional[List[str]], + typer.Option("--set-var", help="Set template variable in key=value format"), + ] = None, + dry_run: Annotated[ + bool, + typer.Option( + "--dry-run", help="Show what would be created without making changes" + ), + ] = False, + skip_hooks: Annotated[ + bool, typer.Option("--skip-hooks", help="Skip post-creation hooks") + ] = False, +) -> None: """Create a new KiCad project from a template. Creates a new KiCad project from a template in one of the configured libraries. @@ -114,8 +114,8 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): all_templates = find_all_templates(config) if not all_templates: - click.echo("No templates found in any configured libraries.") - click.echo("Use 'kilm template make' to create a template first.") + console.print("No templates found in any configured libraries.") + console.print("Use 'kilm template make' to create a template first.") return # Parse name and directory @@ -153,12 +153,12 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): break if not selected_template: - click.echo(f"Template '{template}' not found.") - click.echo("Available templates:") + console.print(f"Template '{template}' not found.") + console.print("Available templates:") for t_name, t_data in all_templates.items(): library = t_data.get("source_library", "unknown") description = t_data.get("description", "") - click.echo(f" {t_name} ({library}): {description}") + console.print(f" {t_name} ({library}): {description}") return else: # Interactive template selection using questionary @@ -175,22 +175,21 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): ).ask() if selected_template_name is None: # Handle cancellation - click.echo("Template selection cancelled.") + console.print("Template selection cancelled.") return selected_template = all_templates.get(selected_template_name) # Ensure selected_template is not None before proceeding if not selected_template: - click.echo("Error: No template selected.", err=True) + console.print("[red]Error: No template selected.[/red]") return # Get template directory template_path_str = selected_template.get("path") if not template_path_str: - click.echo( - f"Error: Template metadata for '{selected_template.get('name')}' is missing the 'path'.", - err=True, + err_console.print( + f"Error: Template metadata for '{selected_template.get('name')}' is missing the 'path'." ) return template_dir = Path(template_path_str) @@ -201,12 +200,12 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): with metadata_file.open() as f: metadata = yaml.safe_load(f) if not metadata: # Handle empty metadata file - click.echo( - f"Warning: Template metadata file is empty: {metadata_file}", err=True + err_console.print( + f"Warning: Template metadata file is empty: {metadata_file}" ) metadata = {} # Use empty dict to avoid downstream errors except Exception as e: - click.echo(f"Error reading template metadata {metadata_file}: {e}", err=True) + err_console.print(f"Error reading template metadata {metadata_file}: {e}") return # Get template variables from metadata @@ -217,7 +216,7 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): command_line_vars = {} # Variables set via --set-var # Parse --set-var options first - for var in set_var: + for var in set_var or []: if "=" in var: key, value = var.split("=", 1) command_line_vars[key.strip()] = value.strip() @@ -238,14 +237,14 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): variables["project_name"] = name # Show template info - click.echo() - click.echo(f"Using Template: {metadata.get('name', 'Unknown')}") - click.echo(f"Description: {metadata.get('description', 'N/A')}") + console.print() + console.print(f"Using Template: {metadata.get('name', 'Unknown')}") + console.print(f"Description: {metadata.get('description', 'N/A')}") if metadata.get("use_case"): - click.echo(f"Use case: {metadata.get('use_case')}") + console.print(f"Use case: {metadata.get('use_case')}") - click.echo() - click.echo("Template Variables:") + console.print() + console.print("Template Variables:") # Combine initial variables from args and --set-var variables.update(command_line_vars) @@ -263,7 +262,7 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): else "--set-var" ) if var_name in command_line_vars or (var_name == "project_name" and name): - click.echo( + console.print( f" {var_name}: {variables[var_name]} (from {source}) - {description}" ) continue # Skip prompting @@ -281,16 +280,15 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): except jinja2.exceptions.UndefinedError as e: # If a variable needed for the default hasn't been entered yet, # keep the original template string or empty if undefined errors occur early - click.echo( - f"Debug: Undefined variable for default of {var_name}: {e}. Default might be incomplete.", - err=True, + err_console.print( + f"Debug: Undefined variable for default of {var_name}: {e}. Default might be incomplete." ) rendered_default = ( "" # Or keep 'default'? Better to show empty than half-rendered? ) except Exception as e: - click.echo( - f"Warning: Could not render default for {var_name}: {e}", err=True + err_console.print( + f"Warning: Could not render default for {var_name}: {e}" ) rendered_default = default # Use original default on other errors @@ -302,7 +300,7 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): ).ask() if answer is None: # Handle Ctrl+C or cancellation - click.echo("Variable input cancelled.") + console.print("Variable input cancelled.") return # Exit the command gracefully # Store the answer for use in subsequent default renderings @@ -340,9 +338,8 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): original_default_template, variables ) except Exception as e: - click.echo( - f"Warning: Could not re-render default for {var_name}: {e}", - err=True, + err_console.print( + f"Warning: Could not re-render default for {var_name}: {e}" ) correct_default = variables[var_name] # Keep existing value on error @@ -352,14 +349,14 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): variables[var_name] == shown_default and variables[var_name] != correct_default ): - click.echo( + console.print( f"Updating default for '{var_name}': '{shown_default}' -> '{correct_default}'" ) variables[var_name] = correct_default # --- End Post-processing --- - click.echo() - click.echo( + console.print() + console.print( f"Final variables: {json.dumps(variables, indent=2)}" ) # Changed message for clarity @@ -381,9 +378,8 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): ) final_project_dir = project_dir / dir_name_rendered except Exception as e: - click.echo( - f"Warning: Could not render default directory_name '{directory_name_template}': {e}", - err=True, + err_console.print( + f"Warning: Could not render default directory_name '{directory_name_template}': {e}" ) # Fallback below @@ -391,47 +387,45 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): if not final_project_dir and "project_name" in variables: project_name_sanitized = variables["project_name"].lower().replace(" ", "-") final_project_dir = project_dir / project_name_sanitized - click.echo(f"Using project_name to determine directory: {final_project_dir}") + console.print(f"Using project_name to determine directory: {final_project_dir}") # Final check if we have a directory if not final_project_dir: - click.echo( - "Error: Cannot determine project directory. Ensure 'project_name' or 'directory_name' variable is properly handled.", - err=True, + err_console.print( + "Error: Cannot determine project directory. Ensure 'project_name' or 'directory_name' variable is properly handled." ) return # --- End Directory Determination --- - click.echo() - click.echo(f"Project will be created in: {final_project_dir}") + console.print() + console.print(f"Project will be created in: {final_project_dir}") # --- Execution --- if dry_run: - click.echo("Dry run enabled. No changes will be made.") + console.print("Dry run enabled. No changes will be made.") # Optionally, list files that *would* be created here else: # Check if target directory exists and handle overwrite if final_project_dir.exists(): - if not click.confirm( + if not typer.confirm( f"Directory '{final_project_dir}' already exists. Overwrite?" ): - click.echo("Aborted.") + console.print("Aborted.") return else: - click.echo(f"Removing existing directory: {final_project_dir}") + console.print(f"Removing existing directory: {final_project_dir}") try: shutil.rmtree(final_project_dir) except Exception as e: - click.echo(f"Error removing existing directory: {e}", err=True) + err_console.print(f"Error removing existing directory: {e}") return # Create parent directories if they don't exist try: final_project_dir.parent.mkdir(parents=True, exist_ok=True) except Exception as e: - click.echo( - f"Error creating parent directories for {final_project_dir}: {e}", - err=True, + err_console.print( + f"Error creating parent directories for {final_project_dir}: {e}" ) return @@ -448,31 +442,25 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): old_syntax_files.append(file) if old_syntax_files: - click.echo() - click.echo("WARNING: Windows Compatibility Notice:", err=True) - click.echo( - "This template uses the old {{variable}} syntax in filenames, which may not work on Windows.", - err=True, + console.print() + err_console.print("WARNING: Windows Compatibility Notice:") + err_console.print( + "This template uses the old {{variable}} syntax in filenames, which may not work on Windows." ) - click.echo( - "Consider updating the template to use the new Windows-compatible %{variable} syntax.", - err=True, + err_console.print( + "Consider updating the template to use the new Windows-compatible %{variable} syntax." ) - click.echo("Files with old syntax:", err=True) + err_console.print("Files with old syntax:") for file in old_syntax_files[:3]: # Show first 3 files - click.echo(f" - {file}", err=True) + err_console.print(f" - {file}") if len(old_syntax_files) > 3: - click.echo( - f" ... and {len(old_syntax_files) - 3} more", err=True - ) - click.echo() - click.echo("New syntax examples:", err=True) - click.echo(" - %{project_name}.kicad_pro", err=True) - click.echo(" - %{project_name.lower}.kicad_sch", err=True) - click.echo( - " - %{project_name.replace(' ', '-')}.kicad_pcb", err=True - ) - click.echo() + err_console.print(f" ... and {len(old_syntax_files) - 3} more") + console.print() + err_console.print("New syntax examples:") + err_console.print(" - %{project_name}.kicad_pro") + err_console.print(" - %{project_name.lower}.kicad_sch") + err_console.print(" - %{project_name.replace(' ', '-')}.kicad_pcb") + console.print() success = create_project_from_template( template_dir=template_dir, @@ -483,93 +471,68 @@ def create(name, directory, template, library, set_var, dry_run, skip_hooks): metadata=metadata, # Pass metadata for post-hook if needed ) except Exception as e: - click.echo(f"Error during project creation: {e}", err=True) + err_console.print(f"Error during project creation: {e}") traceback.print_exc() # Print traceback for debugging success = False if success: if not dry_run: - click.echo() - click.echo( + console.print() + console.print( f"Project '{variables.get('project_name', name)}' created successfully in '{final_project_dir}'" ) else: - click.echo() - click.echo("Project creation failed.", err=True) + console.print() + err_console.print("Project creation failed.") -@template.command() -@click.argument("name", required=False) -@click.argument( - "source_directory", - required=False, - type=click.Path(exists=True, file_okay=False, dir_okay=True), -) -@click.option( - "--description", - help="Template description", - default=None, -) -@click.option( - "--use-case", - help="Template use case description", - default=None, -) -@click.option( - "--output-directory", - help="Directory where the template will be created", - type=click.Path(), - default=None, -) -@click.option( - "--exclude", - multiple=True, - help="Additional patterns to exclude (gitignore format)", -) -@click.option( - "--variable", - multiple=True, - help="Define a template variable in name=value format", -) -@click.option( - "--extends", - help="Parent template that this template extends", - default=None, -) -@click.option( - "--non-interactive", - is_flag=True, - default=False, - help="Non-interactive mode (don't prompt for variables or configuration)", - show_default=True, -) -@click.option( - "--dry-run", - is_flag=True, - default=False, - help="Show what would be created without making changes", - show_default=True, -) -@click.option( - "--force", - is_flag=True, - default=False, - help="Overwrite existing template if it exists", - show_default=True, -) def make( - name, - source_directory, - description, - use_case, - output_directory, - exclude, - variable, - extends, - non_interactive, - dry_run, - force, -): + name: Annotated[ + Optional[str], typer.Argument(help="Name of the template to create") + ] = None, + source_directory: Annotated[ + Optional[Path], typer.Argument(help="Source project directory") + ] = None, + description: Annotated[ + Optional[str], typer.Option(help="Template description") + ] = None, + use_case: Annotated[ + Optional[str], typer.Option("--use-case", help="Template use case description") + ] = None, + output_directory: Annotated[ + Optional[Path], + typer.Option( + "--output-directory", help="Directory where the template will be created" + ), + ] = None, + exclude: Annotated[ + Optional[List[str]], + typer.Option(help="Additional patterns to exclude (gitignore format)"), + ] = None, + variable: Annotated[ + Optional[List[str]], + typer.Option(help="Define a template variable in name=value format"), + ] = None, + extends: Annotated[ + Optional[str], typer.Option(help="Parent template that this template extends") + ] = None, + non_interactive: Annotated[ + bool, + typer.Option( + "--non-interactive", + help="Non-interactive mode (don't prompt for variables or configuration)", + ), + ] = False, + dry_run: Annotated[ + bool, + typer.Option( + "--dry-run", help="Show what would be created without making changes" + ), + ] = False, + force: Annotated[ + bool, typer.Option("--force", help="Overwrite existing template if it exists") + ] = False, +) -> None: """Create a template from an existing project. Creates a new KiCad project template from an existing project. If NAME @@ -616,7 +579,7 @@ def make( library_paths = {lib["name"]: lib["path"] for lib in all_libraries} if not library_names: - click.echo( + console.print( "No GitHub libraries configured. Use 'kilm init' to create one first." ) sys.exit(1) @@ -629,39 +592,39 @@ def make( # Ask for source directory if not specified if not source_directory: default_dir = str(Path.cwd()) - source_dir_input = click.prompt( + source_dir_input = typer.prompt( "Source project directory", default=default_dir ) # Handle relative paths if not Path(source_dir_input).is_absolute(): - source_directory = str(Path.cwd() / source_dir_input) + source_directory = Path.cwd() / source_dir_input else: - source_directory = source_dir_input + source_directory = Path(source_dir_input) # Ask for template name if not specified if not name: - default_name = Path(source_directory).name - name = click.prompt("Template name", default=default_name) + default_name = source_directory.name if source_directory else "template" + name = typer.prompt("Template name", default=default_name) # Ask for description and use case if not specified if not description: - description = click.prompt( + description = typer.prompt( "Template description", default=f"{name} template" ) if not use_case: - use_case = click.prompt("Template use case", default="") + use_case = typer.prompt("Template use case", default="") # Ask for output directory if not specified if not output_directory: # Show numbered list of libraries - click.echo("\nChoose a library to store the template:") + console.print("\nChoose a library to store the template:") for i, lib_name in enumerate(library_names): - click.echo(f"{i + 1}. {lib_name} ({library_paths[lib_name]})") + console.print(f"{i + 1}. {lib_name} ({library_paths[lib_name]})") # Get selection while True: try: - lib_selection = click.prompt( + lib_selection = typer.prompt( "Select library (number)", type=int, default=1 ) if 1 <= lib_selection <= len(library_names): @@ -669,65 +632,68 @@ def make( library_path = library_paths[selected_lib] break else: - click.echo( + console.print( f"Please enter a number between 1 and {len(library_names)}" ) except ValueError: - click.echo("Please enter a valid number") + console.print("Please enter a valid number") output_directory = Path(library_path) / TEMPLATES_DIR / name - click.echo(f"Template will be created in: {output_directory}") + console.print(f"Template will be created in: {output_directory}") else: # Non-interactive mode - use current directory if not specified if not source_directory: - source_directory = str(Path.cwd()) + source_directory = Path.cwd() # If name is not provided, use the directory name if not name: - name = Path(source_directory).name + name = source_directory.name # Determine the output directory if not output_directory: # Find the library to add the template to library_path = config.get_symbol_library_path() if not library_path: - click.echo( + console.print( "No library configured. Use 'kilm init' to create one first." ) return output_directory = Path(library_path) / TEMPLATES_DIR / name - # Convert source_directory to Path object - source_directory = Path(source_directory) + # Ensure source_directory is a Path object + if source_directory is None: + source_directory = Path.cwd() + elif not isinstance(source_directory, Path): + source_directory = Path(source_directory) # Check if template already exists - if output_directory and Path(output_directory).exists() and not force: - click.echo(f"Template '{name}' already exists at {output_directory}") - click.echo("Use --force to overwrite.") + if output_directory and output_directory.exists() and not force: + console.print(f"Template '{name}' already exists at {output_directory}") + console.print("Use --force to overwrite.") return # Get gitignore spec gitignore_spec = get_gitignore_spec(source_directory) # Show what we're going to do - click.echo(f"Creating template '{name}' from {source_directory}") - click.echo(f"Output directory: {output_directory}") + console.print(f"Creating template '{name}' from {source_directory}") + console.print(f"Output directory: {output_directory}") if description: - click.echo(f"Description: {description}") + console.print(f"Description: {description}") if use_case: - click.echo(f"Use case: {use_case}") + console.print(f"Use case: {use_case}") if exclude: - click.echo("Additional exclusions:") + console.print("Additional exclusions:") for pattern in exclude: - click.echo(f" {pattern}") + console.print(f" {pattern}") if extends: - click.echo(f"Extends: {extends}") + console.print(f"Extends: {extends}") # Parse variables from command line variable_dict = {} - for var in variable: + for var in variable or []: if "=" in var: key, value = var.split("=", 1) variable_dict[key.strip()] = { @@ -736,27 +702,27 @@ def make( } if variable_dict: - click.echo("\nTemplate variables:") + console.print("\nTemplate variables:") for key, value in variable_dict.items(): - click.echo(f" {key}: {value['default']} - {value['description']}") + console.print(f" {key}: {value['default']} - {value['description']}") # If interactive mode is enabled, scan for potential variables detected_variables = {} if interactive: potential_vars = find_potential_variables(source_directory) if potential_vars: - click.echo("\nFound potential template variables:") + console.print("\nFound potential template variables:") for var_name, values in potential_vars.items(): value_str = ", ".join(values) - click.echo(f" {var_name}: {value_str}") + console.print(f" {var_name}: {value_str}") # Ask if the user wants to use this variable - if click.confirm( + if typer.confirm( f" Use '{var_name}' as a template variable?", default=True ): # Use the first value as default default_value = values[0] if values else "" - description = click.prompt( + description = typer.prompt( " Description", default=f"Value for {var_name}" ) @@ -766,12 +732,12 @@ def make( } # Always ask if the user wants to define additional variables - while click.confirm( + while typer.confirm( "Would you like to define additional template variables?", default=False ): - var_name = click.prompt("Variable name") - var_default = click.prompt("Default value", default="") - var_description = click.prompt( + var_name = typer.prompt("Variable name") + var_default = typer.prompt("Default value", default="") + var_description = typer.prompt( "Description", default=f"Value for {var_name}" ) @@ -849,16 +815,16 @@ def make( included_files.sort() excluded_files.sort() - click.echo("\nFiles that will be included in the template:") + console.print("\nFiles that will be included in the template:") for file in included_files: - click.echo(f" + {file}") + console.print(f" + {file}") # Show which Markdown files will be templated md_files = [f for f in included_files if f.lower().endswith(".md")] if md_files: - click.echo("\nMarkdown files that will be converted to Jinja templates:") + console.print("\nMarkdown files that will be converted to Jinja templates:") for file in md_files: - click.echo(f" * {file}") + console.print(f" * {file}") # Show which KiCad project files will be templated kicad_files = [ @@ -867,7 +833,7 @@ def make( if f.lower().endswith((".kicad_pro", ".kicad_sch", ".kicad_pcb")) ] if kicad_files: - click.echo("\nKiCad project files that will be templated:") + console.print("\nKiCad project files that will be templated:") for file in kicad_files: # Show the templated filename that will be used if file.lower().endswith(".kicad_pro"): @@ -879,21 +845,22 @@ def make( else: templated_name = file - click.echo(f" * {file} → {templated_name}") + console.print(f" * {file} → {templated_name}") - click.echo("\nFiles that will be excluded from the template:") + console.print("\nFiles that will be excluded from the template:") for file in excluded_files: - click.echo(f" - {file}") + console.print(f" - {file}") # If this is a dry run, stop here if dry_run: - click.echo("\nDry run complete. No changes were made.") + console.print("\nDry run complete. No changes were made.") return # Create the template try: # Create the template directory structure - Path(output_directory).mkdir(parents=True, exist_ok=True) + if output_directory: + output_directory.mkdir(parents=True, exist_ok=True) # Create template structure with special handling for Markdown files create_template_structure( @@ -904,62 +871,54 @@ def make( additional_excludes=exclude or None, ) - click.echo(f"\nTemplate '{name}' created successfully at {output_directory}") + console.print(f"\nTemplate '{name}' created successfully at {output_directory}") # Add hints for next steps - click.echo("\nNext steps:") - click.echo( - f"1. Edit {output_directory / TEMPLATE_METADATA} to customize template metadata" + console.print("\nNext steps:") + console.print( + f"1. Edit {output_directory / TEMPLATE_METADATA if output_directory else 'N/A'} to customize template metadata" ) - click.echo( - f"2. Customize template files in {output_directory / TEMPLATE_CONTENT_DIR}" + console.print( + f"2. Customize template files in {output_directory / TEMPLATE_CONTENT_DIR if output_directory else 'N/A'}" ) - click.echo( - f"3. Edit post-creation hook in {output_directory / HOOKS_DIR / POST_CREATE_HOOK} if needed" + console.print( + f"3. Edit post-creation hook in {output_directory / HOOKS_DIR / POST_CREATE_HOOK if output_directory else 'N/A'} if needed" ) - click.echo( + console.print( f"4. Use your template with: kilm template create MyProject --template {name}" ) # Add information about filename templating syntax - click.echo("\nFilename Templating:") - click.echo("For Windows compatibility, use %{variable} syntax in filenames:") - click.echo(" - %{project_name}.kicad_pro") - click.echo(" - %{project_name.lower}.kicad_sch") - click.echo(" - %{project_name.replace(' ', '-')}.kicad_pcb") - click.echo(" - %{project_name.upper.replace(' ', '_')}.md") - click.echo( + console.print("\nFilename Templating:") + console.print("For Windows compatibility, use %{variable} syntax in filenames:") + console.print(" - %{project_name}.kicad_pro") + console.print(" - %{project_name.lower}.kicad_sch") + console.print(" - %{project_name.replace(' ', '-')}.kicad_pcb") + console.print(" - %{project_name.upper.replace(' ', '_')}.md") + console.print( "(Old {{variable}} syntax still works but may cause issues on Windows)" ) except Exception as e: - click.echo(f"Error creating template: {str(e)}", err=True) + err_console.print(f"Error creating template: {str(e)}") traceback.print_exc() sys.exit(1) -@template.command() -@click.option( - "--library", - help="Filter templates by library name", - default=None, -) -@click.option( - "--verbose", - "-v", - is_flag=True, - default=False, - help="Show detailed information including variables", - show_default=True, -) -@click.option( - "--json", - is_flag=True, - default=False, - help="Output in JSON format", - show_default=True, -) -def list_templates_cmd(library, verbose, json): +def list_templates( + library: Annotated[ + Optional[str], typer.Option(help="Filter templates by library name") + ] = None, + verbose: Annotated[ + bool, + typer.Option( + "-v", "--verbose", help="Show detailed information including variables" + ), + ] = False, + json_output: Annotated[ + bool, typer.Option("--json", help="Output in JSON format") + ] = False, +) -> None: """List all available templates. Displays all available templates across all configured libraries, @@ -989,8 +948,17 @@ def list_templates_cmd(library, verbose, json): all_templates = find_all_templates(config) if not all_templates: - click.echo("No templates found in any configured libraries.") - click.echo("Use 'kilm template make' to create a template first.") + console.print() + console.print( + Panel( + "[yellow]No templates found in any configured libraries.[/yellow]\n\n" + "[cyan]💡 Get Started:[/cyan]\n" + "• Create a template: [blue]kilm template make[/blue]\n" + "• Check library configuration: [blue]kilm list-libraries[/blue]", + title="[bold yellow]⚠️ No Templates[/bold yellow]", + border_style="yellow", + ) + ) return # Filter by library if requested @@ -1002,14 +970,25 @@ def list_templates_cmd(library, verbose, json): } if not all_templates: - click.echo(f"No templates found in library '{library}'.") + console.print() + console.print( + Panel( + f"[yellow]No templates found in library '[cyan]{library}[/cyan]'.[/yellow]\n\n" + "[cyan]💡 Try:[/cyan]\n" + f"• List all libraries: [blue]kilm list-libraries[/blue]\n" + f"• Create template in '{library}': [blue]kilm template make --library {library}[/blue]\n" + "• List all templates: [blue]kilm template list[/blue]", + title="[bold yellow]⚠️ No Templates Found[/bold yellow]", + border_style="yellow", + ) + ) return # If JSON output is requested - if json: + if json_output: import json as json_lib - click.echo(json_lib.dumps(all_templates, indent=2)) + console.print(json_lib.dumps(all_templates, indent=2)) return # Group templates by library for display @@ -1020,61 +999,85 @@ def list_templates_cmd(library, verbose, json): templates_by_library[lib_name] = [] templates_by_library[lib_name].append((name, data)) - # Display templates - click.echo("Available Templates:") - click.echo("===================") - click.echo() + # Display templates in Rich tables organized by library + console.print() for lib_name, templates in templates_by_library.items(): - click.echo(f"Library: {lib_name}") - click.echo("-" * (len(lib_name) + 9)) + # Create a table for each library + table = Table( + title=f"[bold cyan]{lib_name}[/bold cyan] Templates", + show_header=True, + header_style="bold magenta", + border_style="cyan", + ) + + table.add_column("Template", style="cyan", no_wrap=True) + table.add_column("Version", justify="center", style="blue", width=8) + table.add_column("Description", style="green") + + if verbose: + table.add_column("Variables", style="yellow", max_width=30) + table.add_column("Extends", style="magenta", max_width=15) + # Add rows for each template for name, data in sorted(templates): description = data.get("description", "No description") - use_case = data.get("use_case", "") version = data.get("version", "1.0.0") + extends = data.get("extends", "") - click.echo() - click.echo(f"- {name} (v{version})") - click.echo(f" Description: {description}") + row_data = [f"[bold]{name}[/bold]", version, description] - if use_case: - click.echo(f" Use Case: {use_case}") - - if data.get("extends"): - click.echo(f" Extends: {data.get('extends')}") - - # Show variables if verbose if verbose: + # Format variables for display variables = data.get("variables", {}) + var_display = "" if variables: - click.echo() - click.echo(" Variables:") - for var_name, var_info in variables.items(): - var_desc = var_info.get("description", "") - var_default = var_info.get("default", "") - click.echo( - f" {var_name}: {var_desc} (default: '{var_default}')" - ) + var_list = [f"{k}" for k in variables] + var_display = ", ".join(var_list[:3]) # Show first 3 variables + if len(var_list) > 3: + var_display += f", +{len(var_list) - 3} more" + else: + var_display = "[dim]None[/dim]" - # Show dependencies if present - dependencies = data.get("dependencies", {}) - if dependencies: - recommended = dependencies.get("recommended", []) - if recommended: - click.echo() - click.echo(" Recommended Dependencies:") - for dep in recommended: - click.echo(f" - {dep}") + row_data.append(var_display) + row_data.append(extends if extends else "[dim]None[/dim]") - click.echo("") # Empty line between templates + table.add_row(*row_data) - click.echo("") # Empty line between libraries + console.print(table) + console.print() - # Show count - click.echo(f"Total: {len(all_templates)} template(s) found") + # Add usage hint panel + hint_content = ( + "[cyan]Usage:[/cyan] kilm template create --template \n" + ) + hint_content += "[cyan]Verbose:[/cyan] kilm template list --verbose\n" + hint_content += "[cyan]Filter:[/cyan] kilm template list --library " + + console.print( + Panel( + hint_content, + title="[bold blue]💡 Quick Tips[/bold blue]", + border_style="blue", + ) + ) + # Add summary panel + library_count = len(templates_by_library) + template_count = len(all_templates) + + summary_content = f"[green]Libraries:[/green] {library_count}\n" + summary_content += f"[green]Templates:[/green] {template_count}" + + console.print( + Panel( + summary_content, + title="[bold cyan]📊 Summary[/bold cyan]", + border_style="cyan", + width=30, + ) + ) # Register the template command if __name__ == "__main__": - template() + main_callback() diff --git a/kicad_lib_manager/commands/update/__init__.py b/kicad_lib_manager/commands/update/__init__.py index 1ed481f..a1fc882 100644 --- a/kicad_lib_manager/commands/update/__init__.py +++ b/kicad_lib_manager/commands/update/__init__.py @@ -1,3 +1,13 @@ +import typer + from .command import update -__all__ = ["update"] +update_app = typer.Typer( + name="update", + help="Update KiLM itself to the latest version", + rich_markup_mode="rich", + callback=update, + invoke_without_command=True, +) + +__all__ = ["update", "update_app"] diff --git a/kicad_lib_manager/commands/update/command.py b/kicad_lib_manager/commands/update/command.py index 85d5ec5..570d33d 100644 --- a/kicad_lib_manager/commands/update/command.py +++ b/kicad_lib_manager/commands/update/command.py @@ -1,31 +1,28 @@ """ -Update command implementation for KiCad Library Manager. +Update command implementation for KiCad Library Manager (Typer version). Updates KiLM itself to the latest version. """ import importlib.metadata +from typing import Annotated -import click +import typer +from rich.console import Console +from rich.panel import Panel from ...services.update_service import UpdateManager +console = Console() -@click.command() -@click.option( - "--check", - is_flag=True, - default=False, - help="Check for updates without installing", - show_default=True, -) -@click.option( - "--force", - is_flag=True, - default=False, - help="Force update even if already up to date", - show_default=True, -) -def update(check, force): + +def update( + check: Annotated[ + bool, typer.Option(help="Check for updates without installing") + ] = False, + force: Annotated[ + bool, typer.Option(help="Force update even if already up to date") + ] = False, +) -> None: """Update KiLM to the latest version. This command updates KiLM itself by downloading and installing the latest @@ -39,59 +36,77 @@ def update(check, force): Use --check to see if updates are available without installing. """ - # Display deprecation notice prominently - click.echo("\n" + "=" * 70) - click.echo("⚠️ BREAKING CHANGE NOTICE (KiLM 0.4.0)") - click.echo("=" * 70) - click.echo("The 'kilm update' command now updates KiLM itself.") - click.echo("To update library content, use 'kilm sync' instead.") - click.echo("This notice will be removed in a future version.") - click.echo("=" * 70 + "\n") + + deprecation_notice = ( + "[bold yellow]⚠️ BREAKING CHANGE NOTICE (KiLM 0.4.0)[/bold yellow]\n\n" + "The [bold]kilm update[/bold] command now updates KiLM itself.\n" + "To update library content, use [bold cyan]kilm sync[/bold cyan] instead.\n" + "This notice will be removed in a future version." + ) + console.print(Panel(deprecation_notice, expand=False, border_style="yellow")) version = importlib.metadata.version("kilm") update_manager = UpdateManager(version) - click.echo(f"Current KiLM version: {version}") - click.echo(f"Installation method: {update_manager.installation_method}") - click.echo("\nChecking for updates...") + console.print( + f"[blue]Current KiLM version:[/blue] [bold cyan]v{version}[/bold cyan]" + ) + console.print( + f"[blue]Installation method:[/blue] {update_manager.installation_method}" + ) + console.print("\n[bold cyan]Checking for updates...[/bold cyan]") latest_version = update_manager.check_latest_version() if latest_version is None: - click.echo("Could not check for updates. Please try again later.") + console.print("[red]Could not check for updates. Please try again later.[/red]") return if not update_manager.is_newer_version_available(latest_version): if not force: - click.echo(f"KiLM is up to date (v{version})") + console.print( + f"[green]KiLM is up to date[/green] [bold green]v{version}[/bold green]" + ) return else: - click.echo(f"Forcing update to v{latest_version} (current: v{version})") + console.print( + f"[yellow]Forcing update to v{latest_version}[/yellow] (current: v{version})" + ) else: - click.echo(f"New version available: {latest_version}") + console.print( + f"[green]New version available:[/green] [bold green]v{latest_version}[/bold green]" + ) if check: if update_manager.is_newer_version_available(latest_version): - click.echo(f"\nUpdate available: {latest_version}") - click.echo(f"To update, run: {update_manager.get_update_instruction()}") + console.print( + f"\n[green]Update available:[/green] [bold green]v{latest_version}[/bold green]" + ) + console.print( + f"[blue]To update, run:[/blue] [cyan]{update_manager.get_update_instruction()}[/cyan]" + ) else: - click.echo("No updates available.") + console.print("[green]No updates available[/green]") return # Perform the update if update_manager.can_auto_update(): - click.echo(f"\nUpdating KiLM to version {latest_version}...") + console.print( + f"\n[bold cyan]Updating KiLM to version {latest_version}...[/bold cyan]" + ) success, message = update_manager.perform_update() if success: - click.echo(f"✅ {message}") - click.echo(f"KiLM has been updated to version {latest_version}") + console.print(f"[bold green]✅ {message}[/bold green]") + console.print( + f"[green]KiLM has been updated to version {latest_version}[/green]" + ) else: - click.echo(f"❌ {message}") + console.print(f"[bold red]❌ {message}[/bold red]") else: instruction = update_manager.get_update_instruction() - click.echo( - f"\nManual update required for {update_manager.installation_method} installation." + console.print( + f"\n[yellow]Manual update required for {update_manager.installation_method} installation.[/yellow]" ) - click.echo(f"Please run: {instruction}") + console.print(f"[blue]Please run:[/blue] [cyan]{instruction}[/cyan]") diff --git a/kicad_lib_manager/main.py b/kicad_lib_manager/main.py index 63437b4..f6d1ce1 100644 --- a/kicad_lib_manager/main.py +++ b/kicad_lib_manager/main.py @@ -13,12 +13,18 @@ from rich.traceback import install from typer.core import TyperGroup +from .commands.add_3d import add_3d_app +from .commands.add_hook import add_hook_app +from .commands.config import config_app from .commands.init import init_app from .commands.list_libraries import list_app from .commands.pin import pin_app from .commands.setup import setup_app from .commands.status import status_app +from .commands.sync import sync_app +from .commands.template import template_app from .commands.unpin import unpin_app +from .commands.update import update_app from .utils.banner import show_banner TAGLINE = "Professional KiCad library management" @@ -111,14 +117,12 @@ def main( app.add_typer(pin_app, name="pin", help="Pin favorite libraries") app.add_typer(unpin_app, name="unpin", help="Unpin favorite libraries") app.add_typer(setup_app, name="setup", help="Configure KiCad to use libraries") - -# TODO: Migrate remaining commands to Typer -# - add-3d: Add 3D model libraries -# - config: Manage configuration settings -# - sync: Update/sync library content -# - update: Update KiLM itself -# - add-hook: Add project hooks -# - template: Manage project templates +app.add_typer(config_app, name="config", help="Manage configuration settings") +app.add_typer(template_app, name="template", help="Manage project templates") +app.add_typer(add_3d_app, name="add-3d", help="Add 3D model libraries") +app.add_typer(sync_app, name="sync", help="Update/sync library content") +app.add_typer(update_app, name="update", help="Update KiLM itself") +app.add_typer(add_hook_app, name="add-hook", help="Add project hooks") if __name__ == "__main__": diff --git a/kicad_lib_manager/utils/file_ops.py b/kicad_lib_manager/utils/file_ops.py index 87ec2d5..4e93976 100644 --- a/kicad_lib_manager/utils/file_ops.py +++ b/kicad_lib_manager/utils/file_ops.py @@ -247,21 +247,26 @@ def list_configured_libraries(kicad_config: Path) -> Tuple[List[dict], List[dict if sym_table.exists(): content = read_file_with_encoding(sym_table) - # Extract all library entries - lib_entries = re.findall(r'\(lib \(name "([^"]+)"\)(.+?)\)', content, re.DOTALL) - for name, details in lib_entries: - lib_info = {"name": name} - - # Extract other properties - uri_match = re.search(r'\(uri "([^"]+)"\)', details) + # Match each complete (lib ...) entry on its own line + # This is more robust than trying to match up to the first ')' + for match in re.finditer(r"^\s*\(lib\s+(.*?)\)\s*$", content, re.MULTILINE): + entry = match.group(1) + + name_match = re.search(r'\(name\s+"([^"]+)"\)', entry) + if not name_match: + continue + lib_info = {"name": name_match.group(1)} + + # Extract other properties (support both uri and url just in case) + uri_match = re.search(r'\((?:uri|url)\s+"([^"]+)"\)', entry) if uri_match: lib_info["uri"] = uri_match.group(1) - type_match = re.search(r'\(type "([^"]+)"\)', details) + type_match = re.search(r'\(type\s+"([^"]+)"\)', entry) if type_match: lib_info["type"] = type_match.group(1) - descr_match = re.search(r'\(descr "([^"]+)"\)', details) + descr_match = re.search(r'\(descr\s+"([^"]+)"\)', entry) if descr_match: lib_info["description"] = descr_match.group(1) @@ -270,21 +275,23 @@ def list_configured_libraries(kicad_config: Path) -> Tuple[List[dict], List[dict if fp_table.exists(): content = read_file_with_encoding(fp_table) - # Extract all library entries - lib_entries = re.findall(r'\(lib \(name "([^"]+)"\)(.+?)\)', content, re.DOTALL) - for name, details in lib_entries: - lib_info = {"name": name} + for match in re.finditer(r"^\s*\(lib\s+(.*?)\)\s*$", content, re.MULTILINE): + entry = match.group(1) + + name_match = re.search(r'\(name\s+"([^"]+)"\)', entry) + if not name_match: + continue + lib_info = {"name": name_match.group(1)} - # Extract other properties - uri_match = re.search(r'\(uri "([^"]+)"\)', details) + uri_match = re.search(r'\((?:uri|url)\s+"([^"]+)"\)', entry) if uri_match: lib_info["uri"] = uri_match.group(1) - type_match = re.search(r'\(type "([^"]+)"\)', details) + type_match = re.search(r'\(type\s+"([^"]+)"\)', entry) if type_match: lib_info["type"] = type_match.group(1) - descr_match = re.search(r'\(descr "([^"]+)"\)', details) + descr_match = re.search(r'\(descr\s+"([^"]+)"\)', entry) if descr_match: lib_info["description"] = descr_match.group(1) diff --git a/tests/test_config_commands.py b/tests/test_config_commands.py index e961110..1d02aa0 100644 --- a/tests/test_config_commands.py +++ b/tests/test_config_commands.py @@ -5,9 +5,9 @@ from typing import List import pytest -from click.testing import CliRunner +from typer.testing import CliRunner -from kicad_lib_manager.cli import main +from kicad_lib_manager.main import app as main from kicad_lib_manager.services.config_service import Config, LibraryDict # Sample test data @@ -55,12 +55,24 @@ def test_config_list(mock_config_class): result = runner.invoke(main, ["config", "list"]) assert result.exit_code == 0 - assert "Configured Libraries" in result.output assert "GitHub Libraries" in result.output assert "Cloud Libraries" in result.output assert "test-github-lib" in result.output assert "test-cloud-lib" in result.output - assert "(current)" in result.output # Current library should be marked + assert "✓ Current" in result.output # Current library should be marked + + +def test_config_list_verbose(mock_config_class): + """Test the 'kilm config list --verbose' command.""" + runner = CliRunner() + result = runner.invoke(main, ["config", "list", "--verbose"]) + + assert result.exit_code == 0 + assert "GitHub Libraries" in result.output + assert "Cloud Libraries" in result.output + assert "test-github-lib" in result.output + assert "test-cloud-lib" in result.output + assert "✓ CURRENT" in result.output def test_config_list_filtered(mock_config_class): diff --git a/tests/test_library_manager.py b/tests/test_library_manager.py index 8f64721..e4a08b1 100644 --- a/tests/test_library_manager.py +++ b/tests/test_library_manager.py @@ -3,32 +3,28 @@ import pytest -from kicad_lib_manager.services.library_service import ( - add_entries_to_table, - add_libraries, - format_uri, -) +from kicad_lib_manager.services.library_service import LibraryService def test_format_uri_absolute_path(): """Test URI formatting with absolute paths.""" # Test Unix-style paths assert ( - format_uri("/path/to/lib", "test_lib", "symbols") + LibraryService.format_uri("/path/to/lib", "test_lib", "symbols") == "/path/to/lib/symbols/test_lib.kicad_sym" ) assert ( - format_uri("/path/to/lib", "test_lib", "footprints") + LibraryService.format_uri("/path/to/lib", "test_lib", "footprints") == "/path/to/lib/footprints/test_lib.pretty" ) # Test Windows-style paths assert ( - format_uri("C:\\path\\to\\lib", "test_lib", "symbols") + LibraryService.format_uri("C:\\path\\to\\lib", "test_lib", "symbols") == "C:/path/to/lib/symbols/test_lib.kicad_sym" ) assert ( - format_uri("C:\\path\\to\\lib", "test_lib", "footprints") + LibraryService.format_uri("C:\\path\\to\\lib", "test_lib", "footprints") == "C:/path/to/lib/footprints/test_lib.pretty" ) @@ -36,11 +32,11 @@ def test_format_uri_absolute_path(): def test_format_uri_env_var(): """Test URI formatting with environment variable names.""" assert ( - format_uri("KICAD_LIB", "test_lib", "symbols") + LibraryService.format_uri("KICAD_LIB", "test_lib", "symbols") == "${KICAD_LIB}/symbols/test_lib.kicad_sym" ) assert ( - format_uri("KICAD_LIB", "test_lib", "footprints") + LibraryService.format_uri("KICAD_LIB", "test_lib", "footprints") == "${KICAD_LIB}/footprints/test_lib.pretty" ) @@ -49,13 +45,13 @@ def test_format_uri_path_in_curly(): """Test URI formatting with paths already in ${} format.""" # Test absolute paths in ${} assert ( - format_uri("${/path/to/lib}", "test_lib", "symbols") + LibraryService.format_uri("${/path/to/lib}", "test_lib", "symbols") == "/path/to/lib/symbols/test_lib.kicad_sym" ) # Test environment variables in ${} assert ( - format_uri("${KICAD_LIB}", "test_lib", "symbols") + LibraryService.format_uri("${KICAD_LIB}", "test_lib", "symbols") == "${KICAD_LIB}/symbols/test_lib.kicad_sym" ) @@ -64,30 +60,31 @@ def test_format_uri_edge_cases(): """Test URI formatting with edge cases.""" # Test with empty library name assert ( - format_uri("/path/to/lib", "", "symbols") == "/path/to/lib/symbols/.kicad_sym" + LibraryService.format_uri("/path/to/lib", "", "symbols") + == "/path/to/lib/symbols/.kicad_sym" ) # Test with special characters in library name assert ( - format_uri("/path/to/lib", "test-lib_123", "symbols") + LibraryService.format_uri("/path/to/lib", "test-lib_123", "symbols") == "/path/to/lib/symbols/test-lib_123.kicad_sym" ) # Test with mixed slashes assert ( - format_uri("C:/path\\to/lib", "test_lib", "symbols") + LibraryService.format_uri("C:/path\\to/lib", "test_lib", "symbols") == "C:/path/to/lib/symbols/test_lib.kicad_sym" ) # Test with UTF-8 characters in path assert ( - format_uri("/path/to/šžć", "test_lib", "symbols") + LibraryService.format_uri("/path/to/šžć", "test_lib", "symbols") == "/path/to/šžć/symbols/test_lib.kicad_sym" ) # Test with UTF-8 characters and spaces in path assert ( - format_uri("/path/to /šžć ", "test_lib", "symbols") + LibraryService.format_uri("/path/to /šžć ", "test_lib", "symbols") == "/path/to /šžć /symbols/test_lib.kicad_sym" ) @@ -95,13 +92,15 @@ def test_format_uri_edge_cases(): def test_format_uri_invalid_input(): """Test URI formatting with invalid inputs.""" with pytest.raises(ValueError): - format_uri("", "test_lib", "symbols") # Empty base path + LibraryService.format_uri("", "test_lib", "symbols") # Empty base path with pytest.raises(ValueError): - format_uri("/path/to/lib", "test_lib", "invalid_type") # Invalid library type + LibraryService.format_uri( + "/path/to/lib", "test_lib", "invalid_type" + ) # Invalid library type with pytest.raises(ValueError): - format_uri("${unclosed", "test_lib", "symbols") # Unclosed ${ + LibraryService.format_uri("${unclosed", "test_lib", "symbols") # Unclosed ${ def test_add_libraries_integration(tmp_path): @@ -118,20 +117,23 @@ def test_add_libraries_integration(tmp_path): (lib_dir / "symbols" / "test_lib.kicad_sym").touch() (lib_dir / "footprints" / "test_lib.pretty").touch() + # Create LibraryService instance + service = LibraryService() + # Test with absolute path - added_libs, changes = add_libraries(str(lib_dir), config_dir, dry_run=True) + added_libs, changes = service.add_libraries(str(lib_dir), config_dir, dry_run=True) assert "test_lib" in added_libs assert changes # Test with environment variable path - we need to set up the environment variable first os.environ["KICAD_LIB"] = str(lib_dir) - added_libs, changes = add_libraries("KICAD_LIB", config_dir, dry_run=True) + added_libs, changes = service.add_libraries("KICAD_LIB", config_dir, dry_run=True) assert "test_lib" in added_libs assert changes # Test with path in ${} - use a proper environment variable name os.environ["TEST_LIB"] = str(lib_dir) - added_libs, changes = add_libraries("${TEST_LIB}", config_dir, dry_run=True) + added_libs, changes = service.add_libraries("${TEST_LIB}", config_dir, dry_run=True) assert "test_lib" in added_libs assert changes @@ -152,8 +154,11 @@ def test_add_libraries_utf8(tmp_path): lib_dir / "footprints" / "test_šž.pretty" ).mkdir() # Footprint libs are directories + # Create LibraryService instance + service = LibraryService() + # Test adding libraries with UTF-8 paths/names - added_libs, changes = add_libraries(str(lib_dir), config_dir, dry_run=True) + added_libs, changes = service.add_libraries(str(lib_dir), config_dir, dry_run=True) # Assert that the libraries with UTF-8 names were detected assert "test_čš" in added_libs @@ -185,7 +190,7 @@ def test_add_entries_with_special_chars(tmp_path): ] # Add entries - add_entries_to_table(table_path, entries) + LibraryService.add_entries_to_table(table_path, entries) # Read the updated table with Path(table_path).open(encoding="utf-8") as f: diff --git a/tests/test_sync_command.py b/tests/test_sync_command.py index 2cbaab8..3ae5b82 100644 --- a/tests/test_sync_command.py +++ b/tests/test_sync_command.py @@ -3,13 +3,13 @@ """ from pathlib import Path -from unittest.mock import MagicMock, Mock, patch +from unittest.mock import MagicMock, patch import pytest -from click.testing import CliRunner +from typer.testing import CliRunner -from kicad_lib_manager.cli import main from kicad_lib_manager.commands.sync.command import check_for_library_changes +from kicad_lib_manager.main import app as main # Sample test libraries TEST_LIBRARIES = [ @@ -121,26 +121,18 @@ def test_sync_command(mock_config, mock_subprocess_run, mock_path_methods): def test_sync_with_auto_setup(mock_config, mock_subprocess_run, mock_path_methods): """Test sync with auto-setup option.""" - # Mock the setup module import - setup_module_mock = Mock() - setup_command_mock = Mock(name="setup_command") - setup_command_mock.make_context = Mock(return_value=Mock()) - setup_command_mock.invoke = Mock() - setup_module_mock.setup = setup_command_mock - - # Mock the module import - with patch.dict( - "sys.modules", {"kicad_lib_manager.commands.setup": setup_module_mock} - ), patch("click.get_current_context", return_value=Mock()): + # Mock the setup command function (imported within sync function) + with patch("kicad_lib_manager.commands.setup.command.setup") as mock_setup: + mock_setup.return_value = None # setup function returns None on success + runner = CliRunner() result = runner.invoke(main, ["sync", "--auto-setup"]) assert result.exit_code == 0 assert "Running 'kilm setup'" in result.output - # Verify that make_context and invoke were called - setup_command_mock.make_context.assert_called_once() - setup_command_mock.invoke.assert_called_once() + # Verify that setup was called + mock_setup.assert_called_once() def test_sync_with_already_up_to_date(mock_config, mock_path_methods): diff --git a/tests/test_unpin_command.py b/tests/test_unpin_command.py index bbf8d95..228d527 100644 --- a/tests/test_unpin_command.py +++ b/tests/test_unpin_command.py @@ -5,9 +5,9 @@ from pathlib import Path from unittest.mock import patch -from click.testing import CliRunner +from typer.testing import CliRunner -from kicad_lib_manager.commands.unpin import unpin +from kicad_lib_manager.main import app as main class TestUnpinCommand: @@ -19,16 +19,16 @@ def setup_method(self): def test_mutual_exclusivity_all_with_symbols(self): """Test that --all cannot be used with --symbols.""" - result = self.runner.invoke(unpin, ["--all", "--symbols", "lib1"]) - assert result.exit_code == 2 # Click usage error exit code + result = self.runner.invoke(main, ["unpin", "--all", "--symbols", "lib1"]) + assert result.exit_code == 1 # Typer validation error exit code assert ( "'--all' cannot be used with '--symbols' or '--footprints'" in result.output ) def test_mutual_exclusivity_all_with_footprints(self): """Test that --all cannot be used with --footprints.""" - result = self.runner.invoke(unpin, ["--all", "--footprints", "lib1"]) - assert result.exit_code == 2 # Click usage error exit code + result = self.runner.invoke(main, ["unpin", "--all", "--footprints", "lib1"]) + assert result.exit_code == 1 # Typer validation error exit code assert ( "'--all' cannot be used with '--symbols' or '--footprints'" in result.output ) @@ -36,9 +36,9 @@ def test_mutual_exclusivity_all_with_footprints(self): def test_mutual_exclusivity_all_with_both(self): """Test that --all cannot be used with both --symbols and --footprints.""" result = self.runner.invoke( - unpin, ["--all", "--symbols", "lib1", "--footprints", "lib2"] + main, ["unpin", "--all", "--symbols", "lib1", "--footprints", "lib2"] ) - assert result.exit_code == 2 # Click usage error exit code + assert result.exit_code == 1 # Typer validation error exit code assert ( "'--all' cannot be used with '--symbols' or '--footprints'" in result.output ) @@ -46,7 +46,7 @@ def test_mutual_exclusivity_all_with_both(self): def test_mutual_exclusivity_all_only(self): """Test that --all can be used without --symbols or --footprints.""" with patch( - "kicad_lib_manager.commands.unpin.command.find_kicad_config" + "kicad_lib_manager.services.library_service.LibraryService.find_kicad_config" ) as mock_find_config: mock_find_config.return_value = Path("/tmp/kicad") @@ -59,14 +59,14 @@ def test_mutual_exclusivity_all_only(self): ) # Should not raise an error - result = self.runner.invoke(unpin, ["--all"]) + result = self.runner.invoke(main, ["unpin", "--all"]) # Exit code 0 means success, or 1 if no libraries found (which is expected) assert result.exit_code in [0, 1] def test_mutual_exclusivity_symbols_only(self): """Test that --symbols can be used without --all.""" with patch( - "kicad_lib_manager.commands.unpin.command.find_kicad_config" + "kicad_lib_manager.services.library_service.LibraryService.find_kicad_config" ) as mock_find_config: mock_find_config.return_value = Path("/tmp/kicad") @@ -77,14 +77,14 @@ def test_mutual_exclusivity_symbols_only(self): mock_open.return_value.__enter__.return_value.read.return_value = '{"session": {"pinned_symbol_libs": ["lib1"], "pinned_fp_libs": []}}' # Should not raise an error - result = self.runner.invoke(unpin, ["--symbols", "lib1"]) + result = self.runner.invoke(main, ["unpin", "--symbols", "lib1"]) # Exit code 0 means success, or 1 if no libraries found (which is expected) assert result.exit_code in [0, 1] def test_mutual_exclusivity_footprints_only(self): """Test that --footprints can be used without --all.""" with patch( - "kicad_lib_manager.commands.unpin.command.find_kicad_config" + "kicad_lib_manager.services.library_service.LibraryService.find_kicad_config" ) as mock_find_config: mock_find_config.return_value = Path("/tmp/kicad") @@ -95,6 +95,6 @@ def test_mutual_exclusivity_footprints_only(self): mock_open.return_value.__enter__.return_value.read.return_value = '{"session": {"pinned_symbol_libs": [], "pinned_fp_libs": ["lib1"]}}' # Should not raise an error - result = self.runner.invoke(unpin, ["--footprints", "lib1"]) + result = self.runner.invoke(main, ["unpin", "--footprints", "lib1"]) # Exit code 0 means success, or 1 if no libraries found (which is expected) assert result.exit_code in [0, 1] From 1d342e11115739d8b00ac3b0a711eb5ff645cc59 Mon Sep 17 00:00:00 2001 From: barisgit Date: Mon, 8 Sep 2025 14:30:07 +0200 Subject: [PATCH 09/13] Documentation updates and type/lint fixed --- CLAUDE.md | 32 +++-- PLAN.md | 2 +- docs/src/assets/cli-config-list-verbose.png | Bin 0 -> 260044 bytes docs/src/assets/cli-help.png | Bin 0 -> 319825 bytes docs/src/assets/cli-sync.png | Bin 0 -> 117925 bytes docs/src/assets/cli-welcome.png | Bin 0 -> 24862 bytes .../content/docs/community/development.mdx | 2 +- .../content/docs/guides/getting-started.mdx | 20 +++ docs/src/content/docs/index.mdx | 2 +- kicad_lib_manager/commands/add_3d/command.py | 13 +- kicad_lib_manager/commands/status/command.py | 3 +- kicad_lib_manager/commands/status/docs.mdx | 5 +- kicad_lib_manager/commands/update/docs.mdx | 12 -- .../interfaces/library_service.py | 13 +- kicad_lib_manager/services/config_service.py | 4 +- kicad_lib_manager/services/library_service.py | 2 +- kicad_lib_manager/utils/metadata.py | 16 ++- kicad_lib_manager/utils/template.py | 123 +++++++++++------- 18 files changed, 159 insertions(+), 90 deletions(-) create mode 100644 docs/src/assets/cli-config-list-verbose.png create mode 100644 docs/src/assets/cli-help.png create mode 100644 docs/src/assets/cli-sync.png create mode 100644 docs/src/assets/cli-welcome.png diff --git a/CLAUDE.md b/CLAUDE.md index f602ec5..a218089 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -119,7 +119,7 @@ kilm # Main CLI entry point - **Professional UX**: Non-intrusive notifications with method-specific guidance ### Core Modules -- **CLI Layer** (`cli.py`): Click-based command interface +- **CLI Layer** (`main.py`): Typer-based command interface with Rich output - **Commands** (`commands/`): Individual command implementations - **Library Manager** (`library_manager.py`): Core library management logic - **Configuration** (`config.py`): KiCad configuration handling with update preferences @@ -220,24 +220,30 @@ class LibraryManager(Protocol): **Step 1**: Create command module ```python -# commands/new_command.py -import click -from typing import Optional - -@click.command() -@click.option('--option', help='Command option') -def new_command(option: Optional[str]) -> None: +# commands/new_command/command.py +from typing import Annotated, Optional +import typer +from rich.console import Console + +console = Console() + +def new_command( + option: Annotated[ + Optional[str], + typer.Option("--option", help="Command option") + ] = None, +) -> None: """New command description.""" - # Implementation with proper type hints - pass + # Implementation with proper type hints and Rich output + console.print("Command executed successfully!") ``` **Step 2**: Register in CLI ```python -# cli.py -from .commands.new_command import new_command +# main.py - Add to the CLI app +from .commands.new_command.command import new_command -main.add_command(new_command) +app.command("new-command")(new_command) ``` **Step 3**: Add tests diff --git a/PLAN.md b/PLAN.md index 48c970f..dd5d766 100644 --- a/PLAN.md +++ b/PLAN.md @@ -65,7 +65,7 @@ KiLM follows a **simple, focused command structure**: - **`kilm pin `** - Pin favorite libraries for quick access - **`kilm unpin `** - Unpin libraries - **`kilm add-3d `** - Add 3D model libraries -- **`kilm update`** - Update library definitions +- **`kilm sync`** - Update library definitions ### Configuration & Templates - **`kilm config`** - Manage configuration settings diff --git a/docs/src/assets/cli-config-list-verbose.png b/docs/src/assets/cli-config-list-verbose.png new file mode 100644 index 0000000000000000000000000000000000000000..ced42281ddc261e7209fc0476da18911faa07a6b GIT binary patch literal 260044 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
    1EN{D0m?phQY?W*OR`-_G`Ej6Ek=nX6 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%0DD5q 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
  1. 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�Qo0#z?&Cj1wGy5B|qlxMbnWz0z4d<`sZWr1*r?()4VX*?g0{2=800>s>3p zWRD)HvT6->T=nYuf*x8&8Jvw_Fql$A9K0+@V_w>BEHy2Z+=B5>f^P#k_tsk;-dMaI zt9=$$yhWp^C0Z;BEMihKTlzY%1#zpyA&F`0jsHUQJ3} zjM-I$X#Ef!i%z=B{<1oSavDn%-+=Z6H%D}tZLyt1onhamOnQnJcK~Ede5vAyu_DkL z=voM-)vGF6ZfZMErXD!2+{1}i6~(<`6m4+arI;iHyRITz?2^@C=&!|?XbrMMlSJKA zs>HaQJ>Fv&s~*c_C@L6<-8z4#@fd#GXljIM#8+9wvXvc-m{O`P?th~E>b*BMmpA??9Tc(>1mo36TDf4X?&b1+TT($W#UsoJ zk|`I{urY?V`c1dd%6H5o@bO-^3A@lwyn-DR%+{q>c4W_05*4~Uza8HK|awRvbdPTvp$^Zh}3z$!fCrrRE z&nrpG4bEd8{X2E3xGC<(2FM26 zRP~mlxaZ?8B8v))fg5jUwiR$aGn5aa*UnJz_~JDS(hjqY@E_?9}kSQ{O9H&YpT{>HT^_v3hyPx8H?17mF0eQ})DI9y73@oGkOT35c%;dV?s~jZ0 zonqX0Yw61v_>1YJ;3}5H^I(&4-86)|Vn;?B8 zBR3vVg5le6W^|jbnc4njRvT_3$~$M6USdB9g%{RE1g$w#dQ{M^eh)4-bh@t(~7DMrK%t+eQP+{`>TLYd|A{>co4h2g({v0j`L>S7<~XY0jj3Z{q&17es>cwdQjBA()h{Su+3DJf z2S0!|1y`-Urv!KUgA=*BQAdGVbbKF*JbFs%w+H4@C!}TqmnF{^M0ql2sUjR23ruMa zN-=h`em2XD57O9C3PI2&^+7Fg%G=sK(jV_&90VD>=Iy&O-A=jy+T>#B53|KP@9JH52^Ly7Q(8fVVDoC2bmTstyW|0b5Z{>8~^3( zqE)YD1-F%knX!W@8*lLq0k&2(yVz$LvrsY>(8YB$r(&;|Cjqk+;RkkIyv=y8KB96F zxo3;zpbF^I;n-~DWC~@_04qUoVvdug$wpiHEyFI)*aKLehQ!sPjB=5C_i&=A43Kr| zk;39A3pUIh>9`k1`!RKzbsgrrOQh(YG>xCKed17t-saGpVEcO|F;Gg54e@Hb&U&%niWz`Z2HBVFE0(K%DU;xP&Hh^Stj z*6Jm)Tu!howWk+)fsu2o1w7u*q=#BY6zntLJz4!U*V(jA!COpl=0ir(L~1WU8{DX8 zY`=V(JszOgEeZIVrNCE$X0DmuVfVu*LU8Gt8IO%z#gLP0O{6!}f%@UflHa!mcea(O ziU<9?Esa6RMg#9(3>`%^E`n=Uqz!wc3X<8{5Z`WXFY!;C3IW41CTos|W!#lXz4kNY zcS?J;U@q7hCUM8(v$Jg_98m#5_8E>^FfnW^|4+k3Qnu*&vj)nU?P3x%N!*-Q znDU$)N@QL-f!=qdu8T71_G-1F0n>DNWs_R;@7C26-mfh-xh5fOpgL;Doeip!t6&*rz?wF=Rh3|rRv3qY~M!?W6kO(=@t5o{F zR3=+CTbclL?;=fM9%}KxbM`P!FQrsl9+vFP-Jayb_yL0s1bh8ggF2W7J-812C##9% z=%jRdSqQ`qf^PfFz=)l|4Fc6QK&-kA z^z1G50KoQ*7hv~NqqVm`?I*JOb%yZ9JtO zckji75;RRG83LQCi+zWji2p?}I(mp&yx$v|;s+V)Nwr`51C248a& zU;62peZL@L%W_~_W6)X4NKIq>DolLClLm0GIS48ld9t+VUEU;)^9;@gkT?n%d|jH- z@HNgOt3v=^vRU|q+KBA&c?|GV#6oM7*or%AxB6@sM*YYm@Pt`=Dz__x{}-8TjXa2o$33|y z@e@1%iwTh?7tgegw0~TcLk9AIa~}|_D~SgI(;fclI^&}huUMXT4!BoMP24pr>Aqz( zeAO@?6a~!AQIBD(+8QG~GCg@k2Ni4H?~GVou*M4l5I^S(ZJ60wxuE=FM)rV+jP93A zFMAxz6<|mR&BbkG=T%c@cy4oUrC%LCa3N{bQNKh^@&2_~@Q4icwbj9AXRByH*!K3ppW`f}NIT7^Ig z*+rshbD8gJE=rWqpQzzpvVQa}dXnKmOBe03Y4>J>iSx-&fKhkM&A?o_i?YpZ3d-HX z36rxU*~UlH)V`K5KK8&tZcRs7h};P6+Vy0WrW%N${rDF$H<_ z9i4mE(u=o){Q-DOsLHnU!(t=!E#~oSih8?rNJSM?S!7i5XkB6Q`OY z`@j9r9P9@Vs395x&&h~zCEvlPH4A*-Hgjfhn?Me}39}}R5U9%U--RD_n&X!!p4Toh z8uQ!RqVyot$#S*XenqY3y1=zUGmFuXJS00aL4vE?Wwkd6%VaxVjmDg2YD7?j>7E?d zAeR}xnx((ZYoRgo_N z?5g?E3}_m1JJ(5%5LAm3&OHE{kpo_%e&6_cT&MFAmui1tWmL;Thav_xLBhE}tlIl3 znUG1@fBU7hK(5aIq)X!f1nyOJ%!d2rZ-w9w|7YWcy!JGu;L7<`J}MTu}!wIuQE}y=g%5<&;2qc$WLR!u`mHC zAX4V8y%tRYa(187WQ}5Nq05sF7SK|BwC@;H^%Sb!YNgq5o8ljKysyb-ysj!0wgTG} z^#?a=l2Rqum57VBg${hCSeS%*$8aV4df3>~>2})j?Mv@bCcJwO%5kh(sLZp=TluPg zn<+sv1IS0y{H!kn%s@*4# zVNa8Nu5j(KJpEXG2SbYqpq_?$5843mfDH^RX#QwaaI{izQl`+~Tm0Mo+Zdl{At3Z= zBuk)W2Ph|3`#qs{6Umi1k9FA%-Z)z(gQ7Of!YMLj1sBq;YIFgd-xaLrQi;O z^p?ea#3$FxlCuprGfrjhH=8UHY)lDS;0wvYZER&ToX3(9+)dtyJxG&FTiAYMk~l&6 zpHdeADO<`J3Sk$QhySY#*rhv5&G!K(t|v`$)`my>cOQBt#IniFy6yCvfcTq0?vwe)*bJc{wq3>aP%u>}TLIiWKVGXXj+C)^>y9dlSplwyHTu)b9RF zA6K8aB0A#*ZC9xi{Q7QPl+6$YZi*`slKK9xxBBnM%P-huTdf{#ovAr~uhAcG9rEh* zS%xs}6lxY_U z$yu7_;DD0kB*ULD7OZ0JuEvFbJbJ9V3Ybmgw|XM{ukT9DD_ILoe-By6!ae!Ftk=K#nm_-? zX$II1d7W!M<6ko;g=^Z!?Vw8Y1mi&oVMEoeO^%zKFSstrUZW?;k)n!;B&Cd{!$Oaf zVOv5ZcO?jUxnO^Xw}CTF0C>gIdjdOHz0x3^iWYD^&h<-Tr+0zr>l3?&80Bz_Sco_1TP*XD{-7Js}>${!gFb@BdD=^&0x$J^kN*@_!xO3$nq%ZC8DMw0f+@0~JC* zjv=?N7l?ji4pxqw zfcSXpEs|gM9u#C3L(;S!!Es@HUstl*!+Kb zO4;@Ez9&QfaAYUmA@3n)+MYUHbyNw_eo@(`VC{N?$cCih|JZOFaB<5^TK;{t)c!!x`CIB-^y-fS8p?YzRK@S> z*Au5IVKYo8rXWWxBbRJ7ssUy_~5NoN4Ky6SR7X7 z5AjUkwN;2S>8q#A8JE0I*pGV83(OUxItrz5R=_Wk4j*e zE(WW2_HKAinvRKW08Gh%H`Ub|cN27pz2pFJ>%zfO>PK!AfU}MYZceA$Xw+DLrKmSr z`33dvaJIBG!4HIGaYfc{so73^Li_bCv2Th2E)V+T3odVuE!;^Dt<|E0N{{Tg>UWp1XOcaZLdzAKw``Cuc`W)gX`G_)r(pz8wkaTCxYfr#lj6?OAev#k%ozWm z79OC#HL@$bEj>c_Xk;oXSPtk;r^sIoJwXz1dh?(<8U?x%5VT~n^tR(St+lE>bLb>V zS8?>i9tDCL4Lo-+9a1-9YxCc|t}Pe{IkU0X5GOK$k)FrWWUc%s+X|Cajumw&j?aSI z)H^QY%FawE^1F$+_auUDzxTJBDBL6rZu@JsWUmDP_j{hVj-ZTHYQ1(cbTUorYLu)s z-7sPFKBUgEA8a!vZMTom9VveB=F#Xfug#z}sz&iKJ|L_{H6}&@3>v|u*!-vU{NIcJ zmHwL5aI@pc)v62EdI4Nzq|>H8Cb*5F?cEB?Rx9$>1N-U%4Y;+WJt))G4yW-{_s6@r3$cz%Y4T5_Rm)H0Lq6-2e}N-bg!=9T@vU}gK$ao zyK{dHVgKnkpCE}LpSx#O4k(l=t&u;9?Mm?EH2}cmU7Ym8(i|Y^l3hGj>c(?J-@Z#N z%7d3^7uX=iT*S1d#L-z->rH{=ZL+~VJ{}{`>#sQOS4-?31DJPGg~EV%Yc=bB3x^Z= zPhx_zC9yfktKAk$5A>x=^RRs~n!bU#OqrYg)!2@G$=)%k*n_NrRLu%W>YCk z!4mn(13@WZvUhw0NXK`oTd)v6+6mJ{X+>~z_AKn0bc1b5nUPvfXpQ#|cn^i>6ZG>1 z&Ts9>iofmI_IF*u;a@1x_+Xu~8MrxL6PP&D5G7#E%6 zW2lJ@zR(1i&~T*rb+ZjEbBp_70^4-+|EPcUKxZXBS;6Ilu1R&KTIAMp$HjJ&^?6hdH_{7bch8%F)#3FHiZ?^GYVvV=4Lg?39GZ*xJmPy zjZU?Gec~0HpOoI!!e$TAY6%~^#Nk>Ez~qb)ssjP@yQUL{-IY;CJOE~Rr5xsBpuct1 z|9jR*)A$VjDZuu7XE8)N)S&gyYmv5Stdn*$Rc=M5sL1MB+*@hYXfL3!RvcG?9{iSA zU-3;x{V;1$Lj@@d^M1&u>M@1-<+Y9YOplM$A}#_{nL-OGZ|A}|fQ-Q|h4%dRoQd!2 z-cGt2`uc1(u*UV002;?hj;g zQG8hvDUR_O2E=~0@ImfXcAUo^ab5tut_GXWP@q9cOl`|(_D1ce0aYQjkqv;G>59$T zn(VHoR`^scl!$+>H3GP&hU(2yE|xwYKdfHwSd+#<6~Exvarc`er)%;5-8&Ryc}_pQ z%;#X|!{9vu(mbJpsGh0~?A1F~V`oqM{HEM$HK2Zv*U(!{h+uw7%U6&40`F};lY+hH zSVt`?f=R@@BP(2NrN_y}e>m#I*&e((_e8_4r~G6nEOIZAddF9_xO{3#N^{?OwDp;W zn>;{hBA?#wVQ#~a`qY+>EQqBSTD~*z`6GR;k2qKAg!0h;R+|xTKt7WYPG3qsMPo{D zAm!EUB5Rnb3IOX&78z5&=$p+Hbmv7|?O0FSu$snWx6(LK<(L}VT)$fq3F;Ph?8$(j zcy5=YujT24)3J7i9l^E%Vjs>yyow#UV}C5DW!xxf1=kda$s|k2!2u+gavEMNL?~y} zGK<}`SYf$3E(r7+0A)G_Uh?UM%7d|kD#!7axRYGDO_xxq*K)7{pTkSNNG{~Lq`We%FbO!s2;>BZY(0TD5~Ia!p4$QelK2l4BUt1~! zsJ?hrxtERZ+WPlq`?J_4S+egT#AP%Rbx`s^=c9c)c6WwSV8>!+# zd6lP9?G!%`l16QB7g%go;H~e#{rki}VvM>8(U1MoeLyuu$ExHhT!$M#dx=r}ud?B5 zMkHc@rqyo}577P->V*>%S++&1GVcKdY2ko}qwf}GwvWk?{o8I~bywpUHn2+BpoEj| z$xjF?mt$Q40B`G=At1^2Adwz?jgVm_2b_Nnb;cKu>8PBpMP7TQr&j>|k6q&KoG;Mw zjIHjmF7+35d(TbCP(R}a?P^H>PD)mWlF-Xcj=?topnhDnGrIrV`27-OvXG!!k_qh= z1?OMYlFn)P0wS9U6J5(uM)58oG^CLNwuT$Y#Y5Z?{U=-nO+TLNbzbOy{B^Ex@-{Mc zVlY7BdofsNT#t&YR?G@v$J!u$IOJUB69k#$Q5sjuwXp7NF>qCcAqR`)?Q#Wt*jdew z3`Q-x9fVE5&b3RByqOz7eyYREq=!N_dW#dF(SGH8`zM0% zcYZAQ93NixDNb~B-@e%sdL`4pbJ95=ZYWE%oQtl1#n_+hhkn~E5T|}ov)m6xv}_Lr zjR0T!XfFkhem4-1YHFVvG+%6#gDIy*YMhfX(%iFmW^Z^dVLW4n-yg$r(`lKbo%g!8 zr4--;oiLtWbjV}M{DEt1jj0#)E0oL)BC0+E#4EZkCtUe zNr=A@RU^B4l;uC4h&xq*OFCy)#~TOmMN0|CMkLW?*ODw5@m>5WV(@2X{Ljmp2AWrr zfFL2*!(-lT_XjII+$oDO8--r%%NY&6Y1@%EbSw2y`F^&gTEg`%f4>jcq5y4Q#{k5B zgUNHbEE@z5nSsPtq1>Kz9>PrrmD>B?!<*p_Ws6?qGU`)?u3fy;1tdcLtU;lIP7`q0 zCvTUM_l!~I*8_yPwKrWUOb>e_0aTmcuG@=cnlKGvLu9$rS|z!?=D55B{HBn{vTs`P%-6S>K> zHRkvAJhA%$D`O~NIdJ}7EiBWv*%jYG*r0Q~7oi5rWYjZFA9Ni6O9+KCn6K%|1f4wp zKK7WN1{xnLI`YH4=$%{tlDF=Q3T<;GoTpMtGL1BD6E zZe!B@2yfd`HgS5Ndv9pAav9c0ZTAJBm5WwsG0%ej45tBvaIb!(z~PxCfaO@?3-E9Z zyg%{Q-4t};UKWYn_IO&D+2W~j7M=zQhHCI{H{>AX&I%TQf@a za|v^R<-kFkd4Mj3-%<%e`d^NtFXz7K*J|}gueha2ck4Sg?#9P6w5u}>2Dyjp_0N?k zT6WGk8ccK{T(Sart0Zr|JMFM3wr(`y<&gR!(R>bnX4&ovg`PPmwWk%CQMn&lGKwXq z_8bS#-L`m7tUt7$UQMwKBXhyH&)plrw|ZD3`qeGS^UFs0SmF2D`l!q=$ zFuQ$pHrsdQRsL-GvT@qG^_;*QQ;QpY2ZfEr{>Fvl$whDdmnEG~gXc1%-ZjvS2p`+P zh~M$BmE0LAp7PhQ$cS`qPxFqj%C&Uht!(EdzmBLL^$XL+;^GUnST#Nb;59>Yx<{Senm9uh@>hPLqCpZfSd+OrC@6$`RR z3O=F)gfsH05365;P`_y8JJ*Z|t@YBCo`V=k5E3&@OwvkiF%hm37z$i~wgxL#Ax}{X zyCO|$_05B?#bH(oE}p~VEi4DOiox2^bAwk)`Cc=xsD)4+iK z4X_@okuy9dD)_;Fhx8PaE3oj10-UyNbHXEw4zKcrI)P9Hl-}V`;sM$L_v$yl3C+Dn zodcsvxP)pNH-*i8YEk()`z(SxhEp~R*E3kG92&WvR0TQ^NZcJ3n|b>6Im@fWo)d!^ z8_uUFlG>_&$?s&G5~W*?Q?HkzRj=!V{F57b!nF|SKy7BPmbu5;2OsWoh|39;SQ||0 z8eFepZMc^IaBE^RKX34p;jj`9F`q>-q;$CX(IDH=JqNp2=78qoc?mNxoow(;{J>*` z4_vhE1>w{gdiMTn5f`#<4tSn8!OX9sAgBL}FQG%PP!3tj6F5qQPNLgwN)GzhdsYSg zQCn)c-TUWeF|>^1f;{2JZa|;v?f~t9Cafco8+XB@b47av7fHyr-u%dgyk1?mOAbn) zw%te=BJA31jiL1cs$#@}xavZi@c*;NJ4aZgpRZvD?93YLB9&o4%^S)Dz{9vrL| zP@<;eUJ_2{?#TVBI{!2l`~(qz@DG61lxXc4S9s;{l$@uzYq9pEgq$aT$eNb#BiG5B z$-cKE)?Tim4%=dl zOL^}&;Z!)INPCy=`GI_X(7CXymn|&5c{+sapQ7-ttr_N^ zA`I@XmGNX&ST?AnjS!y-;aavn>_`82zI@LWE+t)R+@x;_wYrycf#s2RPDw%M*M_IH z=5@rlf<+Ejd4pjku7!Lm#S}U>OJ1jfozA@5);kJfP&c^Amn|&@xw%*~cmgf$E%rfh z3R$}T9n(9O&9A1MdTnRap6$ILA4_YVV^&pG7uFgzYYeTG5h)wG?Iktq`9^ADC`;Oy zhy1bt-jT?C*9HsiB{;&T8f~PbKlmaAu1HqiiuR(Y{Zg~A`%u@bEH;$?a?`=~%`N@I zueSSZ=QJ?J>48m<^*QjixDs^rdXwv&RWEPy$n;Nr`0i2-TH8XnJ=f}W=z_BEhF^GC zaGN8_Qt5S%=PiZa?v77Xi ziEojB;fy;IDfb_?@Lz1K{#geqhW<2xg!6+fH}lH|Y9tC=(2bsJ=~}1a8++F1&p$Xw zOLOV#`W*c%h>T*9+X+;h8zklK<#w8NzWC%7jd9aZZ#NniCYD8{%I&F-?yhybZsMtW z4_d91oNmTTJ*|*@uvW?|r5LQ_`Yk*E^ByZtw2JT*+xuHdbr?$4gz$vru6}5;fD)Zv zZ-&`y4o1I$GzHmk)33nffs7wh;WO#S{7T;5>&Bg6SaD84#Gz)-lF7m_v~kLDHWdBh z>cR)|AWgp<7%v_dxCI|8$L2(*>v*{>XBxd}rsPk?tS<8rry5O5;2v%*FAr?1J;qBS zH8dK58Gd<#atrQxtu8ZZ`T5I?dDbfx5Eij^sHnC;5N!?>BWPk}S;)I~Umlgp-2m1b z@GdllRDt@S6OuA5g#pa0CtO<~LrVG$;yaCuWlWgr$gQ3(487KjeVNB+#6^7mGD|zc zz`d->)O!D_MVgW~sE|_+CT;Cb_2r&Yd+d;& z*Hlv`IfVX+sJJ-kSPSPQfqDW!hm3t^~$BfmQ7GY0bRaxKk7ly(xPV z4?$OgRx3_0H(II892uXc2wyKU!+WO%ntf@~ms#Dg{8HYIU(x(-JmJ1cZcTWv#vFww zy+iCloUNT>Ri)^nz2??jrif@JU!P|qP&DVFjeE-XW{ZiD>JC?($GU}L?c47^ z=^yUQUssY?srD0EUBUH=?@0%~d?M|uu;9hMLm33psOi*9G3Y=K+43dCXO-%z`1cmCVl8Ql7T*o&fYh5aFB4vSLBrO(4W=Lzo~VuJ{GG)y0sa+@LAv<*tsV)mjHaMhqeuHCX-pf!!yn=9&r zkDy%-bG7_3f?KpXdp}1S#_U&Low8lIA|&%J>a&44`ovq7taO;f?cZ*?Ab)QVhHP$K z^3(<1F*SWNjfCt)NZ~zKbPu`%qqg+|E`8r5D|g$mIWG^rA8r++^Z_hhIi+Ai510q2DLA@%Nn(gx63$c z0++?DHT0I~*`z^x@^q8b7cqk&(V5c13jCfcUv?T=XHD$J&_KNhtiq6bfJ&HkS_P4Q z5b2z4bBOPxe4f=GXm2VA-dN-E>rWa69P8BrW3>qge%k=7RG#+9DUF~pPMiY~J7Niw zn5*l;p92@`!xqocWFA5FfnDxD$PF)w|N<0uhKObWKZ)4!U-auLs0V}tS_Iq(jF?SJfgsk|?z+c>^ zK2$l3IeIu~yU1y~WlAose-3#X^*pLyuKuuJ|zV;qtHxPt`Ye^4{bBRgx=AzoPI zn;c$tcIG3$*~L7jo4<~scMCuyYM1Lss>9FWf6V6)rv>R48bMnY5;wk9J{f(|#hj<= z3JDphR7^5o(mEL`j_!7u`BA|&RYOya*Tr9-YFY`8{?wo5&rI8Ib_275Di1H50m~lm zQr~>Z1%u5pjhvKyc6V=Rz&%R(h(qYHs%v>!Xw~1RwAEohWU(6$e^xuEed~p5;>iQQ-DW! zbEo-B%UsQzsR2V(fYONxI5nKh12dX6e^`=M^XuOOu7^$U-jP`nc` z_ak4c>p=h1m$hwu>E9WN1IJx9*Yg?;-*qO{$2oXM4(lLly9tNyo<`X9Zn&ZBJxlzg z3EwB)B?K_LqMY2q6?9XEE2MXQ4}SFQt$0QHGTp&lZ$i4I?O%C4XVMS2y2iIZY;Pw6 zF{&Y|7tKx>y{AO-BAsJ~ge>_}uMyexnZ%8P4P7s=dkI=PPsboUYpwz9g}yPXuRr z8xj+0^aYOmR9OX7Deq2ud2bjHSg9_{Y{$5@6;?hv{aSCKBqL;Uw=%~K98W8Mt3Eya z#0B#qQD$p2!BQ@J&yVKu6*Ja5=4+YjLzg!CiJ&f@&yriU@HZK7imLtrusjgHoK(7C zk#)Fx3lgZ~X>DTBabT+z)!lnWrCmS!K3GLXp$< znoS?Vc`!)12~ew5(~SK7CV0k0n#49xqu~O>CdNzO^ME=o#)yUix({|kV5$kMN8EVj ze_0*;tAqJ}!(b+D^vTdaL2bMJw5~DfX#04=1&Le5K)MLyG~X|g(NlE!=*%{S?|m8g z?ks&qOmw2wC>>YcNz%__EPIo?Q?3P%`XWM{6Tqock&~5pvvK=J#hbFzydL^|dyrlh4)51e z+j{F8Qe)M##Bthk23lLRNQ1}PhNqh zxr=wQV9+rMyA=?2TrqC+gP^|;3vxGVFMlnQweLwf?BF8v%w|eIf(8?VQRDW zu*P$s}J4nUmhBz&8eKEKs?q!Q0NGnsew z^#4c9D+6NQTDHegs%Fxm#^hkg+n_8`+%zwK;`1AcnS0)xY61}wh=+@@VZ7CbuQ}5N z4-i6!)28$Ghc(M*#-K;?iBz{L^ZIk1;c;he3VvqNP!V3L%~6H=6BqbbQW!|?Pi=tcKNO9&q>un;7j~n%dNMZB1Coj``p=5GrJ|;#jE+R4PIq zwB2z%3sRx&OzPFTg^HI+bHPy+`3FdzJ z15o!KPv_-3R>M?;i!$JJ`Wa1`K#OTI3gVXd{nm`pJF;SbU$pUkw>OWvvStUBy?^7GzGAB1%^cfQ1=}dITQcab=gGhhmd2Jr(_cp7kXuC!-eDDjh^ALz z{qW~NAeB$GSL#hl)1)&_7t?lRZ=DSNvaOfm+AhMHdEGkqb@r}@)hu3-504`?!4t|y(WCWc+!S}n zfq?=MV&|9DuiESP$814?<7oLdb?^N)y@lxotoS>ZZYIheiL+0+xW{bfsGAZy$%3FFM?q-aozk z8U@^TWB@Zx(6VTqj*pY*n3~{FrXk~Bm~@jF@W^#;@ZN$tn5IfWX#YI@vPnNYPr1mK z#RQ=rZv>O}nwAGD+xFOW4i*x!2kE)ULo&8p3K|uBUZL{^tfi0THK#+K#Fp@pus4*) zkF*#T@G8A|=uDfbK%mBh4MHw!*-fB8V`nw_n=Sr(FFnkDkp_72;;}=6Guf~YPEEN5 zM?xynp>NH76@qmYEn+GJP3~)l-9Jr;|CQkk5Fc~2-}GwCpSNPGxi_wRUpM^AjDm+z z`SZ^i4B$2`$Io+p&%zO= z%lTC$ul@b~ZFWPVjC4Lt+!J6`o=f$Tcq=yBDLb)$(9x_h=3o|J6Bwus2v)qrkoDe? zu(hGPikJBqKr$VEg6#d7KV0{p`Gh>AG|*MU<}L8#g}$U`fbZ64%-*2BqkNstV=PbJ z{b9!A$jUqmrPG25r`~Gsh(MYXp;M*~-^$lJtLFQ^&GOHfN2jNpsXEmQq*TdHg|iN! zeyFPsW~7OJ9Sh$FYwfJ*ktQL9axJ@RtA)=TJf&y#Bh9<;oM(;n*rkrH-f19;fFJVy z1g+i#WJItsJ6Ql30o9ALabF4s8n8iw^uc1mlSt2Ld0&)160<|3aikr(=>$;i@4)jS z1C+UrAtt=pjDKk$meTod#x2zqhIJ}KF9By3+?3$e*#VRcq z>{on~<#b|>8M>3G@uF(AQi7&(rH_VB)L~ye$#a}HRI>H}H zVZ9j&Z&pwO+wo=Vjh@)HG6@+{I_myFXs`7|YX4Lc)yRUak)r2$VDGkoy?b?L_p?)L zM(@_`&Q%euc#mu%OZ#5#T`TSW#Bg+sgHl%%5aa>5Tanlg^!jDKd<-t~3;O7}qI$!P zxiPpwX$w@7GpH*$yT%XrzF z$t}Kp*z$3brya)zh80f8I7rPE1>QP&<*`+k-Qg=mO_*w=&PtlW_9B}A?`5dPHwy9B zY=Xr7ql{@4dZ6A(nm?N;@sKEHrHxLid;GR>-)LbF^txwhLf%eVzcnLYTNHi0_lnfO zc2#D1LGH6V?}zf8vdh%0F^Az9&E^dsq0PA*M41eXnT{sE9p*os70jRF?m5aou3elZfE9)^i?1#s&0c9 z8D^(c_)B~2o;c;_f^i48d7eRcM8o1N`APf;+RC zb%8VUWQUyXdOJk(yGdM}^yjlI>Y0PJbmC7PM8JogF!$lcX7g?Ui|l0y5@*Y?)wy4} z?!4@fWq6bG@Y{sQ-b(irVYK2laOm)#zIvUd{{@!y2ncL0{((z!oQe9i%+ z(yyZ4$8MAsK1|QFF2r5$J%jl~*1?mk(kWA1fLhlaCYZ3S8N+su-r(3<&P#{`Su{`= zNpsbAov)9SZ2$h>BSgczr|*+dZ1-KV*8Y=e2Ns<6ZB@4780WormW&GMxO`K)7A?H2 zeg_a5Kg~wKXPC!jQll?iKlwM!n7{M8zYOJvIv^Bq7rwqo`6n|Zp6WC|bh={bTPoQW zX|$Tt8J=Lva_;9<7Sl;i8}a6>?2pcW%S4(R3O_&f=Tm>~_8)nYSAr)`QFKl|&ye`@ zvBgW>znuEJw{@%qc^h3kv3|FHhLYBFk_RG^DmA7SS;WftTGH;{_*B$AL(oUy{Ps#- z{&SIk^xc0PT87LyK)E0@z}`vnd*NiGTaN=y@X6P4aY-sb^FXd^8?r_-4yotLr(pcK z0Bh;3jxsx~E1p_D95q*`9w;quYoovTtE%>8zPUv0_-)u-F7$V=D6}^^dXHPv-E{F;B8{}P5}Q@9%w3*-nV-8e*lM}a6SM4 literal 0 HcmV?d00001 diff --git a/docs/src/assets/cli-welcome.png b/docs/src/assets/cli-welcome.png new file mode 100644 index 0000000000000000000000000000000000000000..e0d2545455c7c71af6c0fe68518510c13574242f GIT binary patch literal 24862 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 literal 0 HcmV?d00001 diff --git a/docs/src/content/docs/community/development.mdx b/docs/src/content/docs/community/development.mdx index 0dc7881..59468f4 100644 --- a/docs/src/content/docs/community/development.mdx +++ b/docs/src/content/docs/community/development.mdx @@ -136,7 +136,7 @@ KiLM follows a **type-first development** approach. All code must have proper ty ## Project Architecture ### Core Modules -- **`cli.py`**: Click-based command interface +- **`cli.py`**: Typer-based command interface (modern CLI with better help/UX) - **`commands/`**: Individual command implementations - **`library_manager.py`**: Core library management logic - **`config.py`**: KiCad configuration handling diff --git a/docs/src/content/docs/guides/getting-started.mdx b/docs/src/content/docs/guides/getting-started.mdx index aeb0525..fc6b237 100644 --- a/docs/src/content/docs/guides/getting-started.mdx +++ b/docs/src/content/docs/guides/getting-started.mdx @@ -14,6 +14,26 @@ This guide covers the essential workflows for setting up and using KiLM (KiCad L - **Git:** Optional, but recommended for library version control and collaboration - **KiLM:** [Install KiLM](/guides/installation/) using pip, pipx, or uv +## CLI showcase + +A quick visual tour of the CLI experience: + +### 1) `kilm` + +![KiLM welcome output](../../../assets/cli-welcome.png) + +### 2) `kilm --help` + +![KiLM global help](../../../assets/cli-help.png) + +### 3) `kilm config list -v` + +![Config listing with verbose details](../../../assets/cli-config-list-verbose.png) + +### 4) `kilm sync` + +![Syncing libraries](../../../assets/cli-sync.png) + ## Understanding User Roles (Creator vs. Consumer) KiLM is designed for teams or individuals managing KiCad libraries. We can think of two main roles: diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx index 9e34065..b73a38a 100644 --- a/docs/src/content/docs/index.mdx +++ b/docs/src/content/docs/index.mdx @@ -35,7 +35,7 @@ features: details: Share libraries via Git with consistent metadata and environment setup. - icon: tabler:terminal-2 title: Modern CLI Design - details: Intuitive commands with comprehensive help, dry-run modes, and clear feedback. + details: Intuitive Typer-powered CLI with improved UI/UX, comprehensive help, dry-run modes, and clear feedback. --- import { Card, CardGrid } from "@astrojs/starlight/components"; diff --git a/kicad_lib_manager/commands/add_3d/command.py b/kicad_lib_manager/commands/add_3d/command.py index 5a008f1..2f35c30 100644 --- a/kicad_lib_manager/commands/add_3d/command.py +++ b/kicad_lib_manager/commands/add_3d/command.py @@ -197,10 +197,15 @@ def add_3d( # Add as a cloud-based 3D model library if library_name is None: library_name = metadata.get("name", directory.name) - config.add_library(library_name, str(directory), "cloud") + + # Ensure library_name is a string + final_library_name = ( + str(library_name) if library_name is not None else directory.name + ) + config.add_library(final_library_name, str(directory), "cloud") console.print( - f"[bold green]3D models directory '{library_name}' added successfully![/bold green]" + f"[bold green]3D models directory '{final_library_name}' added successfully![/bold green]" ) console.print(f"[blue]Path:[/blue] {directory}") if model_count > 0: @@ -211,7 +216,9 @@ def add_3d( f"[yellow]Assigned environment variable:[/yellow] {library_env_var}" ) console.print("\n[bold]You can use this directory with:[/bold]") - console.print(f" [cyan]kilm setup --3d-lib-dirs '{library_name}'[/cyan]") + console.print( + f" [cyan]kilm setup --threed-lib-dirs '{library_name}'[/cyan]" + ) console.print(" [dim]# or by setting the environment variable[/dim]") console.print(f" [cyan]export {library_env_var}='{directory}'[/cyan]") diff --git a/kicad_lib_manager/commands/status/command.py b/kicad_lib_manager/commands/status/command.py index bd51c01..61860d6 100644 --- a/kicad_lib_manager/commands/status/command.py +++ b/kicad_lib_manager/commands/status/command.py @@ -14,6 +14,7 @@ from rich.text import Text from ...services.kicad_service import KiCadService +from ...utils.constants import CONFIG_DIR_NAME, CONFIG_FILE_NAME from ...utils.metadata import read_cloud_metadata, read_github_metadata console = Console() @@ -60,7 +61,7 @@ def status( def _show_kilm_configuration() -> None: """Show KILM configuration section""" try: - config_file = Path.home() / ".config" / "kicad-lib-manager" / "config.yaml" + config_file = Path.home() / ".config" / CONFIG_DIR_NAME / CONFIG_FILE_NAME if config_file.exists(): console.print("[bold cyan]KILM Configuration[/bold cyan]") try: diff --git a/kicad_lib_manager/commands/status/docs.mdx b/kicad_lib_manager/commands/status/docs.mdx index 04c11c8..20ec178 100644 --- a/kicad_lib_manager/commands/status/docs.mdx +++ b/kicad_lib_manager/commands/status/docs.mdx @@ -15,6 +15,9 @@ kilm status [OPTIONS] ## Options +- `-v, --verbose`: + Show detailed configured library tables (symbol and footprint tables from KiCad). Without this flag, only the high-level sections are shown. + - `--help`: Show the help message and exit. @@ -26,7 +29,7 @@ The command gathers and displays information about: - **KiCad Configuration Directory:** The location KiLM detected for KiCad's configuration files. - **KiCad Environment Variables:** Lists the environment variables currently set within KiCad's `kicad_common.json` file. - **KiCad Pinned Libraries:** Shows the symbol and footprint libraries currently marked as favorites (pinned) in `kicad_common.json`. -- **KiCad Configured Libraries:** Lists the symbol and footprint libraries currently present in KiCad's `sym-lib-table` and `fp-lib-table`. +- **KiCad Configured Libraries:** Lists the symbol and footprint libraries currently present in KiCad's `sym-lib-table` and `fp-lib-table`. Requires `-v/--verbose`. ## Example diff --git a/kicad_lib_manager/commands/update/docs.mdx b/kicad_lib_manager/commands/update/docs.mdx index 186d0de..151064c 100644 --- a/kicad_lib_manager/commands/update/docs.mdx +++ b/kicad_lib_manager/commands/update/docs.mdx @@ -72,18 +72,6 @@ kilm update kilm update --force ``` -## Configuration - -Update checking behavior can be configured using `kilm config`: - -```bash -# Disable update checking -kilm config set update_check false - -# Set check frequency -kilm config set update_check_frequency weekly # daily, weekly, never -``` - ## Troubleshooting **Update fails with permission errors:** diff --git a/kicad_lib_manager/interfaces/library_service.py b/kicad_lib_manager/interfaces/library_service.py index 0401d35..f619982 100644 --- a/kicad_lib_manager/interfaces/library_service.py +++ b/kicad_lib_manager/interfaces/library_service.py @@ -4,7 +4,7 @@ from abc import abstractmethod from pathlib import Path -from typing import Any, Dict, List, Optional, Protocol, Tuple +from typing import Dict, List, Optional, Protocol, Tuple, Union class LibraryServiceProtocol(Protocol): @@ -18,6 +18,7 @@ def list_libraries(self, directory: Path) -> Tuple[List[str], List[str]]: Returns: Tuple of (symbol_libraries, footprint_libraries) """ + ... @abstractmethod def initialize_library( @@ -28,12 +29,16 @@ def initialize_library( env_var: Optional[str] = None, force: bool = False, no_env_var: bool = False, - ) -> Dict[str, Any]: + ) -> Dict[str, Union[str, bool, Dict[str, bool]]]: """Initialize a library in the given directory.""" + ... @abstractmethod - def get_library_metadata(self, directory: Path) -> Optional[Dict[str, Any]]: + def get_library_metadata( + self, directory: Path + ) -> Optional[Dict[str, Union[str, bool, Dict[str, bool]]]]: """Get metadata for a library directory.""" + ... @abstractmethod def pin_libraries( @@ -50,6 +55,7 @@ def pin_libraries( Returns: True if changes were made, False otherwise """ + ... @abstractmethod def unpin_libraries( @@ -66,3 +72,4 @@ def unpin_libraries( Returns: True if changes were made, False otherwise """ + ... diff --git a/kicad_lib_manager/services/config_service.py b/kicad_lib_manager/services/config_service.py index 6eb2a6b..49b8e53 100644 --- a/kicad_lib_manager/services/config_service.py +++ b/kicad_lib_manager/services/config_service.py @@ -514,10 +514,10 @@ def set_current_library(self, path: str) -> None: def get_max_backups(self) -> int: """Get the maximum number of backups to keep.""" - value = self._config.get("max_backups", 5) + value = self._config.get("max_backups", DEFAULT_MAX_BACKUPS) if isinstance(value, int): return value - return 5 + return DEFAULT_MAX_BACKUPS def set_max_backups(self, count: int) -> None: """Set the maximum number of backups to keep.""" diff --git a/kicad_lib_manager/services/library_service.py b/kicad_lib_manager/services/library_service.py index 1782145..9fe4905 100644 --- a/kicad_lib_manager/services/library_service.py +++ b/kicad_lib_manager/services/library_service.py @@ -81,7 +81,7 @@ def initialize_library( self._create_library_structure(directory) # Update capabilities - capabilities = { + capabilities: Dict[str, bool] = { "symbols": (directory / "symbols").exists(), "footprints": (directory / "footprints").exists(), "templates": (directory / "templates").exists(), diff --git a/kicad_lib_manager/utils/metadata.py b/kicad_lib_manager/utils/metadata.py index a032751..c922625 100644 --- a/kicad_lib_manager/utils/metadata.py +++ b/kicad_lib_manager/utils/metadata.py @@ -5,7 +5,7 @@ import json import re from pathlib import Path -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, Optional, Union import yaml @@ -14,7 +14,7 @@ def read_github_metadata( directory: Path, -) -> Optional[Dict[str, Union[str, List, Dict]]]: +) -> Optional[Dict[str, Any]]: """ Read metadata from a GitHub library directory. @@ -63,7 +63,7 @@ def write_github_metadata(directory: Path, metadata: Dict[str, Any]) -> bool: return False -def read_cloud_metadata(directory: Path) -> Optional[Dict[str, Any]]: +def read_cloud_metadata(directory: Path) -> Optional[Dict[str, Union[str, int, None]]]: """ Read metadata from a cloud 3D model directory. @@ -90,7 +90,9 @@ def read_cloud_metadata(directory: Path) -> Optional[Dict[str, Any]]: return None -def write_cloud_metadata(directory: Path, metadata: Dict[str, Any]) -> bool: +def write_cloud_metadata( + directory: Path, metadata: Dict[str, Union[str, int, None]] +) -> bool: """ Write metadata to a cloud 3D model directory. @@ -141,7 +143,9 @@ def generate_env_var_name(name: str, prefix: str = "") -> str: return clean_name -def get_default_github_metadata(directory: Path) -> Dict[str, Any]: +def get_default_github_metadata( + directory: Path, +) -> Dict[str, Any]: """ Generate default metadata for a GitHub library. @@ -178,7 +182,7 @@ def get_default_github_metadata(directory: Path) -> Dict[str, Any]: } -def get_default_cloud_metadata(directory: Path) -> Dict[str, Any]: +def get_default_cloud_metadata(directory: Path) -> Dict[str, Union[str, int, None]]: """ Generate default metadata for a cloud 3D model directory. diff --git a/kicad_lib_manager/utils/template.py b/kicad_lib_manager/utils/template.py index fd427b1..d6b98ca 100644 --- a/kicad_lib_manager/utils/template.py +++ b/kicad_lib_manager/utils/template.py @@ -10,7 +10,7 @@ import shutil import traceback from pathlib import Path -from typing import Any, Dict, List, Optional +from typing import Any, Dict, List, Mapping, Optional, TypedDict, Union, cast import click import jinja2 @@ -49,6 +49,34 @@ FILENAME_VAR_PATTERN = re.compile(r"%\{([^}]+)\}") +class TemplateVariable(TypedDict): + """Template variable definition.""" + + description: str + default: str + + +class TemplateDependencies(TypedDict): + """Template dependencies definition.""" + + recommended: List[str] + + +class TemplateMetadata(TypedDict, total=False): + """Template metadata structure.""" + + name: str + description: str + use_case: str + version: str + variables: Dict[str, TemplateVariable] + extends: str + dependencies: TemplateDependencies + path: str + source_library: str + library_path: str + + def get_gitignore_spec(directory: Path) -> Optional[pathspec.PathSpec]: """ Get a PathSpec object representing the gitignore patterns in the given directory. @@ -95,7 +123,7 @@ def get_gitignore_spec(directory: Path) -> Optional[pathspec.PathSpec]: return None -def list_templates_in_directory(directory: Path) -> List[Dict[str, Any]]: +def list_templates_in_directory(directory: Path) -> List[TemplateMetadata]: """ List all templates in a given directory. @@ -109,7 +137,7 @@ def list_templates_in_directory(directory: Path) -> List[Dict[str, Any]]: if not templates_dir.exists() or not templates_dir.is_dir(): return [] - templates = [] + templates: List[TemplateMetadata] = [] for template_dir in templates_dir.iterdir(): if not template_dir.is_dir(): @@ -130,7 +158,7 @@ def list_templates_in_directory(directory: Path) -> List[Dict[str, Any]]: metadata["path"] = str(template_dir) metadata["source_library"] = directory.name - templates.append(metadata) + templates.append(cast("TemplateMetadata", metadata)) except Exception as e: # Use click.echo for warnings/errors click.echo( @@ -210,10 +238,10 @@ def create_template_metadata( name: str, description: Optional[str] = None, use_case: Optional[str] = None, - variables: Optional[Dict[str, Dict[str, Any]]] = None, + variables: Optional[Dict[str, TemplateVariable]] = None, extends: Optional[str] = None, dependencies: Optional[List[str]] = None, -) -> Dict[str, Any]: +) -> TemplateMetadata: """ Create template metadata dictionary. @@ -231,40 +259,40 @@ def create_template_metadata( # Default variables if none provided if not variables: variables = { - "project_name": { - "description": "Project name (used in documentation and KiCad files)", - "default": name, - }, - "directory_name": { - "description": "Directory/repository name (used for folder structure)", - "default": "%{project_name.lower.replace(' ', '-')}", - }, - "project_filename": { - "description": "Main KiCad project filename (without extension)", - "default": "%{project_name}", - }, + "project_name": TemplateVariable( + description="Project name (used in documentation and KiCad files)", + default=name, + ), + "directory_name": TemplateVariable( + description="Directory/repository name (used for folder structure)", + default="%{project_name.lower.replace(' ', '-')}", + ), + "project_filename": TemplateVariable( + description="Main KiCad project filename (without extension)", + default="%{project_name}", + ), } else: # Make sure we have the predefined variables if not any(k.lower() == "project_name" for k in variables): - variables["project_name"] = { - "description": "Project name (used in documentation and KiCad files)", - "default": name, - } + variables["project_name"] = TemplateVariable( + description="Project name (used in documentation and KiCad files)", + default=name, + ) if not any(k.lower() == "directory_name" for k in variables): - variables["directory_name"] = { - "description": "Directory/repository name (used for folder structure)", - "default": "%{project_name.lower.replace(' ', '-')}", - } + variables["directory_name"] = TemplateVariable( + description="Directory/repository name (used for folder structure)", + default="%{project_name.lower.replace(' ', '-')}", + ) if not any(k.lower() == "project_filename" for k in variables): - variables["project_filename"] = { - "description": "Main KiCad project filename (without extension)", - "default": "%{project_name}", - } + variables["project_filename"] = TemplateVariable( + description="Main KiCad project filename (without extension)", + default="%{project_name}", + ) - metadata = { + metadata: TemplateMetadata = { "name": name, "description": description or f"KiCad project template for {name}", "use_case": use_case or "", @@ -276,13 +304,12 @@ def create_template_metadata( metadata["extends"] = extends if dependencies: - deps_dict: Dict[str, Any] = {"recommended": dependencies} - metadata["dependencies"] = deps_dict + metadata["dependencies"] = TemplateDependencies(recommended=dependencies) return metadata -def write_template_metadata(directory: Path, metadata: Dict[str, Any]) -> None: +def write_template_metadata(directory: Path, metadata: TemplateMetadata) -> None: """ Write template metadata to a file. @@ -300,7 +327,7 @@ def write_template_metadata(directory: Path, metadata: Dict[str, Any]) -> None: def process_markdown_file( - source_file: Path, target_file: Path, variables: Dict[str, Dict[str, Any]] + source_file: Path, target_file: Path, variables: Dict[str, TemplateVariable] ) -> None: """ Process a Markdown file to add a template header with available variables. @@ -348,7 +375,7 @@ def process_markdown_file( def create_template_structure( source_directory: Path, template_directory: Path, - metadata: Dict[str, Any], + metadata: TemplateMetadata, gitignore_spec: Optional[pathspec.PathSpec] = None, additional_excludes: Optional[List[str]] = None, ) -> None: @@ -639,7 +666,7 @@ def post_create(context): def process_kicad_project_file( - source_file: Path, target_file: Path, variables: Dict[str, Dict[str, Any]] + source_file: Path, target_file: Path, variables: Dict[str, TemplateVariable] ) -> None: """ Process a KiCad project file (.kicad_pro). @@ -782,7 +809,9 @@ def sheet_replacer(match): # Add new functions for rendering templates and creating projects from templates -def render_template_string(template_str: str, variables: Dict[str, Any]) -> str: +def render_template_string( + template_str: str, variables: Mapping[str, Union[str, int, bool]] +) -> str: """ Render a template string using Jinja2 or custom Windows-compatible templating. @@ -808,7 +837,9 @@ def render_template_string(template_str: str, variables: Dict[str, Any]) -> str: return template_str -def render_filename_custom(filename: str, variables: Dict[str, Any]) -> str: +def render_filename_custom( + filename: str, variables: Mapping[str, Union[str, int, bool]] +) -> str: """ Render a filename using a custom Windows-compatible templating system. @@ -902,7 +933,9 @@ def replacer(match): return filename -def render_filename(filename: str, variables: Dict[str, Any]) -> str: +def render_filename( + filename: str, variables: Mapping[str, Union[str, int, bool]] +) -> str: """ Render a filename using either Jinja2 or custom Windows-compatible templating. @@ -932,7 +965,7 @@ def render_filename(filename: str, variables: Dict[str, Any]) -> str: return filename -def find_all_templates(config: Any) -> Dict[str, Dict[str, Any]]: +def find_all_templates(config: Any) -> Dict[str, TemplateMetadata]: """ Find all templates in all configured libraries. @@ -943,7 +976,7 @@ def find_all_templates(config: Any) -> Dict[str, Dict[str, Any]]: Dictionary mapping template names to template metadata """ all_templates = {} - all_libraries = config.get_libraries() + all_libraries = config.get_libraries() # type: ignore[attr-defined] for library in all_libraries: library_path = library.get("path") @@ -977,7 +1010,7 @@ def find_all_templates(config: Any) -> Dict[str, Dict[str, Any]]: def render_template_file( source_file: Path, target_file: Path, - variables: Dict[str, Any], + variables: Mapping[str, Union[str, int, bool]], is_binary: bool = False, ) -> bool: """ @@ -1059,7 +1092,7 @@ def render_template_file( def create_project_from_template( template_dir: Path, project_dir: Path, - variables: Dict[str, Any], + variables: Mapping[str, Union[str, int, bool]], metadata: Optional[Dict[str, Any]] = None, dry_run: bool = False, skip_hooks: bool = False, @@ -1236,7 +1269,7 @@ def create_project_from_template( def run_post_create_hook( hook_script: Path, project_dir: Path, - variables: Dict[str, Any], + variables: Mapping[str, Union[str, int, bool]], template_metadata: Dict[str, Any], ) -> None: """ From 835ddee082bdd5ca4f151271f9545cc83f99d191 Mon Sep 17 00:00:00 2001 From: barisgit Date: Mon, 8 Sep 2025 14:30:45 +0200 Subject: [PATCH 10/13] Bump minor version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 889f839..545e2ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "hatchling.build" [project] name = "kilm" -version = "0.4.2" +version = "0.5.0" description = "A command-line tool for managing KiCad libraries across projects and workstations" readme = "README.md" license = "MIT" From c796d74b684546ce0d81c0950d40e01721622f76 Mon Sep 17 00:00:00 2001 From: barisgit Date: Mon, 8 Sep 2025 14:36:29 +0200 Subject: [PATCH 11/13] Fix uv not being available in gh actions --- .github/workflows/python-package.yml | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index 55a4809..d68b3e4 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -24,22 +24,27 @@ jobs: with: python-version: ${{ matrix.python-version }} + - name: Install uv + uses: astral-sh/setup-uv@v3 + with: + version: "latest" + - name: Install dependencies using uv run: | uv sync --extra dev - name: Lint with ruff run: | - ruff check . - ruff format --check . + uv run ruff check . + uv run ruff format --check . - name: Type check with pyrefly run: | - pyrefly check + uv run pyrefly check - name: Test with pytest run: | - pytest --cov=kicad_lib_manager --cov-report=xml + uv run pytest --cov=kicad_lib_manager --cov-report=xml - name: Upload coverage to Codecov if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.11' From d6e8668497d2e0f28a8d18241eb6ed4cecf2662f Mon Sep 17 00:00:00 2001 From: barisgit Date: Mon, 8 Sep 2025 14:40:13 +0200 Subject: [PATCH 12/13] Drop python 3.8 as supported --- .github/workflows/python-package.yml | 2 +- docs/src/content/docs/community/development.mdx | 2 +- docs/src/content/docs/guides/getting-started.mdx | 2 +- docs/src/content/docs/guides/installation.mdx | 4 ++-- pyproject.toml | 9 ++++----- 5 files changed, 9 insertions(+), 10 deletions(-) diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index d68b3e4..9a517b5 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -14,7 +14,7 @@ jobs: fail-fast: false matrix: os: [ubuntu-latest, windows-latest, macos-latest] - python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] steps: - uses: actions/checkout@v4 diff --git a/docs/src/content/docs/community/development.mdx b/docs/src/content/docs/community/development.mdx index 59468f4..c9286b4 100644 --- a/docs/src/content/docs/community/development.mdx +++ b/docs/src/content/docs/community/development.mdx @@ -9,7 +9,7 @@ This guide covers setting up a professional development environment for KiLM wit ## Prerequisites -- **Python 3.8+**: Required for KiLM development +- **Python 3.9+**: Required for KiLM development - **Git**: For version control and contribution workflow - **KiCad 6.x+**: For testing KiLM integration (run at least once) diff --git a/docs/src/content/docs/guides/getting-started.mdx b/docs/src/content/docs/guides/getting-started.mdx index fc6b237..249ef59 100644 --- a/docs/src/content/docs/guides/getting-started.mdx +++ b/docs/src/content/docs/guides/getting-started.mdx @@ -10,7 +10,7 @@ This guide covers the essential workflows for setting up and using KiLM (KiCad L ## Prerequisites - **KiCad 6.x or newer:** Must be run at least once to generate configuration files -- **Python 3.8 or newer:** Required for KiLM installation and execution +- **Python 3.9 or newer:** Required for KiLM installation and execution - **Git:** Optional, but recommended for library version control and collaboration - **KiLM:** [Install KiLM](/guides/installation/) using pip, pipx, or uv diff --git a/docs/src/content/docs/guides/installation.mdx b/docs/src/content/docs/guides/installation.mdx index dcb028b..8001fa3 100644 --- a/docs/src/content/docs/guides/installation.mdx +++ b/docs/src/content/docs/guides/installation.mdx @@ -5,11 +5,11 @@ description: How to install KiLM on your system. import { Aside } from "@astrojs/starlight/components"; -KiLM (KiCad Library Manager) is a Python CLI tool that requires Python 3.8+ and KiCad 6.x+ to be installed and run at least once. +KiLM (KiCad Library Manager) is a Python CLI tool that requires Python 3.9+ and KiCad 6.x+ to be installed and run at least once. ## System Requirements -- **Python 3.8 or newer** +- **Python 3.9 or newer** - **KiCad 6.x or newer** (must be launched at least once to create configuration directories) - **Operating System:** Windows, macOS, or Linux diff --git a/pyproject.toml b/pyproject.toml index 545e2ce..0cb0fc2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,6 @@ classifiers = [ "License :: OSI Approved :: MIT License", "Operating System :: OS Independent", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -41,7 +40,7 @@ keywords = [ "pcb-design", "cli", ] -requires-python = ">=3.8" +requires-python = ">=3.9" dependencies = [ "click>=8.0", "typer>=0.17.4", @@ -81,7 +80,7 @@ packages = ["kicad_lib_manager"] [tool.black] line-length = 88 -target-version = ['py38'] +target-version = ['py39'] [tool.pytest.ini_options] testpaths = ["tests"] @@ -98,7 +97,7 @@ addopts = [ ] [tool.ruff] -target-version = "py38" +target-version = "py39" line-length = 88 [tool.ruff.lint] @@ -126,7 +125,7 @@ ignore = [ "tests/**/*" = ["ARG", "S101"] [tool.pyrefly] -python-version = "3.8" +python-version = "3.9" [tool.coverage.run] source = ["kicad_lib_manager"] From 4ea46d37041bf0534bbc93918b6397788bf3e588 Mon Sep 17 00:00:00 2001 From: barisgit Date: Mon, 8 Sep 2025 14:44:50 +0200 Subject: [PATCH 13/13] Fix python 3.9+ lint errors --- kicad_lib_manager/commands/pin/command.py | 6 +- kicad_lib_manager/commands/setup/command.py | 8 +- kicad_lib_manager/commands/sync/command.py | 8 +- .../commands/template/command.py | 8 +- kicad_lib_manager/commands/unpin/command.py | 6 +- .../interfaces/config_service.py | 10 +- kicad_lib_manager/interfaces/kicad_service.py | 14 +- .../interfaces/library_service.py | 16 +- kicad_lib_manager/services/config_service.py | 26 +- kicad_lib_manager/services/kicad_service.py | 14 +- kicad_lib_manager/services/library_service.py | 26 +- kicad_lib_manager/services/update_service.py | 10 +- kicad_lib_manager/utils/env_vars.py | 6 +- kicad_lib_manager/utils/file_ops.py | 8 +- kicad_lib_manager/utils/metadata.py | 14 +- kicad_lib_manager/utils/template.py | 33 +- tests/test_config_commands.py | 4 +- tests/test_sync_command.py | 8 +- uv.lock | 649 ++---------------- 19 files changed, 162 insertions(+), 712 deletions(-) diff --git a/kicad_lib_manager/commands/pin/command.py b/kicad_lib_manager/commands/pin/command.py index 5560664..538a495 100644 --- a/kicad_lib_manager/commands/pin/command.py +++ b/kicad_lib_manager/commands/pin/command.py @@ -3,7 +3,7 @@ """ from pathlib import Path -from typing import Annotated, List, Optional +from typing import Annotated, Optional import typer from rich.console import Console @@ -31,7 +31,7 @@ def pin( ), ] = None, symbols: Annotated[ - Optional[List[str]], + Optional[list[str]], typer.Option( "--symbols", "-s", @@ -39,7 +39,7 @@ def pin( ), ] = None, footprints: Annotated[ - Optional[List[str]], + Optional[list[str]], typer.Option( "--footprints", "-f", diff --git a/kicad_lib_manager/commands/setup/command.py b/kicad_lib_manager/commands/setup/command.py index dc76a13..fa91348 100644 --- a/kicad_lib_manager/commands/setup/command.py +++ b/kicad_lib_manager/commands/setup/command.py @@ -4,7 +4,7 @@ import re from pathlib import Path -from typing import Dict, List, Optional +from typing import Optional import typer from rich.console import Console @@ -162,9 +162,9 @@ def setup( console.print(f"Requested symbol libraries: {symbol_lib_names}") # Check Config file for library paths - config_lib_paths: Dict[str, str] = {} - config_3d_libs: List[LibraryDict] = [] - config_symbol_libs: List[LibraryDict] = [] + config_lib_paths: dict[str, str] = {} + config_3d_libs: list[LibraryDict] = [] + config_symbol_libs: list[LibraryDict] = [] config_obj = None try: diff --git a/kicad_lib_manager/commands/sync/command.py b/kicad_lib_manager/commands/sync/command.py index 1fdedf0..878334a 100644 --- a/kicad_lib_manager/commands/sync/command.py +++ b/kicad_lib_manager/commands/sync/command.py @@ -5,7 +5,7 @@ import subprocess from pathlib import Path -from typing import Annotated, List, Tuple +from typing import Annotated import typer from rich.console import Console @@ -59,7 +59,7 @@ def sync( failed_count = 0 # Git pull failed # Track libraries that have changes that might require setup - libraries_with_changes: List[Tuple[str, Path, List[str]]] = [] + libraries_with_changes: list[tuple[str, Path, list[str]]] = [] for lib in libraries: lib_name = lib.get("name", "unnamed") @@ -197,7 +197,7 @@ def sync( # TODO: Should be in services or utils -def check_for_library_changes(lib_path: Path) -> List[str]: +def check_for_library_changes(lib_path: Path) -> list[str]: """ Check if git pull changes indicate new libraries that would require setup. Uses git diff to analyze what files were added/changed in the pull. @@ -282,7 +282,7 @@ def _is_template_change(path: str) -> bool: return path.startswith("templates/") and path.endswith("metadata.yaml") -def _check_current_library_state(lib_path: Path) -> List[str]: +def _check_current_library_state(lib_path: Path) -> list[str]: """ Fallback method to check current library state when git diff is not available. This is used when we can't determine what changed in the pull. diff --git a/kicad_lib_manager/commands/template/command.py b/kicad_lib_manager/commands/template/command.py index c3b137f..45015fe 100644 --- a/kicad_lib_manager/commands/template/command.py +++ b/kicad_lib_manager/commands/template/command.py @@ -9,7 +9,7 @@ import sys import traceback from pathlib import Path -from typing import Annotated, List, Optional +from typing import Annotated, Optional import jinja2 import pathspec @@ -63,7 +63,7 @@ def create( Optional[str], typer.Option(help="Name of the library containing the template") ] = None, set_var: Annotated[ - Optional[List[str]], + Optional[list[str]], typer.Option("--set-var", help="Set template variable in key=value format"), ] = None, dry_run: Annotated[ @@ -506,11 +506,11 @@ def make( ), ] = None, exclude: Annotated[ - Optional[List[str]], + Optional[list[str]], typer.Option(help="Additional patterns to exclude (gitignore format)"), ] = None, variable: Annotated[ - Optional[List[str]], + Optional[list[str]], typer.Option(help="Define a template variable in name=value format"), ] = None, extends: Annotated[ diff --git a/kicad_lib_manager/commands/unpin/command.py b/kicad_lib_manager/commands/unpin/command.py index 9af1fbb..040347e 100644 --- a/kicad_lib_manager/commands/unpin/command.py +++ b/kicad_lib_manager/commands/unpin/command.py @@ -3,7 +3,7 @@ """ import json -from typing import List, Optional +from typing import Optional import typer from rich.console import Console @@ -16,13 +16,13 @@ def unpin( - symbols: Optional[List[str]] = typer.Option( + symbols: Optional[list[str]] = typer.Option( None, "--symbols", "-s", help="Symbol libraries to unpin (can be specified multiple times)", ), - footprints: Optional[List[str]] = typer.Option( + footprints: Optional[list[str]] = typer.Option( None, "--footprints", "-f", diff --git a/kicad_lib_manager/interfaces/config_service.py b/kicad_lib_manager/interfaces/config_service.py index f00cfb1..6258620 100644 --- a/kicad_lib_manager/interfaces/config_service.py +++ b/kicad_lib_manager/interfaces/config_service.py @@ -4,7 +4,7 @@ from abc import abstractmethod from pathlib import Path -from typing import Dict, List, Optional, Protocol +from typing import Optional, Protocol class ConfigServiceProtocol(Protocol): @@ -15,11 +15,11 @@ def get_config_file_path(self) -> Path: """Get the path to the KiLM configuration file.""" @abstractmethod - def load_config(self) -> Dict: + def load_config(self) -> dict: """Load the KiLM configuration.""" @abstractmethod - def save_config(self, config: Dict) -> None: + def save_config(self, config: dict) -> None: """Save the KiLM configuration.""" @abstractmethod @@ -31,11 +31,11 @@ def remove_library(self, name: str) -> None: """Remove a library from the configuration.""" @abstractmethod - def get_libraries(self) -> List[Dict]: + def get_libraries(self) -> list[dict]: """Get all configured libraries.""" @abstractmethod - def get_library_by_name(self, name: str) -> Optional[Dict]: + def get_library_by_name(self, name: str) -> Optional[dict]: """Get a specific library by name.""" @abstractmethod diff --git a/kicad_lib_manager/interfaces/kicad_service.py b/kicad_lib_manager/interfaces/kicad_service.py index a7fcbee..556944e 100644 --- a/kicad_lib_manager/interfaces/kicad_service.py +++ b/kicad_lib_manager/interfaces/kicad_service.py @@ -4,7 +4,7 @@ from abc import abstractmethod from pathlib import Path -from typing import Dict, List, Optional, Protocol, Tuple +from typing import Optional, Protocol class KiCadServiceProtocol(Protocol): @@ -15,14 +15,14 @@ def find_kicad_config_dir(self) -> Path: """Find the KiCad configuration directory.""" @abstractmethod - def get_environment_variables(self, config_dir: Path) -> Dict[str, str]: + def get_environment_variables(self, config_dir: Path) -> dict[str, str]: """Get KiCad environment variables from configuration.""" @abstractmethod def set_environment_variables( self, config_dir: Path, - env_vars: Dict[str, str], + env_vars: dict[str, str], backup: bool = True, max_backups: int = 5, ) -> bool: @@ -31,7 +31,7 @@ def set_environment_variables( @abstractmethod def get_configured_libraries( self, config_dir: Path - ) -> Tuple[List[Dict], List[Dict]]: + ) -> tuple[list[dict], list[dict]]: """ Get configured symbol and footprint libraries. @@ -43,15 +43,15 @@ def get_configured_libraries( def add_libraries_to_kicad( self, config_dir: Path, - symbol_libs: Optional[List[Dict]] = None, - footprint_libs: Optional[List[Dict]] = None, + symbol_libs: Optional[list[dict]] = None, + footprint_libs: Optional[list[dict]] = None, backup: bool = True, max_backups: int = 5, ) -> bool: """Add libraries to KiCad library tables.""" @abstractmethod - def get_pinned_libraries(self, config_dir: Path) -> Tuple[List[str], List[str]]: + def get_pinned_libraries(self, config_dir: Path) -> tuple[list[str], list[str]]: """ Get pinned libraries from KiCad configuration. diff --git a/kicad_lib_manager/interfaces/library_service.py b/kicad_lib_manager/interfaces/library_service.py index f619982..ff04f07 100644 --- a/kicad_lib_manager/interfaces/library_service.py +++ b/kicad_lib_manager/interfaces/library_service.py @@ -4,14 +4,14 @@ from abc import abstractmethod from pathlib import Path -from typing import Dict, List, Optional, Protocol, Tuple, Union +from typing import Optional, Protocol, Union class LibraryServiceProtocol(Protocol): """Protocol for library management services.""" @abstractmethod - def list_libraries(self, directory: Path) -> Tuple[List[str], List[str]]: + def list_libraries(self, directory: Path) -> tuple[list[str], list[str]]: """ List symbol and footprint libraries in a directory. @@ -29,22 +29,22 @@ def initialize_library( env_var: Optional[str] = None, force: bool = False, no_env_var: bool = False, - ) -> Dict[str, Union[str, bool, Dict[str, bool]]]: + ) -> dict[str, Union[str, bool, dict[str, bool]]]: """Initialize a library in the given directory.""" ... @abstractmethod def get_library_metadata( self, directory: Path - ) -> Optional[Dict[str, Union[str, bool, Dict[str, bool]]]]: + ) -> Optional[dict[str, Union[str, bool, dict[str, bool]]]]: """Get metadata for a library directory.""" ... @abstractmethod def pin_libraries( self, - symbol_libs: List[str], - footprint_libs: List[str], + symbol_libs: list[str], + footprint_libs: list[str], kicad_config_dir: Path, dry_run: bool = False, max_backups: int = 5, @@ -60,8 +60,8 @@ def pin_libraries( @abstractmethod def unpin_libraries( self, - symbol_libs: List[str], - footprint_libs: List[str], + symbol_libs: list[str], + footprint_libs: list[str], kicad_config_dir: Path, dry_run: bool = False, max_backups: int = 5, diff --git a/kicad_lib_manager/services/config_service.py b/kicad_lib_manager/services/config_service.py index 49b8e53..0b829e0 100644 --- a/kicad_lib_manager/services/config_service.py +++ b/kicad_lib_manager/services/config_service.py @@ -4,7 +4,7 @@ import time from pathlib import Path -from typing import Dict, List, Optional, Tuple, TypedDict, Union, cast +from typing import Optional, TypedDict, Union, cast import click import yaml @@ -25,9 +25,9 @@ class LibraryDict(TypedDict): type: str -ConfigValue = Union[str, int, List[LibraryDict]] +ConfigValue = Union[str, int, list[LibraryDict]] -DEFAULT_CONFIG: Dict[str, ConfigValue] = { +DEFAULT_CONFIG: dict[str, ConfigValue] = { "max_backups": DEFAULT_MAX_BACKUPS, "libraries": DEFAULT_LIBRARIES, "update_check": True, @@ -138,7 +138,7 @@ def remove_library(self, name: str, library_type: Optional[str] = None) -> bool: return removed - def get_libraries(self, library_type: Optional[str] = None) -> List[LibraryDict]: + def get_libraries(self, library_type: Optional[str] = None) -> list[LibraryDict]: """ Get libraries from configuration @@ -176,7 +176,7 @@ def get_library_path( return None - def get_current_library_paths(self) -> Tuple[Optional[str], Optional[str]]: + def get_current_library_paths(self) -> tuple[Optional[str], Optional[str]]: """ Get paths for the current active libraries @@ -276,7 +276,7 @@ def _normalize_libraries_field(self) -> None: return # Validate and clean up each library entry - normalized_libraries: List[LibraryDict] = [] + normalized_libraries: list[LibraryDict] = [] for lib in libraries: validated_lib = _validate_library_entry(lib) if validated_lib is not None: @@ -286,7 +286,7 @@ def _normalize_libraries_field(self) -> None: self._config["libraries"] = normalized_libraries - def _get_normalized_libraries(self) -> List[LibraryDict]: + def _get_normalized_libraries(self) -> list[LibraryDict]: """ Get libraries ensuring they are properly normalized. @@ -305,7 +305,7 @@ def _get_normalized_libraries(self) -> List[LibraryDict]: return [] # Validate and normalize each library entry - normalized_libraries: List[LibraryDict] = [] + normalized_libraries: list[LibraryDict] = [] needs_save = False for lib in libraries_raw: @@ -365,7 +365,7 @@ def mark_update_check_performed(self) -> None: last_check_file = cache_dir / "last_update_check" last_check_file.write_text(str(time.time())) - def get_update_preferences(self) -> Dict[str, Union[bool, str]]: + def get_update_preferences(self) -> dict[str, Union[bool, str]]: """ Get update-related preferences. @@ -452,7 +452,7 @@ def _make_library_dict(name: str, path: str, type_: str) -> LibraryDict: def _validate_library_entry( - lib: Union[Dict[str, str], LibraryDict], + lib: Union[dict[str, str], LibraryDict], ) -> Optional[LibraryDict]: """Validate and normalize a library entry.""" if isinstance(lib, dict) and all(key in lib for key in ["name", "path", "type"]): @@ -475,11 +475,11 @@ def get_config_file_path(self) -> Path: """Get the path to the KiLM configuration file.""" return self._config._get_config_file() - def load_config(self) -> Dict: + def load_config(self) -> dict: """Load the KiLM configuration.""" return self._config._config - def save_config(self, config: Dict) -> None: + def save_config(self, config: dict) -> None: """Save the KiLM configuration.""" self._config._config = config self._config.save() @@ -492,7 +492,7 @@ def remove_library(self, name: str) -> None: """Remove a library from the configuration.""" self._config.remove_library(name) - def get_libraries(self) -> List[LibraryDict]: + def get_libraries(self) -> list[LibraryDict]: """Get all configured libraries.""" return self._config.get_libraries() diff --git a/kicad_lib_manager/services/kicad_service.py b/kicad_lib_manager/services/kicad_service.py index 16ccf60..4295491 100644 --- a/kicad_lib_manager/services/kicad_service.py +++ b/kicad_lib_manager/services/kicad_service.py @@ -4,7 +4,7 @@ import json from pathlib import Path -from typing import Dict, List, Optional, Tuple +from typing import Optional from ..utils.file_ops import list_configured_libraries from .library_service import LibraryService @@ -17,7 +17,7 @@ class KiCadService: def find_kicad_config_dir() -> Path: return LibraryService.find_kicad_config() - def get_environment_variables(self, config_dir: Path) -> Dict[str, str]: + def get_environment_variables(self, config_dir: Path) -> dict[str, str]: """Get KiCad environment variables from configuration.""" kicad_common = config_dir / "kicad_common.json" @@ -39,7 +39,7 @@ def get_environment_variables(self, config_dir: Path) -> Dict[str, str]: def set_environment_variables( self, config_dir: Path, - env_vars: Dict[str, str], + env_vars: dict[str, str], backup: bool = True, max_backups: int = 5, ) -> bool: @@ -51,15 +51,15 @@ def set_environment_variables( def get_configured_libraries( self, config_dir: Path - ) -> Tuple[List[Dict], List[Dict]]: + ) -> tuple[list[dict], list[dict]]: """Get configured symbol and footprint libraries.""" return list_configured_libraries(config_dir) def add_libraries_to_kicad( self, config_dir: Path, - symbol_libs: Optional[List[Dict]] = None, - footprint_libs: Optional[List[Dict]] = None, + symbol_libs: Optional[list[dict]] = None, + footprint_libs: Optional[list[dict]] = None, backup: bool = True, max_backups: int = 5, ) -> bool: @@ -77,7 +77,7 @@ def add_libraries_to_kicad( _ = added_libs # Suppress unused warning return changes_needed - def get_pinned_libraries(self, config_dir: Path) -> Tuple[List[str], List[str]]: + def get_pinned_libraries(self, config_dir: Path) -> tuple[list[str], list[str]]: """Get pinned libraries from KiCad configuration.""" kicad_common = config_dir / "kicad_common.json" diff --git a/kicad_lib_manager/services/library_service.py b/kicad_lib_manager/services/library_service.py index 9fe4905..47bdeda 100644 --- a/kicad_lib_manager/services/library_service.py +++ b/kicad_lib_manager/services/library_service.py @@ -6,7 +6,7 @@ import os import platform from pathlib import Path -from typing import Dict, List, Optional, Set, Tuple +from typing import Optional import yaml @@ -27,7 +27,7 @@ class LibraryService: """Service for managing KiCad libraries.""" - def list_libraries(self, directory: Path) -> Tuple[List[str], List[str]]: + def list_libraries(self, directory: Path) -> tuple[list[str], list[str]]: """List symbol and footprint libraries in a directory.""" return list_libraries(str(directory)) @@ -39,7 +39,7 @@ def initialize_library( env_var: Optional[str] = None, force: bool = False, no_env_var: bool = False, - ) -> Dict: + ) -> dict: """Initialize a library in the given directory.""" # Check for existing metadata metadata = read_github_metadata(directory) @@ -81,7 +81,7 @@ def initialize_library( self._create_library_structure(directory) # Update capabilities - capabilities: Dict[str, bool] = { + capabilities: dict[str, bool] = { "symbols": (directory / "symbols").exists(), "footprints": (directory / "footprints").exists(), "templates": (directory / "templates").exists(), @@ -91,14 +91,14 @@ def initialize_library( return metadata - def get_library_metadata(self, directory: Path) -> Optional[Dict]: + def get_library_metadata(self, directory: Path) -> Optional[dict]: """Get metadata for a library directory.""" return read_github_metadata(directory) def pin_libraries( self, - symbol_libs: List[str], - footprint_libs: List[str], + symbol_libs: list[str], + footprint_libs: list[str], kicad_config_dir: Path, dry_run: bool = False, max_backups: int = 5, @@ -114,8 +114,8 @@ def pin_libraries( def unpin_libraries( self, - symbol_libs: List[str], - footprint_libs: List[str], + symbol_libs: list[str], + footprint_libs: list[str], kicad_config_dir: Path, dry_run: bool = False, max_backups: int = 5, @@ -127,7 +127,7 @@ def unpin_libraries( _ = symbol_libs, footprint_libs, kicad_config_dir, dry_run, max_backups return False - def _create_library_structure(self, directory: Path) -> Tuple[List[str], List[str]]: + def _create_library_structure(self, directory: Path) -> tuple[list[str], list[str]]: """Create the required directory structure for a library.""" required_folders = ["symbols", "footprints", "templates"] existing_folders = [] @@ -148,9 +148,9 @@ def add_libraries( kicad_lib_dir: str, kicad_config: Path, kicad_3d_dir: Optional[str] = None, - additional_3d_dirs: Optional[Dict[str, str]] = None, + additional_3d_dirs: Optional[dict[str, str]] = None, dry_run: bool = False, - ) -> Tuple[Set[str], bool]: + ) -> tuple[set[str], bool]: """ Add KiCad libraries to the configuration. @@ -474,7 +474,7 @@ def is_absolute_path(path: str) -> bool: return f"{base_path}/footprints/{lib_name}.pretty" @staticmethod - def add_entries_to_table(table_path: Path, entries: List[Dict[str, str]]) -> None: + def add_entries_to_table(table_path: Path, entries: list[dict[str, str]]) -> None: """ Add entries to a KiCad library table file diff --git a/kicad_lib_manager/services/update_service.py b/kicad_lib_manager/services/update_service.py index cbfe41e..7378120 100644 --- a/kicad_lib_manager/services/update_service.py +++ b/kicad_lib_manager/services/update_service.py @@ -9,7 +9,7 @@ import sys import time from pathlib import Path -from typing import Dict, Optional, Tuple +from typing import Optional import requests from packaging.version import InvalidVersion, Version @@ -101,7 +101,7 @@ def check_latest_version(self) -> Optional[str]: return None - def _load_cache(self) -> Optional[Dict]: + def _load_cache(self) -> Optional[dict]: """Load cached version data.""" if self.cache_file.exists(): try: @@ -114,7 +114,7 @@ def _load_cache(self) -> Optional[Dict]: pass return None - def _save_cache(self, data: Dict): + def _save_cache(self, data: dict): """Save version data to cache.""" self.cache_file.parent.mkdir(parents=True, exist_ok=True) with Path(self.cache_file).open("w") as f: @@ -198,7 +198,7 @@ def can_auto_update(self) -> bool: """Check if automatic update is possible for this installation method.""" return self.installation_method in ["pipx", "pip", "pip-venv", "uv"] - def perform_update(self) -> Tuple[bool, str]: + def perform_update(self) -> tuple[bool, str]: """ Execute update using detected installation method. Returns: (success: bool, message: str) @@ -256,6 +256,6 @@ def can_auto_update(self) -> bool: """Check if automatic updates are supported.""" return self.manager.can_auto_update() - def perform_update(self) -> Tuple[bool, str]: + def perform_update(self) -> tuple[bool, str]: """Perform the update.""" return self.manager.perform_update() diff --git a/kicad_lib_manager/utils/env_vars.py b/kicad_lib_manager/utils/env_vars.py index 32467c1..a68620e 100644 --- a/kicad_lib_manager/utils/env_vars.py +++ b/kicad_lib_manager/utils/env_vars.py @@ -8,7 +8,7 @@ import shutil import subprocess from pathlib import Path -from typing import List, Optional +from typing import Optional # Import Config here, but only use it when needed to avoid circular imports try: @@ -230,8 +230,8 @@ def update_kicad_env_vars( def update_pinned_libraries( kicad_config: Path, - symbol_libs: Optional[List[str]] = None, - footprint_libs: Optional[List[str]] = None, + symbol_libs: Optional[list[str]] = None, + footprint_libs: Optional[list[str]] = None, dry_run: bool = False, max_backups: int = 5, ) -> bool: diff --git a/kicad_lib_manager/utils/file_ops.py b/kicad_lib_manager/utils/file_ops.py index 4e93976..f36eee6 100644 --- a/kicad_lib_manager/utils/file_ops.py +++ b/kicad_lib_manager/utils/file_ops.py @@ -4,11 +4,11 @@ import re from pathlib import Path -from typing import List, Optional, Tuple +from typing import Optional def read_file_with_encoding( - file_path: Path, encodings: Optional[List[str]] = None + file_path: Path, encodings: Optional[list[str]] = None ) -> str: """ Read a file trying multiple encodings until successful @@ -190,7 +190,7 @@ def add_footprint_lib( ) -def list_libraries(kicad_lib_dir: str) -> Tuple[List[str], List[str]]: +def list_libraries(kicad_lib_dir: str) -> tuple[list[str], list[str]]: """ List all available libraries in the repository @@ -224,7 +224,7 @@ def list_libraries(kicad_lib_dir: str) -> Tuple[List[str], List[str]]: return symbols, footprints -def list_configured_libraries(kicad_config: Path) -> Tuple[List[dict], List[dict]]: +def list_configured_libraries(kicad_config: Path) -> tuple[list[dict], list[dict]]: """ List all libraries currently configured in KiCad diff --git a/kicad_lib_manager/utils/metadata.py b/kicad_lib_manager/utils/metadata.py index c922625..4c9b401 100644 --- a/kicad_lib_manager/utils/metadata.py +++ b/kicad_lib_manager/utils/metadata.py @@ -5,7 +5,7 @@ import json import re from pathlib import Path -from typing import Any, Dict, Optional, Union +from typing import Any, Optional, Union import yaml @@ -14,7 +14,7 @@ def read_github_metadata( directory: Path, -) -> Optional[Dict[str, Any]]: +) -> Optional[dict[str, Any]]: """ Read metadata from a GitHub library directory. @@ -41,7 +41,7 @@ def read_github_metadata( return None -def write_github_metadata(directory: Path, metadata: Dict[str, Any]) -> bool: +def write_github_metadata(directory: Path, metadata: dict[str, Any]) -> bool: """ Write metadata to a GitHub library directory. @@ -63,7 +63,7 @@ def write_github_metadata(directory: Path, metadata: Dict[str, Any]) -> bool: return False -def read_cloud_metadata(directory: Path) -> Optional[Dict[str, Union[str, int, None]]]: +def read_cloud_metadata(directory: Path) -> Optional[dict[str, Union[str, int, None]]]: """ Read metadata from a cloud 3D model directory. @@ -91,7 +91,7 @@ def read_cloud_metadata(directory: Path) -> Optional[Dict[str, Union[str, int, N def write_cloud_metadata( - directory: Path, metadata: Dict[str, Union[str, int, None]] + directory: Path, metadata: dict[str, Union[str, int, None]] ) -> bool: """ Write metadata to a cloud 3D model directory. @@ -145,7 +145,7 @@ def generate_env_var_name(name: str, prefix: str = "") -> str: def get_default_github_metadata( directory: Path, -) -> Dict[str, Any]: +) -> dict[str, Any]: """ Generate default metadata for a GitHub library. @@ -182,7 +182,7 @@ def get_default_github_metadata( } -def get_default_cloud_metadata(directory: Path) -> Dict[str, Union[str, int, None]]: +def get_default_cloud_metadata(directory: Path) -> dict[str, Union[str, int, None]]: """ Generate default metadata for a cloud 3D model directory. diff --git a/kicad_lib_manager/utils/template.py b/kicad_lib_manager/utils/template.py index d6b98ca..e0a307c 100644 --- a/kicad_lib_manager/utils/template.py +++ b/kicad_lib_manager/utils/template.py @@ -9,8 +9,9 @@ import re import shutil import traceback +from collections.abc import Mapping from pathlib import Path -from typing import Any, Dict, List, Mapping, Optional, TypedDict, Union, cast +from typing import Any, Optional, TypedDict, Union, cast import click import jinja2 @@ -59,7 +60,7 @@ class TemplateVariable(TypedDict): class TemplateDependencies(TypedDict): """Template dependencies definition.""" - recommended: List[str] + recommended: list[str] class TemplateMetadata(TypedDict, total=False): @@ -69,7 +70,7 @@ class TemplateMetadata(TypedDict, total=False): description: str use_case: str version: str - variables: Dict[str, TemplateVariable] + variables: dict[str, TemplateVariable] extends: str dependencies: TemplateDependencies path: str @@ -123,7 +124,7 @@ def get_gitignore_spec(directory: Path) -> Optional[pathspec.PathSpec]: return None -def list_templates_in_directory(directory: Path) -> List[TemplateMetadata]: +def list_templates_in_directory(directory: Path) -> list[TemplateMetadata]: """ List all templates in a given directory. @@ -137,7 +138,7 @@ def list_templates_in_directory(directory: Path) -> List[TemplateMetadata]: if not templates_dir.exists() or not templates_dir.is_dir(): return [] - templates: List[TemplateMetadata] = [] + templates: list[TemplateMetadata] = [] for template_dir in templates_dir.iterdir(): if not template_dir.is_dir(): @@ -169,8 +170,8 @@ def list_templates_in_directory(directory: Path) -> List[TemplateMetadata]: def find_potential_variables( - directory: Path, patterns: Optional[List[str]] = None -) -> Dict[str, List[str]]: + directory: Path, patterns: Optional[list[str]] = None +) -> dict[str, list[str]]: """ Scan files in a directory for potential template variables. @@ -238,9 +239,9 @@ def create_template_metadata( name: str, description: Optional[str] = None, use_case: Optional[str] = None, - variables: Optional[Dict[str, TemplateVariable]] = None, + variables: Optional[dict[str, TemplateVariable]] = None, extends: Optional[str] = None, - dependencies: Optional[List[str]] = None, + dependencies: Optional[list[str]] = None, ) -> TemplateMetadata: """ Create template metadata dictionary. @@ -327,7 +328,7 @@ def write_template_metadata(directory: Path, metadata: TemplateMetadata) -> None def process_markdown_file( - source_file: Path, target_file: Path, variables: Dict[str, TemplateVariable] + source_file: Path, target_file: Path, variables: dict[str, TemplateVariable] ) -> None: """ Process a Markdown file to add a template header with available variables. @@ -377,7 +378,7 @@ def create_template_structure( template_directory: Path, metadata: TemplateMetadata, gitignore_spec: Optional[pathspec.PathSpec] = None, - additional_excludes: Optional[List[str]] = None, + additional_excludes: Optional[list[str]] = None, ) -> None: """ Create template structure from source directory. @@ -666,7 +667,7 @@ def post_create(context): def process_kicad_project_file( - source_file: Path, target_file: Path, variables: Dict[str, TemplateVariable] + source_file: Path, target_file: Path, variables: dict[str, TemplateVariable] ) -> None: """ Process a KiCad project file (.kicad_pro). @@ -858,7 +859,7 @@ def render_filename_custom( Rendered filename """ - def transform_value(value: str, transformations: List[str]) -> str: + def transform_value(value: str, transformations: list[str]) -> str: """Apply a chain of transformations to a value.""" result = value @@ -965,7 +966,7 @@ def render_filename( return filename -def find_all_templates(config: Any) -> Dict[str, TemplateMetadata]: +def find_all_templates(config: Any) -> dict[str, TemplateMetadata]: """ Find all templates in all configured libraries. @@ -1093,7 +1094,7 @@ def create_project_from_template( template_dir: Path, project_dir: Path, variables: Mapping[str, Union[str, int, bool]], - metadata: Optional[Dict[str, Any]] = None, + metadata: Optional[dict[str, Any]] = None, dry_run: bool = False, skip_hooks: bool = False, ) -> bool: @@ -1270,7 +1271,7 @@ def run_post_create_hook( hook_script: Path, project_dir: Path, variables: Mapping[str, Union[str, int, bool]], - template_metadata: Dict[str, Any], + template_metadata: dict[str, Any], ) -> None: """ Run a post-creation hook script. diff --git a/tests/test_config_commands.py b/tests/test_config_commands.py index 1d02aa0..f76d34d 100644 --- a/tests/test_config_commands.py +++ b/tests/test_config_commands.py @@ -2,8 +2,6 @@ Tests for KiCad Library Manager config commands. """ -from typing import List - import pytest from typer.testing import CliRunner @@ -11,7 +9,7 @@ from kicad_lib_manager.services.config_service import Config, LibraryDict # Sample test data -TEST_LIBRARIES: List[LibraryDict] = [ +TEST_LIBRARIES: list[LibraryDict] = [ LibraryDict(name="test-github-lib", path="/path/to/github/library", type="github"), LibraryDict(name="test-cloud-lib", path="/path/to/cloud/library", type="cloud"), ] diff --git a/tests/test_sync_command.py b/tests/test_sync_command.py index 3ae5b82..1fd952e 100644 --- a/tests/test_sync_command.py +++ b/tests/test_sync_command.py @@ -237,9 +237,11 @@ def test_check_for_library_changes_fallback(): mock_run.return_value = result # Mock file existence with a patch for fallback behavior - with patch.object(Path, "exists", return_value=True), patch.object( - Path, "is_dir", return_value=True - ), patch.object(Path, "glob") as mock_glob: + with ( + patch.object(Path, "exists", return_value=True), + patch.object(Path, "is_dir", return_value=True), + patch.object(Path, "glob") as mock_glob, + ): # Setup mock glob to return symbol files def mock_glob_func(pattern): if "**/*.kicad_sym" in pattern: diff --git a/uv.lock b/uv.lock index 3f373ee..1347708 100644 --- a/uv.lock +++ b/uv.lock @@ -1,72 +1,24 @@ version = 1 revision = 3 -requires-python = ">=3.8" +requires-python = ">=3.9" resolution-markers = [ "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] - -[[package]] -name = "black" -version = "24.8.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "mypy-extensions", marker = "python_full_version < '3.9'" }, - { name = "packaging", marker = "python_full_version < '3.9'" }, - { name = "pathspec", marker = "python_full_version < '3.9'" }, - { name = "platformdirs", version = "4.3.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/04/b0/46fb0d4e00372f4a86a6f8efa3cb193c9f64863615e39010b1477e010578/black-24.8.0.tar.gz", hash = "sha256:2500945420b6784c38b9ee885af039f5e7471ef284ab03fa35ecdde4688cd83f", size = 644810, upload-time = "2024-08-02T17:43:18.405Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/47/6e/74e29edf1fba3887ed7066930a87f698ffdcd52c5dbc263eabb06061672d/black-24.8.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:09cdeb74d494ec023ded657f7092ba518e8cf78fa8386155e4a03fdcc44679e6", size = 1632092, upload-time = "2024-08-02T17:47:26.911Z" }, - { url = "https://files.pythonhosted.org/packages/ab/49/575cb6c3faee690b05c9d11ee2e8dba8fbd6d6c134496e644c1feb1b47da/black-24.8.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:81c6742da39f33b08e791da38410f32e27d632260e599df7245cccee2064afeb", size = 1457529, upload-time = "2024-08-02T17:47:29.109Z" }, - { url = "https://files.pythonhosted.org/packages/7a/b4/d34099e95c437b53d01c4aa37cf93944b233066eb034ccf7897fa4e5f286/black-24.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:707a1ca89221bc8a1a64fb5e15ef39cd755633daa672a9db7498d1c19de66a42", size = 1757443, upload-time = "2024-08-02T17:46:20.306Z" }, - { url = "https://files.pythonhosted.org/packages/87/a0/6d2e4175ef364b8c4b64f8441ba041ed65c63ea1db2720d61494ac711c15/black-24.8.0-cp310-cp310-win_amd64.whl", hash = "sha256:d6417535d99c37cee4091a2f24eb2b6d5ec42b144d50f1f2e436d9fe1916fe1a", size = 1418012, upload-time = "2024-08-02T17:47:20.33Z" }, - { url = "https://files.pythonhosted.org/packages/08/a6/0a3aa89de9c283556146dc6dbda20cd63a9c94160a6fbdebaf0918e4a3e1/black-24.8.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:fb6e2c0b86bbd43dee042e48059c9ad7830abd5c94b0bc518c0eeec57c3eddc1", size = 1615080, upload-time = "2024-08-02T17:48:05.467Z" }, - { url = "https://files.pythonhosted.org/packages/db/94/b803d810e14588bb297e565821a947c108390a079e21dbdcb9ab6956cd7a/black-24.8.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:837fd281f1908d0076844bc2b801ad2d369c78c45cf800cad7b61686051041af", size = 1438143, upload-time = "2024-08-02T17:47:30.247Z" }, - { url = "https://files.pythonhosted.org/packages/a5/b5/f485e1bbe31f768e2e5210f52ea3f432256201289fd1a3c0afda693776b0/black-24.8.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:62e8730977f0b77998029da7971fa896ceefa2c4c4933fcd593fa599ecbf97a4", size = 1738774, upload-time = "2024-08-02T17:46:17.837Z" }, - { url = "https://files.pythonhosted.org/packages/a8/69/a000fc3736f89d1bdc7f4a879f8aaf516fb03613bb51a0154070383d95d9/black-24.8.0-cp311-cp311-win_amd64.whl", hash = "sha256:72901b4913cbac8972ad911dc4098d5753704d1f3c56e44ae8dce99eecb0e3af", size = 1427503, upload-time = "2024-08-02T17:46:22.654Z" }, - { url = "https://files.pythonhosted.org/packages/a2/a8/05fb14195cfef32b7c8d4585a44b7499c2a4b205e1662c427b941ed87054/black-24.8.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:7c046c1d1eeb7aea9335da62472481d3bbf3fd986e093cffd35f4385c94ae368", size = 1646132, upload-time = "2024-08-02T17:49:52.843Z" }, - { url = "https://files.pythonhosted.org/packages/41/77/8d9ce42673e5cb9988f6df73c1c5c1d4e9e788053cccd7f5fb14ef100982/black-24.8.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:649f6d84ccbae73ab767e206772cc2d7a393a001070a4c814a546afd0d423aed", size = 1448665, upload-time = "2024-08-02T17:47:54.479Z" }, - { url = "https://files.pythonhosted.org/packages/cc/94/eff1ddad2ce1d3cc26c162b3693043c6b6b575f538f602f26fe846dfdc75/black-24.8.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2b59b250fdba5f9a9cd9d0ece6e6d993d91ce877d121d161e4698af3eb9c1018", size = 1762458, upload-time = "2024-08-02T17:46:19.384Z" }, - { url = "https://files.pythonhosted.org/packages/28/ea/18b8d86a9ca19a6942e4e16759b2fa5fc02bbc0eb33c1b866fcd387640ab/black-24.8.0-cp312-cp312-win_amd64.whl", hash = "sha256:6e55d30d44bed36593c3163b9bc63bf58b3b30e4611e4d88a0c3c239930ed5b2", size = 1436109, upload-time = "2024-08-02T17:46:52.97Z" }, - { url = "https://files.pythonhosted.org/packages/9f/d4/ae03761ddecc1a37d7e743b89cccbcf3317479ff4b88cfd8818079f890d0/black-24.8.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:505289f17ceda596658ae81b61ebbe2d9b25aa78067035184ed0a9d855d18afd", size = 1617322, upload-time = "2024-08-02T17:51:20.203Z" }, - { url = "https://files.pythonhosted.org/packages/14/4b/4dfe67eed7f9b1ddca2ec8e4418ea74f0d1dc84d36ea874d618ffa1af7d4/black-24.8.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b19c9ad992c7883ad84c9b22aaa73562a16b819c1d8db7a1a1a49fb7ec13c7d2", size = 1442108, upload-time = "2024-08-02T17:50:40.824Z" }, - { url = "https://files.pythonhosted.org/packages/97/14/95b3f91f857034686cae0e73006b8391d76a8142d339b42970eaaf0416ea/black-24.8.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f13f7f386f86f8121d76599114bb8c17b69d962137fc70efe56137727c7047e", size = 1745786, upload-time = "2024-08-02T17:46:02.939Z" }, - { url = "https://files.pythonhosted.org/packages/95/54/68b8883c8aa258a6dde958cd5bdfada8382bec47c5162f4a01e66d839af1/black-24.8.0-cp38-cp38-win_amd64.whl", hash = "sha256:f490dbd59680d809ca31efdae20e634f3fae27fba3ce0ba3208333b713bc3920", size = 1426754, upload-time = "2024-08-02T17:46:38.603Z" }, - { url = "https://files.pythonhosted.org/packages/13/b2/b3f24fdbb46f0e7ef6238e131f13572ee8279b70f237f221dd168a9dba1a/black-24.8.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:eab4dd44ce80dea27dc69db40dab62d4ca96112f87996bca68cd75639aeb2e4c", size = 1631706, upload-time = "2024-08-02T17:49:57.606Z" }, - { url = "https://files.pythonhosted.org/packages/d9/35/31010981e4a05202a84a3116423970fd1a59d2eda4ac0b3570fbb7029ddc/black-24.8.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3c4285573d4897a7610054af5a890bde7c65cb466040c5f0c8b732812d7f0e5e", size = 1457429, upload-time = "2024-08-02T17:49:12.764Z" }, - { url = "https://files.pythonhosted.org/packages/27/25/3f706b4f044dd569a20a4835c3b733dedea38d83d2ee0beb8178a6d44945/black-24.8.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e84e33b37be070ba135176c123ae52a51f82306def9f7d063ee302ecab2cf47", size = 1756488, upload-time = "2024-08-02T17:46:08.067Z" }, - { url = "https://files.pythonhosted.org/packages/63/72/79375cd8277cbf1c5670914e6bd4c1b15dea2c8f8e906dc21c448d0535f0/black-24.8.0-cp39-cp39-win_amd64.whl", hash = "sha256:73bbf84ed136e45d451a260c6b73ed674652f90a2b3211d6a35e78054563a9bb", size = 1417721, upload-time = "2024-08-02T17:46:42.637Z" }, - { url = "https://files.pythonhosted.org/packages/27/1e/83fa8a787180e1632c3d831f7e58994d7aaf23a0961320d21e84f922f919/black-24.8.0-py3-none-any.whl", hash = "sha256:972085c618ee94f402da1af548a4f218c754ea7e5dc70acb168bfaca4c2542ed", size = 206504, upload-time = "2024-08-02T17:43:15.747Z" }, + "python_full_version < '3.10'", ] [[package]] name = "black" version = "25.1.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] dependencies = [ - { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" }, + { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, - { name = "mypy-extensions", marker = "python_full_version >= '3.9'" }, - { name = "packaging", marker = "python_full_version >= '3.9'" }, - { name = "pathspec", marker = "python_full_version >= '3.9'" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "mypy-extensions" }, + { name = "packaging" }, + { name = "pathspec" }, + { name = "platformdirs" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/94/49/26a7b0f3f35da4b5a65f081943b7bcd22d7002f5f0fb8098ec1ff21cb6ef/black-25.1.0.tar.gz", hash = "sha256:33496d5cd1222ad73391352b4ae8da15253c5de89b93a80b3e2c8d9a19ec2666", size = 649449, upload-time = "2025-01-29T04:15:40.373Z" } wheels = [ @@ -172,17 +124,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/72/2a/aff5dd112b2f14bcc3462c312dce5445806bfc8ab3a7328555da95330e4b/charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16", size = 152224, upload-time = "2025-08-09T07:56:51.369Z" }, { url = "https://files.pythonhosted.org/packages/b7/8c/9839225320046ed279c6e839d51f028342eb77c91c89b8ef2549f951f3ec/charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce", size = 100086, upload-time = "2025-08-09T07:56:52.722Z" }, { url = "https://files.pythonhosted.org/packages/ee/7a/36fbcf646e41f710ce0a563c1c9a343c6edf9be80786edeb15b6f62e17db/charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c", size = 107400, upload-time = "2025-08-09T07:56:55.172Z" }, - { url = "https://files.pythonhosted.org/packages/22/82/63a45bfc36f73efe46731a3a71cb84e2112f7e0b049507025ce477f0f052/charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c", size = 198805, upload-time = "2025-08-09T07:56:56.496Z" }, - { url = "https://files.pythonhosted.org/packages/0c/52/8b0c6c3e53f7e546a5e49b9edb876f379725914e1130297f3b423c7b71c5/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b", size = 142862, upload-time = "2025-08-09T07:56:57.751Z" }, - { url = "https://files.pythonhosted.org/packages/59/c0/a74f3bd167d311365e7973990243f32c35e7a94e45103125275b9e6c479f/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4", size = 155104, upload-time = "2025-08-09T07:56:58.984Z" }, - { url = "https://files.pythonhosted.org/packages/1a/79/ae516e678d6e32df2e7e740a7be51dc80b700e2697cb70054a0f1ac2c955/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b", size = 152598, upload-time = "2025-08-09T07:57:00.201Z" }, - { url = "https://files.pythonhosted.org/packages/00/bd/ef9c88464b126fa176f4ef4a317ad9b6f4d30b2cffbc43386062367c3e2c/charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9", size = 147391, upload-time = "2025-08-09T07:57:01.441Z" }, - { url = "https://files.pythonhosted.org/packages/7a/03/cbb6fac9d3e57f7e07ce062712ee80d80a5ab46614684078461917426279/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb", size = 145037, upload-time = "2025-08-09T07:57:02.638Z" }, - { url = "https://files.pythonhosted.org/packages/64/d1/f9d141c893ef5d4243bc75c130e95af8fd4bc355beff06e9b1e941daad6e/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a", size = 156425, upload-time = "2025-08-09T07:57:03.898Z" }, - { url = "https://files.pythonhosted.org/packages/c5/35/9c99739250742375167bc1b1319cd1cec2bf67438a70d84b2e1ec4c9daa3/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942", size = 153734, upload-time = "2025-08-09T07:57:05.549Z" }, - { url = "https://files.pythonhosted.org/packages/50/10/c117806094d2c956ba88958dab680574019abc0c02bcf57b32287afca544/charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b", size = 148551, upload-time = "2025-08-09T07:57:06.823Z" }, - { url = "https://files.pythonhosted.org/packages/61/c5/dc3ba772489c453621ffc27e8978a98fe7e41a93e787e5e5bde797f1dddb/charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557", size = 98459, upload-time = "2025-08-09T07:57:08.031Z" }, - { url = "https://files.pythonhosted.org/packages/05/35/bb59b1cd012d7196fc81c2f5879113971efc226a63812c9cf7f89fe97c40/charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40", size = 105887, upload-time = "2025-08-09T07:57:09.401Z" }, { url = "https://files.pythonhosted.org/packages/c2/ca/9a0983dd5c8e9733565cf3db4df2b0a2e9a82659fd8aa2a868ac6e4a991f/charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05", size = 207520, upload-time = "2025-08-09T07:57:11.026Z" }, { url = "https://files.pythonhosted.org/packages/39/c6/99271dc37243a4f925b09090493fb96c9333d7992c6187f5cfe5312008d2/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e", size = 147307, upload-time = "2025-08-09T07:57:12.4Z" }, { url = "https://files.pythonhosted.org/packages/e4/69/132eab043356bba06eb333cc2cc60c6340857d0a2e4ca6dc2b51312886b3/charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99", size = 160448, upload-time = "2025-08-09T07:57:13.712Z" }, @@ -202,9 +143,7 @@ name = "click" version = "8.1.8" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.9.*'", - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", + "python_full_version < '3.10'", ] dependencies = [ { name = "colorama", marker = "python_full_version < '3.10' and sys_platform == 'win32'" }, @@ -238,102 +177,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] -[[package]] -name = "coverage" -version = "7.6.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f7/08/7e37f82e4d1aead42a7443ff06a1e406aabf7302c4f00a546e4b320b994c/coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d", size = 798791, upload-time = "2024-08-04T19:45:30.9Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7e/61/eb7ce5ed62bacf21beca4937a90fe32545c91a3c8a42a30c6616d48fc70d/coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16", size = 206690, upload-time = "2024-08-04T19:43:07.695Z" }, - { url = "https://files.pythonhosted.org/packages/7d/73/041928e434442bd3afde5584bdc3f932fb4562b1597629f537387cec6f3d/coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36", size = 207127, upload-time = "2024-08-04T19:43:10.15Z" }, - { url = "https://files.pythonhosted.org/packages/c7/c8/6ca52b5147828e45ad0242388477fdb90df2c6cbb9a441701a12b3c71bc8/coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02", size = 235654, upload-time = "2024-08-04T19:43:12.405Z" }, - { url = "https://files.pythonhosted.org/packages/d5/da/9ac2b62557f4340270942011d6efeab9833648380109e897d48ab7c1035d/coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc", size = 233598, upload-time = "2024-08-04T19:43:14.078Z" }, - { url = "https://files.pythonhosted.org/packages/53/23/9e2c114d0178abc42b6d8d5281f651a8e6519abfa0ef460a00a91f80879d/coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23", size = 234732, upload-time = "2024-08-04T19:43:16.632Z" }, - { url = "https://files.pythonhosted.org/packages/0f/7e/a0230756fb133343a52716e8b855045f13342b70e48e8ad41d8a0d60ab98/coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34", size = 233816, upload-time = "2024-08-04T19:43:19.049Z" }, - { url = "https://files.pythonhosted.org/packages/28/7c/3753c8b40d232b1e5eeaed798c875537cf3cb183fb5041017c1fdb7ec14e/coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c", size = 232325, upload-time = "2024-08-04T19:43:21.246Z" }, - { url = "https://files.pythonhosted.org/packages/57/e3/818a2b2af5b7573b4b82cf3e9f137ab158c90ea750a8f053716a32f20f06/coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959", size = 233418, upload-time = "2024-08-04T19:43:22.945Z" }, - { url = "https://files.pythonhosted.org/packages/c8/fb/4532b0b0cefb3f06d201648715e03b0feb822907edab3935112b61b885e2/coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232", size = 209343, upload-time = "2024-08-04T19:43:25.121Z" }, - { url = "https://files.pythonhosted.org/packages/5a/25/af337cc7421eca1c187cc9c315f0a755d48e755d2853715bfe8c418a45fa/coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0", size = 210136, upload-time = "2024-08-04T19:43:26.851Z" }, - { url = "https://files.pythonhosted.org/packages/ad/5f/67af7d60d7e8ce61a4e2ddcd1bd5fb787180c8d0ae0fbd073f903b3dd95d/coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93", size = 206796, upload-time = "2024-08-04T19:43:29.115Z" }, - { url = "https://files.pythonhosted.org/packages/e1/0e/e52332389e057daa2e03be1fbfef25bb4d626b37d12ed42ae6281d0a274c/coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3", size = 207244, upload-time = "2024-08-04T19:43:31.285Z" }, - { url = "https://files.pythonhosted.org/packages/aa/cd/766b45fb6e090f20f8927d9c7cb34237d41c73a939358bc881883fd3a40d/coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff", size = 239279, upload-time = "2024-08-04T19:43:33.581Z" }, - { url = "https://files.pythonhosted.org/packages/70/6c/a9ccd6fe50ddaf13442a1e2dd519ca805cbe0f1fcd377fba6d8339b98ccb/coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d", size = 236859, upload-time = "2024-08-04T19:43:35.301Z" }, - { url = "https://files.pythonhosted.org/packages/14/6f/8351b465febb4dbc1ca9929505202db909c5a635c6fdf33e089bbc3d7d85/coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6", size = 238549, upload-time = "2024-08-04T19:43:37.578Z" }, - { url = "https://files.pythonhosted.org/packages/68/3c/289b81fa18ad72138e6d78c4c11a82b5378a312c0e467e2f6b495c260907/coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56", size = 237477, upload-time = "2024-08-04T19:43:39.92Z" }, - { url = "https://files.pythonhosted.org/packages/ed/1c/aa1efa6459d822bd72c4abc0b9418cf268de3f60eeccd65dc4988553bd8d/coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234", size = 236134, upload-time = "2024-08-04T19:43:41.453Z" }, - { url = "https://files.pythonhosted.org/packages/fb/c8/521c698f2d2796565fe9c789c2ee1ccdae610b3aa20b9b2ef980cc253640/coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133", size = 236910, upload-time = "2024-08-04T19:43:43.037Z" }, - { url = "https://files.pythonhosted.org/packages/7d/30/033e663399ff17dca90d793ee8a2ea2890e7fdf085da58d82468b4220bf7/coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c", size = 209348, upload-time = "2024-08-04T19:43:44.787Z" }, - { url = "https://files.pythonhosted.org/packages/20/05/0d1ccbb52727ccdadaa3ff37e4d2dc1cd4d47f0c3df9eb58d9ec8508ca88/coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6", size = 210230, upload-time = "2024-08-04T19:43:46.707Z" }, - { url = "https://files.pythonhosted.org/packages/7e/d4/300fc921dff243cd518c7db3a4c614b7e4b2431b0d1145c1e274fd99bd70/coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778", size = 206983, upload-time = "2024-08-04T19:43:49.082Z" }, - { url = "https://files.pythonhosted.org/packages/e1/ab/6bf00de5327ecb8db205f9ae596885417a31535eeda6e7b99463108782e1/coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391", size = 207221, upload-time = "2024-08-04T19:43:52.15Z" }, - { url = "https://files.pythonhosted.org/packages/92/8f/2ead05e735022d1a7f3a0a683ac7f737de14850395a826192f0288703472/coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8", size = 240342, upload-time = "2024-08-04T19:43:53.746Z" }, - { url = "https://files.pythonhosted.org/packages/0f/ef/94043e478201ffa85b8ae2d2c79b4081e5a1b73438aafafccf3e9bafb6b5/coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d", size = 237371, upload-time = "2024-08-04T19:43:55.993Z" }, - { url = "https://files.pythonhosted.org/packages/1f/0f/c890339dd605f3ebc269543247bdd43b703cce6825b5ed42ff5f2d6122c7/coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca", size = 239455, upload-time = "2024-08-04T19:43:57.618Z" }, - { url = "https://files.pythonhosted.org/packages/d1/04/7fd7b39ec7372a04efb0f70c70e35857a99b6a9188b5205efb4c77d6a57a/coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163", size = 238924, upload-time = "2024-08-04T19:44:00.012Z" }, - { url = "https://files.pythonhosted.org/packages/ed/bf/73ce346a9d32a09cf369f14d2a06651329c984e106f5992c89579d25b27e/coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a", size = 237252, upload-time = "2024-08-04T19:44:01.713Z" }, - { url = "https://files.pythonhosted.org/packages/86/74/1dc7a20969725e917b1e07fe71a955eb34bc606b938316bcc799f228374b/coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d", size = 238897, upload-time = "2024-08-04T19:44:03.898Z" }, - { url = "https://files.pythonhosted.org/packages/b6/e9/d9cc3deceb361c491b81005c668578b0dfa51eed02cd081620e9a62f24ec/coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5", size = 209606, upload-time = "2024-08-04T19:44:05.532Z" }, - { url = "https://files.pythonhosted.org/packages/47/c8/5a2e41922ea6740f77d555c4d47544acd7dc3f251fe14199c09c0f5958d3/coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb", size = 210373, upload-time = "2024-08-04T19:44:07.079Z" }, - { url = "https://files.pythonhosted.org/packages/8c/f9/9aa4dfb751cb01c949c990d136a0f92027fbcc5781c6e921df1cb1563f20/coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106", size = 207007, upload-time = "2024-08-04T19:44:09.453Z" }, - { url = "https://files.pythonhosted.org/packages/b9/67/e1413d5a8591622a46dd04ff80873b04c849268831ed5c304c16433e7e30/coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9", size = 207269, upload-time = "2024-08-04T19:44:11.045Z" }, - { url = "https://files.pythonhosted.org/packages/14/5b/9dec847b305e44a5634d0fb8498d135ab1d88330482b74065fcec0622224/coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c", size = 239886, upload-time = "2024-08-04T19:44:12.83Z" }, - { url = "https://files.pythonhosted.org/packages/7b/b7/35760a67c168e29f454928f51f970342d23cf75a2bb0323e0f07334c85f3/coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a", size = 237037, upload-time = "2024-08-04T19:44:15.393Z" }, - { url = "https://files.pythonhosted.org/packages/f7/95/d2fd31f1d638df806cae59d7daea5abf2b15b5234016a5ebb502c2f3f7ee/coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060", size = 239038, upload-time = "2024-08-04T19:44:17.466Z" }, - { url = "https://files.pythonhosted.org/packages/6e/bd/110689ff5752b67924efd5e2aedf5190cbbe245fc81b8dec1abaffba619d/coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862", size = 238690, upload-time = "2024-08-04T19:44:19.336Z" }, - { url = "https://files.pythonhosted.org/packages/d3/a8/08d7b38e6ff8df52331c83130d0ab92d9c9a8b5462f9e99c9f051a4ae206/coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388", size = 236765, upload-time = "2024-08-04T19:44:20.994Z" }, - { url = "https://files.pythonhosted.org/packages/d6/6a/9cf96839d3147d55ae713eb2d877f4d777e7dc5ba2bce227167d0118dfe8/coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155", size = 238611, upload-time = "2024-08-04T19:44:22.616Z" }, - { url = "https://files.pythonhosted.org/packages/74/e4/7ff20d6a0b59eeaab40b3140a71e38cf52547ba21dbcf1d79c5a32bba61b/coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a", size = 209671, upload-time = "2024-08-04T19:44:24.418Z" }, - { url = "https://files.pythonhosted.org/packages/35/59/1812f08a85b57c9fdb6d0b383d779e47b6f643bc278ed682859512517e83/coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129", size = 210368, upload-time = "2024-08-04T19:44:26.276Z" }, - { url = "https://files.pythonhosted.org/packages/9c/15/08913be1c59d7562a3e39fce20661a98c0a3f59d5754312899acc6cb8a2d/coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e", size = 207758, upload-time = "2024-08-04T19:44:29.028Z" }, - { url = "https://files.pythonhosted.org/packages/c4/ae/b5d58dff26cade02ada6ca612a76447acd69dccdbb3a478e9e088eb3d4b9/coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962", size = 208035, upload-time = "2024-08-04T19:44:30.673Z" }, - { url = "https://files.pythonhosted.org/packages/b8/d7/62095e355ec0613b08dfb19206ce3033a0eedb6f4a67af5ed267a8800642/coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb", size = 250839, upload-time = "2024-08-04T19:44:32.412Z" }, - { url = "https://files.pythonhosted.org/packages/7c/1e/c2967cb7991b112ba3766df0d9c21de46b476d103e32bb401b1b2adf3380/coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704", size = 246569, upload-time = "2024-08-04T19:44:34.547Z" }, - { url = "https://files.pythonhosted.org/packages/8b/61/a7a6a55dd266007ed3b1df7a3386a0d760d014542d72f7c2c6938483b7bd/coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b", size = 248927, upload-time = "2024-08-04T19:44:36.313Z" }, - { url = "https://files.pythonhosted.org/packages/c8/fa/13a6f56d72b429f56ef612eb3bc5ce1b75b7ee12864b3bd12526ab794847/coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f", size = 248401, upload-time = "2024-08-04T19:44:38.155Z" }, - { url = "https://files.pythonhosted.org/packages/75/06/0429c652aa0fb761fc60e8c6b291338c9173c6aa0f4e40e1902345b42830/coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223", size = 246301, upload-time = "2024-08-04T19:44:39.883Z" }, - { url = "https://files.pythonhosted.org/packages/52/76/1766bb8b803a88f93c3a2d07e30ffa359467810e5cbc68e375ebe6906efb/coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3", size = 247598, upload-time = "2024-08-04T19:44:41.59Z" }, - { url = "https://files.pythonhosted.org/packages/66/8b/f54f8db2ae17188be9566e8166ac6df105c1c611e25da755738025708d54/coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f", size = 210307, upload-time = "2024-08-04T19:44:43.301Z" }, - { url = "https://files.pythonhosted.org/packages/9f/b0/e0dca6da9170aefc07515cce067b97178cefafb512d00a87a1c717d2efd5/coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657", size = 211453, upload-time = "2024-08-04T19:44:45.677Z" }, - { url = "https://files.pythonhosted.org/packages/81/d0/d9e3d554e38beea5a2e22178ddb16587dbcbe9a1ef3211f55733924bf7fa/coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0", size = 206674, upload-time = "2024-08-04T19:44:47.694Z" }, - { url = "https://files.pythonhosted.org/packages/38/ea/cab2dc248d9f45b2b7f9f1f596a4d75a435cb364437c61b51d2eb33ceb0e/coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a", size = 207101, upload-time = "2024-08-04T19:44:49.32Z" }, - { url = "https://files.pythonhosted.org/packages/ca/6f/f82f9a500c7c5722368978a5390c418d2a4d083ef955309a8748ecaa8920/coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b", size = 236554, upload-time = "2024-08-04T19:44:51.631Z" }, - { url = "https://files.pythonhosted.org/packages/a6/94/d3055aa33d4e7e733d8fa309d9adf147b4b06a82c1346366fc15a2b1d5fa/coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3", size = 234440, upload-time = "2024-08-04T19:44:53.464Z" }, - { url = "https://files.pythonhosted.org/packages/e4/6e/885bcd787d9dd674de4a7d8ec83faf729534c63d05d51d45d4fa168f7102/coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de", size = 235889, upload-time = "2024-08-04T19:44:55.165Z" }, - { url = "https://files.pythonhosted.org/packages/f4/63/df50120a7744492710854860783d6819ff23e482dee15462c9a833cc428a/coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6", size = 235142, upload-time = "2024-08-04T19:44:57.269Z" }, - { url = "https://files.pythonhosted.org/packages/3a/5d/9d0acfcded2b3e9ce1c7923ca52ccc00c78a74e112fc2aee661125b7843b/coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569", size = 233805, upload-time = "2024-08-04T19:44:59.033Z" }, - { url = "https://files.pythonhosted.org/packages/c4/56/50abf070cb3cd9b1dd32f2c88f083aab561ecbffbcd783275cb51c17f11d/coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989", size = 234655, upload-time = "2024-08-04T19:45:01.398Z" }, - { url = "https://files.pythonhosted.org/packages/25/ee/b4c246048b8485f85a2426ef4abab88e48c6e80c74e964bea5cd4cd4b115/coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7", size = 209296, upload-time = "2024-08-04T19:45:03.819Z" }, - { url = "https://files.pythonhosted.org/packages/5c/1c/96cf86b70b69ea2b12924cdf7cabb8ad10e6130eab8d767a1099fbd2a44f/coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8", size = 210137, upload-time = "2024-08-04T19:45:06.25Z" }, - { url = "https://files.pythonhosted.org/packages/19/d3/d54c5aa83268779d54c86deb39c1c4566e5d45c155369ca152765f8db413/coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255", size = 206688, upload-time = "2024-08-04T19:45:08.358Z" }, - { url = "https://files.pythonhosted.org/packages/a5/fe/137d5dca72e4a258b1bc17bb04f2e0196898fe495843402ce826a7419fe3/coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8", size = 207120, upload-time = "2024-08-04T19:45:11.526Z" }, - { url = "https://files.pythonhosted.org/packages/78/5b/a0a796983f3201ff5485323b225d7c8b74ce30c11f456017e23d8e8d1945/coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2", size = 235249, upload-time = "2024-08-04T19:45:13.202Z" }, - { url = "https://files.pythonhosted.org/packages/4e/e1/76089d6a5ef9d68f018f65411fcdaaeb0141b504587b901d74e8587606ad/coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a", size = 233237, upload-time = "2024-08-04T19:45:14.961Z" }, - { url = "https://files.pythonhosted.org/packages/9a/6f/eef79b779a540326fee9520e5542a8b428cc3bfa8b7c8f1022c1ee4fc66c/coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc", size = 234311, upload-time = "2024-08-04T19:45:16.924Z" }, - { url = "https://files.pythonhosted.org/packages/75/e1/656d65fb126c29a494ef964005702b012f3498db1a30dd562958e85a4049/coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004", size = 233453, upload-time = "2024-08-04T19:45:18.672Z" }, - { url = "https://files.pythonhosted.org/packages/68/6a/45f108f137941a4a1238c85f28fd9d048cc46b5466d6b8dda3aba1bb9d4f/coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb", size = 231958, upload-time = "2024-08-04T19:45:20.63Z" }, - { url = "https://files.pythonhosted.org/packages/9b/e7/47b809099168b8b8c72ae311efc3e88c8d8a1162b3ba4b8da3cfcdb85743/coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36", size = 232938, upload-time = "2024-08-04T19:45:23.062Z" }, - { url = "https://files.pythonhosted.org/packages/52/80/052222ba7058071f905435bad0ba392cc12006380731c37afaf3fe749b88/coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c", size = 209352, upload-time = "2024-08-04T19:45:25.042Z" }, - { url = "https://files.pythonhosted.org/packages/b8/d8/1b92e0b3adcf384e98770a00ca095da1b5f7b483e6563ae4eb5e935d24a1/coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca", size = 210153, upload-time = "2024-08-04T19:45:27.079Z" }, - { url = "https://files.pythonhosted.org/packages/a5/2b/0354ed096bca64dc8e32a7cbcae28b34cb5ad0b1fe2125d6d99583313ac0/coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df", size = 198926, upload-time = "2024-08-04T19:45:28.875Z" }, -] - -[package.optional-dependencies] -toml = [ - { name = "tomli", marker = "python_full_version < '3.9'" }, -] - [[package]] name = "coverage" version = "7.10.6" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/14/70/025b179c993f019105b79575ac6edb5e084fb0f0e63f15cdebef4e454fb5/coverage-7.10.6.tar.gz", hash = "sha256:f644a3ae5933a552a29dbb9aa2f90c677a875f80ebea028e5a52a4f429044b90", size = 823736, upload-time = "2025-08-29T15:35:16.668Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a8/1d/2e64b43d978b5bd184e0756a41415597dfef30fcbd90b747474bd749d45f/coverage-7.10.6-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:70e7bfbd57126b5554aa482691145f798d7df77489a177a6bef80de78860a356", size = 217025, upload-time = "2025-08-29T15:32:57.169Z" }, @@ -427,7 +274,7 @@ wheels = [ [package.optional-dependencies] toml = [ - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version <= '3.11'" }, + { name = "tomli", marker = "python_full_version <= '3.11'" }, ] [[package]] @@ -444,113 +291,40 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.13'" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] -[[package]] -name = "filelock" -version = "3.16.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/9d/db/3ef5bb276dae18d6ec2124224403d1d67bccdbefc17af4cc8f553e341ab1/filelock-3.16.1.tar.gz", hash = "sha256:c249fbfcd5db47e5e2d6d62198e565475ee65e4831e2561c8e313fa7eb961435", size = 18037, upload-time = "2024-09-17T19:02:01.779Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/b9/f8/feced7779d755758a52d1f6635d990b8d98dc0a29fa568bbe0625f18fdf3/filelock-3.16.1-py3-none-any.whl", hash = "sha256:2082e5703d51fbf98ea75855d9d5527e33d8ff23099bec374a134febee6946b0", size = 16163, upload-time = "2024-09-17T19:02:00.268Z" }, -] - [[package]] name = "filelock" version = "3.19.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/40/bb/0ab3e58d22305b6f5440629d20683af28959bf793d98d11950e305c1c326/filelock-3.19.1.tar.gz", hash = "sha256:66eda1888b0171c998b35be2bcc0f6d75c388a7ce20c3f3f37aa8e96c2dddf58", size = 17687, upload-time = "2025-08-14T16:56:03.016Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/42/14/42b2651a2f46b022ccd948bca9f2d5af0fd8929c4eec235b8d6d844fbe67/filelock-3.19.1-py3-none-any.whl", hash = "sha256:d38e30481def20772f5baf097c122c3babc4fcdb7e14e57049eb9d88c6dc017d", size = 15988, upload-time = "2025-08-14T16:56:01.633Z" }, ] -[[package]] -name = "flake8" -version = "5.0.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.8.1'", -] -dependencies = [ - { name = "mccabe", marker = "python_full_version < '3.8.1'" }, - { name = "pycodestyle", version = "2.9.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8.1'" }, - { name = "pyflakes", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8.1'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ad/00/9808c62b2d529cefc69ce4e4a1ea42c0f855effa55817b7327ec5b75e60a/flake8-5.0.4.tar.gz", hash = "sha256:6fbe320aad8d6b95cec8b8e47bc933004678dc63095be98528b7bdd2a9f510db", size = 145862, upload-time = "2022-08-03T23:21:27.108Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/cf/a0/b881b63a17a59d9d07f5c0cc91a29182c8e8a9aa2bde5b3b2b16519c02f4/flake8-5.0.4-py2.py3-none-any.whl", hash = "sha256:7a1cf6b73744f5806ab95e526f6f0d8c01c66d7bbe349562d22dfca20610b248", size = 61897, upload-time = "2022-08-03T23:21:25.027Z" }, -] - -[[package]] -name = "flake8" -version = "7.1.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", -] -dependencies = [ - { name = "mccabe", marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, - { name = "pycodestyle", version = "2.12.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, - { name = "pyflakes", version = "3.2.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/58/16/3f2a0bb700ad65ac9663262905a025917c020a3f92f014d2ba8964b4602c/flake8-7.1.2.tar.gz", hash = "sha256:c586ffd0b41540951ae41af572e6790dbd49fc12b3aa2541685d253d9bd504bd", size = 48119, upload-time = "2025-02-16T18:45:44.296Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/35/f8/08d37b2cd89da306e3520bd27f8a85692122b42b56c0c2c3784ff09c022f/flake8-7.1.2-py2.py3-none-any.whl", hash = "sha256:1cbc62e65536f65e6d754dfe6f1bada7f5cf392d6f5db3c2b85892466c3e7c1a", size = 57745, upload-time = "2025-02-16T18:45:42.351Z" }, -] - [[package]] name = "flake8" version = "7.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] dependencies = [ - { name = "mccabe", marker = "python_full_version >= '3.9'" }, - { name = "pycodestyle", version = "2.14.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pyflakes", version = "3.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "mccabe" }, + { name = "pycodestyle" }, + { name = "pyflakes" }, ] sdist = { url = "https://files.pythonhosted.org/packages/9b/af/fbfe3c4b5a657d79e5c47a2827a362f9e1b763336a52f926126aa6dc7123/flake8-7.3.0.tar.gz", hash = "sha256:fe044858146b9fc69b551a4b490d69cf960fcb78ad1edcb84e7fbb1b4a8e3872", size = 48326, upload-time = "2025-06-20T19:31:35.838Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/9f/56/13ab06b4f93ca7cac71078fbe37fcea175d3216f31f85c3168a6bbd0bb9a/flake8-7.3.0-py2.py3-none-any.whl", hash = "sha256:b9696257b9ce8beb888cdbe31cf885c90d31928fe202be0889a7cdafad32f01e", size = 57922, upload-time = "2025-06-20T19:31:34.425Z" }, ] -[[package]] -name = "identify" -version = "2.6.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/29/bb/25024dbcc93516c492b75919e76f389bac754a3e4248682fba32b250c880/identify-2.6.1.tar.gz", hash = "sha256:91478c5fb7c3aac5ff7bf9b4344f803843dc586832d5f110d672b19aa1984c98", size = 99097, upload-time = "2024-09-14T23:50:32.513Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7d/0c/4ef72754c050979fdcc06c744715ae70ea37e734816bb6514f79df77a42f/identify-2.6.1-py2.py3-none-any.whl", hash = "sha256:53863bcac7caf8d2ed85bd20312ea5dcfc22226800f6d6881f232d861db5a8f0", size = 98972, upload-time = "2024-09-14T23:50:30.747Z" }, -] - [[package]] name = "identify" version = "2.6.14" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/52/c4/62963f25a678f6a050fb0505a65e9e726996171e6dbe1547f79619eefb15/identify-2.6.14.tar.gz", hash = "sha256:663494103b4f717cb26921c52f8751363dc89db64364cd836a9bf1535f53cd6a", size = 99283, upload-time = "2025-09-06T19:30:52.938Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/e5/ae/2ad30f4652712c82f1c23423d79136fbce338932ad166d70c1efb86a5998/identify-2.6.14-py2.py3-none-any.whl", hash = "sha256:11a073da82212c6646b1f39bb20d4483bfb9543bd5566fec60053c4bb309bf2e", size = 99172, upload-time = "2025-09-06T19:30:51.759Z" }, @@ -579,8 +353,7 @@ name = "jinja2" version = "3.1.6" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "markupsafe", version = "2.1.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "markupsafe", version = "3.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "markupsafe" }, ] sdist = { url = "https://files.pythonhosted.org/packages/df/bf/f7da0350254c0ed7c72f3e33cef02e048281fec7ecec5f032d4aac52226b/jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", size = 245115, upload-time = "2025-03-05T20:05:02.478Z" } wheels = [ @@ -589,7 +362,7 @@ wheels = [ [[package]] name = "kilm" -version = "0.4.2" +version = "0.5.0" source = { editable = "." } dependencies = [ { name = "click", version = "8.1.8", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.10'" }, @@ -599,28 +372,20 @@ dependencies = [ { name = "pathlib" }, { name = "pathspec" }, { name = "pyyaml" }, - { name = "questionary", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "questionary", version = "2.1.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "requests", version = "2.32.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "requests", version = "2.32.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "questionary" }, + { name = "requests" }, { name = "rich" }, { name = "typer" }, ] [package.optional-dependencies] dev = [ - { name = "black", version = "24.8.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "black", version = "25.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "flake8", version = "5.0.4", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.8.1'" }, - { name = "flake8", version = "7.1.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.8.1' and python_full_version < '3.9'" }, - { name = "flake8", version = "7.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pre-commit", version = "3.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pre-commit", version = "4.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "black" }, + { name = "flake8" }, + { name = "pre-commit" }, { name = "pyrefly" }, - { name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pytest-cov", version = "5.0.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "pytest-cov", version = "6.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "pytest" }, + { name = "pytest-cov" }, { name = "ruff" }, ] @@ -651,9 +416,7 @@ name = "markdown-it-py" version = "3.0.0" source = { registry = "https://pypi.org/simple" } resolution-markers = [ - "python_full_version == '3.9.*'", - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", + "python_full_version < '3.10'", ] dependencies = [ { name = "mdurl", marker = "python_full_version < '3.10'" }, @@ -678,76 +441,10 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/94/54/e7d793b573f298e1c9013b8c4dade17d481164aa517d1d7148619c2cedbf/markdown_it_py-4.0.0-py3-none-any.whl", hash = "sha256:87327c59b172c5011896038353a81343b6754500a08cd7a4973bb48c6d578147", size = 87321, upload-time = "2025-08-11T12:57:51.923Z" }, ] -[[package]] -name = "markupsafe" -version = "2.1.5" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/87/5b/aae44c6655f3801e81aa3eef09dbbf012431987ba564d7231722f68df02d/MarkupSafe-2.1.5.tar.gz", hash = "sha256:d283d37a890ba4c1ae73ffadf8046435c76e7bc2247bbb63c00bd1a709c6544b", size = 19384, upload-time = "2024-02-02T16:31:22.863Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e4/54/ad5eb37bf9d51800010a74e4665425831a9db4e7c4e0fde4352e391e808e/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a17a92de5231666cfbe003f0e4b9b3a7ae3afb1ec2845aadc2bacc93ff85febc", size = 18206, upload-time = "2024-02-02T16:30:04.105Z" }, - { url = "https://files.pythonhosted.org/packages/6a/4a/a4d49415e600bacae038c67f9fecc1d5433b9d3c71a4de6f33537b89654c/MarkupSafe-2.1.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:72b6be590cc35924b02c78ef34b467da4ba07e4e0f0454a2c5907f473fc50ce5", size = 14079, upload-time = "2024-02-02T16:30:06.5Z" }, - { url = "https://files.pythonhosted.org/packages/0a/7b/85681ae3c33c385b10ac0f8dd025c30af83c78cec1c37a6aa3b55e67f5ec/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61659ba32cf2cf1481e575d0462554625196a1f2fc06a1c777d3f48e8865d46", size = 26620, upload-time = "2024-02-02T16:30:08.31Z" }, - { url = "https://files.pythonhosted.org/packages/7c/52/2b1b570f6b8b803cef5ac28fdf78c0da318916c7d2fe9402a84d591b394c/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2174c595a0d73a3080ca3257b40096db99799265e1c27cc5a610743acd86d62f", size = 25818, upload-time = "2024-02-02T16:30:09.577Z" }, - { url = "https://files.pythonhosted.org/packages/29/fe/a36ba8c7ca55621620b2d7c585313efd10729e63ef81e4e61f52330da781/MarkupSafe-2.1.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ae2ad8ae6ebee9d2d94b17fb62763125f3f374c25618198f40cbb8b525411900", size = 25493, upload-time = "2024-02-02T16:30:11.488Z" }, - { url = "https://files.pythonhosted.org/packages/60/ae/9c60231cdfda003434e8bd27282b1f4e197ad5a710c14bee8bea8a9ca4f0/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:075202fa5b72c86ad32dc7d0b56024ebdbcf2048c0ba09f1cde31bfdd57bcfff", size = 30630, upload-time = "2024-02-02T16:30:13.144Z" }, - { url = "https://files.pythonhosted.org/packages/65/dc/1510be4d179869f5dafe071aecb3f1f41b45d37c02329dfba01ff59e5ac5/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:598e3276b64aff0e7b3451b72e94fa3c238d452e7ddcd893c3ab324717456bad", size = 29745, upload-time = "2024-02-02T16:30:14.222Z" }, - { url = "https://files.pythonhosted.org/packages/30/39/8d845dd7d0b0613d86e0ef89549bfb5f61ed781f59af45fc96496e897f3a/MarkupSafe-2.1.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:fce659a462a1be54d2ffcacea5e3ba2d74daa74f30f5f143fe0c58636e355fdd", size = 30021, upload-time = "2024-02-02T16:30:16.032Z" }, - { url = "https://files.pythonhosted.org/packages/c7/5c/356a6f62e4f3c5fbf2602b4771376af22a3b16efa74eb8716fb4e328e01e/MarkupSafe-2.1.5-cp310-cp310-win32.whl", hash = "sha256:d9fad5155d72433c921b782e58892377c44bd6252b5af2f67f16b194987338a4", size = 16659, upload-time = "2024-02-02T16:30:17.079Z" }, - { url = "https://files.pythonhosted.org/packages/69/48/acbf292615c65f0604a0c6fc402ce6d8c991276e16c80c46a8f758fbd30c/MarkupSafe-2.1.5-cp310-cp310-win_amd64.whl", hash = "sha256:bf50cd79a75d181c9181df03572cdce0fbb75cc353bc350712073108cba98de5", size = 17213, upload-time = "2024-02-02T16:30:18.251Z" }, - { url = "https://files.pythonhosted.org/packages/11/e7/291e55127bb2ae67c64d66cef01432b5933859dfb7d6949daa721b89d0b3/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:629ddd2ca402ae6dbedfceeba9c46d5f7b2a61d9749597d4307f943ef198fc1f", size = 18219, upload-time = "2024-02-02T16:30:19.988Z" }, - { url = "https://files.pythonhosted.org/packages/6b/cb/aed7a284c00dfa7c0682d14df85ad4955a350a21d2e3b06d8240497359bf/MarkupSafe-2.1.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5b7b716f97b52c5a14bffdf688f971b2d5ef4029127f1ad7a513973cfd818df2", size = 14098, upload-time = "2024-02-02T16:30:21.063Z" }, - { url = "https://files.pythonhosted.org/packages/1c/cf/35fe557e53709e93feb65575c93927942087e9b97213eabc3fe9d5b25a55/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ec585f69cec0aa07d945b20805be741395e28ac1627333b1c5b0105962ffced", size = 29014, upload-time = "2024-02-02T16:30:22.926Z" }, - { url = "https://files.pythonhosted.org/packages/97/18/c30da5e7a0e7f4603abfc6780574131221d9148f323752c2755d48abad30/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b91c037585eba9095565a3556f611e3cbfaa42ca1e865f7b8015fe5c7336d5a5", size = 28220, upload-time = "2024-02-02T16:30:24.76Z" }, - { url = "https://files.pythonhosted.org/packages/0c/40/2e73e7d532d030b1e41180807a80d564eda53babaf04d65e15c1cf897e40/MarkupSafe-2.1.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7502934a33b54030eaf1194c21c692a534196063db72176b0c4028e140f8f32c", size = 27756, upload-time = "2024-02-02T16:30:25.877Z" }, - { url = "https://files.pythonhosted.org/packages/18/46/5dca760547e8c59c5311b332f70605d24c99d1303dd9a6e1fc3ed0d73561/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:0e397ac966fdf721b2c528cf028494e86172b4feba51d65f81ffd65c63798f3f", size = 33988, upload-time = "2024-02-02T16:30:26.935Z" }, - { url = "https://files.pythonhosted.org/packages/6d/c5/27febe918ac36397919cd4a67d5579cbbfa8da027fa1238af6285bb368ea/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c061bb86a71b42465156a3ee7bd58c8c2ceacdbeb95d05a99893e08b8467359a", size = 32718, upload-time = "2024-02-02T16:30:28.111Z" }, - { url = "https://files.pythonhosted.org/packages/f8/81/56e567126a2c2bc2684d6391332e357589a96a76cb9f8e5052d85cb0ead8/MarkupSafe-2.1.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3a57fdd7ce31c7ff06cdfbf31dafa96cc533c21e443d57f5b1ecc6cdc668ec7f", size = 33317, upload-time = "2024-02-02T16:30:29.214Z" }, - { url = "https://files.pythonhosted.org/packages/00/0b/23f4b2470accb53285c613a3ab9ec19dc944eaf53592cb6d9e2af8aa24cc/MarkupSafe-2.1.5-cp311-cp311-win32.whl", hash = "sha256:397081c1a0bfb5124355710fe79478cdbeb39626492b15d399526ae53422b906", size = 16670, upload-time = "2024-02-02T16:30:30.915Z" }, - { url = "https://files.pythonhosted.org/packages/b7/a2/c78a06a9ec6d04b3445a949615c4c7ed86a0b2eb68e44e7541b9d57067cc/MarkupSafe-2.1.5-cp311-cp311-win_amd64.whl", hash = "sha256:2b7c57a4dfc4f16f7142221afe5ba4e093e09e728ca65c51f5620c9aaeb9a617", size = 17224, upload-time = "2024-02-02T16:30:32.09Z" }, - { url = "https://files.pythonhosted.org/packages/53/bd/583bf3e4c8d6a321938c13f49d44024dbe5ed63e0a7ba127e454a66da974/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:8dec4936e9c3100156f8a2dc89c4b88d5c435175ff03413b443469c7c8c5f4d1", size = 18215, upload-time = "2024-02-02T16:30:33.081Z" }, - { url = "https://files.pythonhosted.org/packages/48/d6/e7cd795fc710292c3af3a06d80868ce4b02bfbbf370b7cee11d282815a2a/MarkupSafe-2.1.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:3c6b973f22eb18a789b1460b4b91bf04ae3f0c4234a0a6aa6b0a92f6f7b951d4", size = 14069, upload-time = "2024-02-02T16:30:34.148Z" }, - { url = "https://files.pythonhosted.org/packages/51/b5/5d8ec796e2a08fc814a2c7d2584b55f889a55cf17dd1a90f2beb70744e5c/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac07bad82163452a6884fe8fa0963fb98c2346ba78d779ec06bd7a6262132aee", size = 29452, upload-time = "2024-02-02T16:30:35.149Z" }, - { url = "https://files.pythonhosted.org/packages/0a/0d/2454f072fae3b5a137c119abf15465d1771319dfe9e4acbb31722a0fff91/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5dfb42c4604dddc8e4305050aa6deb084540643ed5804d7455b5df8fe16f5e5", size = 28462, upload-time = "2024-02-02T16:30:36.166Z" }, - { url = "https://files.pythonhosted.org/packages/2d/75/fd6cb2e68780f72d47e6671840ca517bda5ef663d30ada7616b0462ad1e3/MarkupSafe-2.1.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ea3d8a3d18833cf4304cd2fc9cbb1efe188ca9b5efef2bdac7adc20594a0e46b", size = 27869, upload-time = "2024-02-02T16:30:37.834Z" }, - { url = "https://files.pythonhosted.org/packages/b0/81/147c477391c2750e8fc7705829f7351cf1cd3be64406edcf900dc633feb2/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d050b3361367a06d752db6ead6e7edeb0009be66bc3bae0ee9d97fb326badc2a", size = 33906, upload-time = "2024-02-02T16:30:39.366Z" }, - { url = "https://files.pythonhosted.org/packages/8b/ff/9a52b71839d7a256b563e85d11050e307121000dcebc97df120176b3ad93/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:bec0a414d016ac1a18862a519e54b2fd0fc8bbfd6890376898a6c0891dd82e9f", size = 32296, upload-time = "2024-02-02T16:30:40.413Z" }, - { url = "https://files.pythonhosted.org/packages/88/07/2dc76aa51b481eb96a4c3198894f38b480490e834479611a4053fbf08623/MarkupSafe-2.1.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:58c98fee265677f63a4385256a6d7683ab1832f3ddd1e66fe948d5880c21a169", size = 33038, upload-time = "2024-02-02T16:30:42.243Z" }, - { url = "https://files.pythonhosted.org/packages/96/0c/620c1fb3661858c0e37eb3cbffd8c6f732a67cd97296f725789679801b31/MarkupSafe-2.1.5-cp312-cp312-win32.whl", hash = "sha256:8590b4ae07a35970728874632fed7bd57b26b0102df2d2b233b6d9d82f6c62ad", size = 16572, upload-time = "2024-02-02T16:30:43.326Z" }, - { url = "https://files.pythonhosted.org/packages/3f/14/c3554d512d5f9100a95e737502f4a2323a1959f6d0d01e0d0997b35f7b10/MarkupSafe-2.1.5-cp312-cp312-win_amd64.whl", hash = "sha256:823b65d8706e32ad2df51ed89496147a42a2a6e01c13cfb6ffb8b1e92bc910bb", size = 17127, upload-time = "2024-02-02T16:30:44.418Z" }, - { url = "https://files.pythonhosted.org/packages/f8/ff/2c942a82c35a49df5de3a630ce0a8456ac2969691b230e530ac12314364c/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:656f7526c69fac7f600bd1f400991cc282b417d17539a1b228617081106feb4a", size = 18192, upload-time = "2024-02-02T16:30:57.715Z" }, - { url = "https://files.pythonhosted.org/packages/4f/14/6f294b9c4f969d0c801a4615e221c1e084722ea6114ab2114189c5b8cbe0/MarkupSafe-2.1.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:97cafb1f3cbcd3fd2b6fbfb99ae11cdb14deea0736fc2b0952ee177f2b813a46", size = 14072, upload-time = "2024-02-02T16:30:58.844Z" }, - { url = "https://files.pythonhosted.org/packages/81/d4/fd74714ed30a1dedd0b82427c02fa4deec64f173831ec716da11c51a50aa/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f3fbcb7ef1f16e48246f704ab79d79da8a46891e2da03f8783a5b6fa41a9532", size = 26928, upload-time = "2024-02-02T16:30:59.922Z" }, - { url = "https://files.pythonhosted.org/packages/c7/bd/50319665ce81bb10e90d1cf76f9e1aa269ea6f7fa30ab4521f14d122a3df/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fa9db3f79de01457b03d4f01b34cf91bc0048eb2c3846ff26f66687c2f6d16ab", size = 26106, upload-time = "2024-02-02T16:31:01.582Z" }, - { url = "https://files.pythonhosted.org/packages/4c/6f/f2b0f675635b05f6afd5ea03c094557bdb8622fa8e673387444fe8d8e787/MarkupSafe-2.1.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ffee1f21e5ef0d712f9033568f8344d5da8cc2869dbd08d87c84656e6a2d2f68", size = 25781, upload-time = "2024-02-02T16:31:02.71Z" }, - { url = "https://files.pythonhosted.org/packages/51/e0/393467cf899b34a9d3678e78961c2c8cdf49fb902a959ba54ece01273fb1/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:5dedb4db619ba5a2787a94d877bc8ffc0566f92a01c0ef214865e54ecc9ee5e0", size = 30518, upload-time = "2024-02-02T16:31:04.392Z" }, - { url = "https://files.pythonhosted.org/packages/f6/02/5437e2ad33047290dafced9df741d9efc3e716b75583bbd73a9984f1b6f7/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:30b600cf0a7ac9234b2638fbc0fb6158ba5bdcdf46aeb631ead21248b9affbc4", size = 29669, upload-time = "2024-02-02T16:31:05.53Z" }, - { url = "https://files.pythonhosted.org/packages/0e/7d/968284145ffd9d726183ed6237c77938c021abacde4e073020f920e060b2/MarkupSafe-2.1.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8dd717634f5a044f860435c1d8c16a270ddf0ef8588d4887037c5028b859b0c3", size = 29933, upload-time = "2024-02-02T16:31:06.636Z" }, - { url = "https://files.pythonhosted.org/packages/bf/f3/ecb00fc8ab02b7beae8699f34db9357ae49d9f21d4d3de6f305f34fa949e/MarkupSafe-2.1.5-cp38-cp38-win32.whl", hash = "sha256:daa4ee5a243f0f20d528d939d06670a298dd39b1ad5f8a72a4275124a7819eff", size = 16656, upload-time = "2024-02-02T16:31:07.767Z" }, - { url = "https://files.pythonhosted.org/packages/92/21/357205f03514a49b293e214ac39de01fadd0970a6e05e4bf1ddd0ffd0881/MarkupSafe-2.1.5-cp38-cp38-win_amd64.whl", hash = "sha256:619bc166c4f2de5caa5a633b8b7326fbe98e0ccbfacabd87268a2b15ff73a029", size = 17206, upload-time = "2024-02-02T16:31:08.843Z" }, - { url = "https://files.pythonhosted.org/packages/0f/31/780bb297db036ba7b7bbede5e1d7f1e14d704ad4beb3ce53fb495d22bc62/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7a68b554d356a91cce1236aa7682dc01df0edba8d043fd1ce607c49dd3c1edcf", size = 18193, upload-time = "2024-02-02T16:31:10.155Z" }, - { url = "https://files.pythonhosted.org/packages/6c/77/d77701bbef72892affe060cdacb7a2ed7fd68dae3b477a8642f15ad3b132/MarkupSafe-2.1.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:db0b55e0f3cc0be60c1f19efdde9a637c32740486004f20d1cff53c3c0ece4d2", size = 14073, upload-time = "2024-02-02T16:31:11.442Z" }, - { url = "https://files.pythonhosted.org/packages/d9/a7/1e558b4f78454c8a3a0199292d96159eb4d091f983bc35ef258314fe7269/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e53af139f8579a6d5f7b76549125f0d94d7e630761a2111bc431fd820e163b8", size = 26486, upload-time = "2024-02-02T16:31:12.488Z" }, - { url = "https://files.pythonhosted.org/packages/5f/5a/360da85076688755ea0cceb92472923086993e86b5613bbae9fbc14136b0/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:17b950fccb810b3293638215058e432159d2b71005c74371d784862b7e4683f3", size = 25685, upload-time = "2024-02-02T16:31:13.726Z" }, - { url = "https://files.pythonhosted.org/packages/6a/18/ae5a258e3401f9b8312f92b028c54d7026a97ec3ab20bfaddbdfa7d8cce8/MarkupSafe-2.1.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4c31f53cdae6ecfa91a77820e8b151dba54ab528ba65dfd235c80b086d68a465", size = 25338, upload-time = "2024-02-02T16:31:14.812Z" }, - { url = "https://files.pythonhosted.org/packages/0b/cc/48206bd61c5b9d0129f4d75243b156929b04c94c09041321456fd06a876d/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bff1b4290a66b490a2f4719358c0cdcd9bafb6b8f061e45c7a2460866bf50c2e", size = 30439, upload-time = "2024-02-02T16:31:15.946Z" }, - { url = "https://files.pythonhosted.org/packages/d1/06/a41c112ab9ffdeeb5f77bc3e331fdadf97fa65e52e44ba31880f4e7f983c/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bc1667f8b83f48511b94671e0e441401371dfd0f0a795c7daa4a3cd1dde55bea", size = 29531, upload-time = "2024-02-02T16:31:17.13Z" }, - { url = "https://files.pythonhosted.org/packages/02/8c/ab9a463301a50dab04d5472e998acbd4080597abc048166ded5c7aa768c8/MarkupSafe-2.1.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5049256f536511ee3f7e1b3f87d1d1209d327e818e6ae1365e8653d7e3abb6a6", size = 29823, upload-time = "2024-02-02T16:31:18.247Z" }, - { url = "https://files.pythonhosted.org/packages/bc/29/9bc18da763496b055d8e98ce476c8e718dcfd78157e17f555ce6dd7d0895/MarkupSafe-2.1.5-cp39-cp39-win32.whl", hash = "sha256:00e046b6dd71aa03a41079792f8473dc494d564611a8f89bbbd7cb93295ebdcf", size = 16658, upload-time = "2024-02-02T16:31:19.583Z" }, - { url = "https://files.pythonhosted.org/packages/f6/f8/4da07de16f10551ca1f640c92b5f316f9394088b183c6a57183df6de5ae4/MarkupSafe-2.1.5-cp39-cp39-win_amd64.whl", hash = "sha256:fa173ec60341d6bb97a89f5ea19c85c5643c1e7dedebc22f5181eb73573142c5", size = 17211, upload-time = "2024-02-02T16:31:20.96Z" }, -] - [[package]] name = "markupsafe" version = "3.0.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/b2/97/5d42485e71dfc078108a86d6de8fa46db44a1a9295e89c5d6d4a06e23a62/markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", size = 20537, upload-time = "2024-10-18T15:21:54.129Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/04/90/d08277ce111dd22f77149fd1a5d4653eeb3b3eaacbdfcbae5afb2600eebd/MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", size = 14357, upload-time = "2024-10-18T15:20:51.44Z" }, @@ -875,92 +572,34 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/cc/20/ff623b09d963f88bfde16306a54e12ee5ea43e9b597108672ff3a408aad6/pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08", size = 31191, upload-time = "2023-12-10T22:30:43.14Z" }, ] -[[package]] -name = "platformdirs" -version = "4.3.6" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/13/fc/128cc9cb8f03208bdbf93d3aa862e16d376844a14f9a0ce5cf4507372de4/platformdirs-4.3.6.tar.gz", hash = "sha256:357fb2acbc885b0419afd3ce3ed34564c13c9b95c89360cd9563f73aa5e2b907", size = 21302, upload-time = "2024-09-17T19:06:50.688Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/a6/bc1012356d8ece4d66dd75c4b9fc6c1f6650ddd5991e421177d9f8f671be/platformdirs-4.3.6-py3-none-any.whl", hash = "sha256:73e575e1408ab8103900836b97580d5307456908a03e92031bab39e4554cc3fb", size = 18439, upload-time = "2024-09-17T19:06:49.212Z" }, -] - [[package]] name = "platformdirs" version = "4.4.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/23/e8/21db9c9987b0e728855bd57bff6984f67952bea55d6f75e055c46b5383e8/platformdirs-4.4.0.tar.gz", hash = "sha256:ca753cf4d81dc309bc67b0ea38fd15dc97bc30ce419a7f58d13eb3bf14c4febf", size = 21634, upload-time = "2025-08-26T14:32:04.268Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/40/4b/2028861e724d3bd36227adfa20d3fd24c3fc6d52032f4a93c133be5d17ce/platformdirs-4.4.0-py3-none-any.whl", hash = "sha256:abd01743f24e5287cd7a5db3752faf1a2d65353f38ec26d98e25a6db65958c85", size = 18654, upload-time = "2025-08-26T14:32:02.735Z" }, ] -[[package]] -name = "pluggy" -version = "1.5.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" }, -] - [[package]] name = "pluggy" version = "1.6.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] -[[package]] -name = "pre-commit" -version = "3.5.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -dependencies = [ - { name = "cfgv", marker = "python_full_version < '3.9'" }, - { name = "identify", version = "2.6.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "nodeenv", marker = "python_full_version < '3.9'" }, - { name = "pyyaml", marker = "python_full_version < '3.9'" }, - { name = "virtualenv", marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/04/b3/4ae08d21eb097162f5aad37f4585f8069a86402ed7f5362cc9ae097f9572/pre_commit-3.5.0.tar.gz", hash = "sha256:5804465c675b659b0862f07907f96295d490822a450c4c40e747d0b1c6ebcb32", size = 177079, upload-time = "2023-10-13T15:57:48.334Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/6c/75/526915fedf462e05eeb1c75ceaf7e3f9cde7b5ce6f62740fe5f7f19a0050/pre_commit-3.5.0-py2.py3-none-any.whl", hash = "sha256:841dc9aef25daba9a0238cd27984041fa0467b4199fc4852e27950664919f660", size = 203698, upload-time = "2023-10-13T15:57:46.378Z" }, -] - [[package]] name = "pre-commit" version = "4.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] dependencies = [ - { name = "cfgv", marker = "python_full_version >= '3.9'" }, - { name = "identify", version = "2.6.14", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "nodeenv", marker = "python_full_version >= '3.9'" }, - { name = "pyyaml", marker = "python_full_version >= '3.9'" }, - { name = "virtualenv", marker = "python_full_version >= '3.9'" }, + { name = "cfgv" }, + { name = "identify" }, + { name = "nodeenv" }, + { name = "pyyaml" }, + { name = "virtualenv" }, ] sdist = { url = "https://files.pythonhosted.org/packages/ff/29/7cf5bbc236333876e4b41f56e06857a87937ce4bf91e117a6991a2dbb02a/pre_commit-4.3.0.tar.gz", hash = "sha256:499fe450cc9d42e9d58e606262795ecb64dd05438943c62b66f6a8673da30b16", size = 193792, upload-time = "2025-08-09T18:56:14.651Z" } wheels = [ @@ -979,75 +618,19 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, ] -[[package]] -name = "pycodestyle" -version = "2.9.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/b6/83/5bcaedba1f47200f0665ceb07bcb00e2be123192742ee0edfb66b600e5fd/pycodestyle-2.9.1.tar.gz", hash = "sha256:2c9607871d58c76354b697b42f5d57e1ada7d261c261efac224b664affdc5785", size = 102127, upload-time = "2022-08-03T23:13:29.715Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/67/e4/fc77f1039c34b3612c4867b69cbb2b8a4e569720b1f19b0637002ee03aff/pycodestyle-2.9.1-py2.py3-none-any.whl", hash = "sha256:d1735fc58b418fd7c5f658d28d943854f8a849b01a5d0a1e6f3f3fdd0166804b", size = 41493, upload-time = "2022-08-03T23:13:27.416Z" }, -] - -[[package]] -name = "pycodestyle" -version = "2.12.1" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/43/aa/210b2c9aedd8c1cbeea31a50e42050ad56187754b34eb214c46709445801/pycodestyle-2.12.1.tar.gz", hash = "sha256:6838eae08bbce4f6accd5d5572075c63626a15ee3e6f842df996bf62f6d73521", size = 39232, upload-time = "2024-08-04T20:26:54.576Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3a/d8/a211b3f85e99a0daa2ddec96c949cac6824bd305b040571b82a03dd62636/pycodestyle-2.12.1-py2.py3-none-any.whl", hash = "sha256:46f0fb92069a7c28ab7bb558f05bfc0110dac69a0cd23c61ea0040283a9d78b3", size = 31284, upload-time = "2024-08-04T20:26:53.173Z" }, -] - [[package]] name = "pycodestyle" version = "2.14.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/11/e0/abfd2a0d2efe47670df87f3e3a0e2edda42f055053c85361f19c0e2c1ca8/pycodestyle-2.14.0.tar.gz", hash = "sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783", size = 39472, upload-time = "2025-06-20T18:49:48.75Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/d7/27/a58ddaf8c588a3ef080db9d0b7e0b97215cee3a45df74f3a94dbbf5c893a/pycodestyle-2.14.0-py2.py3-none-any.whl", hash = "sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d", size = 31594, upload-time = "2025-06-20T18:49:47.491Z" }, ] -[[package]] -name = "pyflakes" -version = "2.5.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/07/92/f0cb5381f752e89a598dd2850941e7f570ac3cb8ea4a344854de486db152/pyflakes-2.5.0.tar.gz", hash = "sha256:491feb020dca48ccc562a8c0cbe8df07ee13078df59813b83959cbdada312ea3", size = 66388, upload-time = "2022-07-30T17:29:05.816Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/dc/13/63178f59f74e53acc2165aee4b002619a3cfa7eeaeac989a9eb41edf364e/pyflakes-2.5.0-py2.py3-none-any.whl", hash = "sha256:4579f67d887f804e67edb544428f264b7b24f435b263c4614f384135cea553d2", size = 66116, upload-time = "2022-07-30T17:29:04.179Z" }, -] - -[[package]] -name = "pyflakes" -version = "3.2.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", -] -sdist = { url = "https://files.pythonhosted.org/packages/57/f9/669d8c9c86613c9d568757c7f5824bd3197d7b1c6c27553bc5618a27cce2/pyflakes-3.2.0.tar.gz", hash = "sha256:1c61603ff154621fb2a9172037d84dca3500def8c8b630657d1701f026f8af3f", size = 63788, upload-time = "2024-01-05T00:28:47.703Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d4/d7/f1b7db88d8e4417c5d47adad627a93547f44bdc9028372dbd2313f34a855/pyflakes-3.2.0-py2.py3-none-any.whl", hash = "sha256:84b5be138a2dfbb40689ca07e2152deb896a65c3a3e24c251c5c62489568074a", size = 62725, upload-time = "2024-01-05T00:28:45.903Z" }, -] - [[package]] name = "pyflakes" version = "3.4.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/45/dc/fd034dc20b4b264b3d015808458391acbf9df40b1e54750ef175d39180b1/pyflakes-3.4.0.tar.gz", hash = "sha256:b24f96fafb7d2ab0ec5075b7350b3d2d2218eab42003821c06344973d3ea2f58", size = 64669, upload-time = "2025-06-20T18:45:27.834Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/c2/2f/81d580a0fb83baeb066698975cb14a618bdbed7720678566f1b046a95fe8/pyflakes-3.4.0-py2.py3-none-any.whl", hash = "sha256:f742a7dbd0d9cb9ea41e9a24a918996e8170c799fa528688d40dd582c8265f4f", size = 63551, upload-time = "2025-06-20T18:45:26.937Z" }, @@ -1078,78 +661,32 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/53/b02648724846a3bd676410261f2d980a260a16e337fe978028429fc712d1/pyrefly-0.31.1-py3-none-win_arm64.whl", hash = "sha256:370d2b7fab9cab0de937f44638cf6666322e27b6d2c84c4b82cba0e868c6d437", size = 6421184, upload-time = "2025-09-05T23:06:48.218Z" }, ] -[[package]] -name = "pytest" -version = "8.3.5" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -dependencies = [ - { name = "colorama", marker = "python_full_version < '3.9' and sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version < '3.9'" }, - { name = "iniconfig", marker = "python_full_version < '3.9'" }, - { name = "packaging", marker = "python_full_version < '3.9'" }, - { name = "pluggy", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "tomli", marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" }, -] - [[package]] name = "pytest" version = "8.4.2" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] dependencies = [ - { name = "colorama", marker = "python_full_version >= '3.9' and sys_platform == 'win32'" }, - { name = "exceptiongroup", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, - { name = "iniconfig", marker = "python_full_version >= '3.9'" }, - { name = "packaging", marker = "python_full_version >= '3.9'" }, - { name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pygments", marker = "python_full_version >= '3.9'" }, - { name = "tomli", marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "colorama", marker = "sys_platform == 'win32'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "iniconfig" }, + { name = "packaging" }, + { name = "pluggy" }, + { name = "pygments" }, + { name = "tomli", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" }, ] -[[package]] -name = "pytest-cov" -version = "5.0.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -dependencies = [ - { name = "coverage", version = "7.6.1", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version < '3.9'" }, - { name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/74/67/00efc8d11b630c56f15f4ad9c7f9223f1e5ec275aaae3fa9118c6a223ad2/pytest-cov-5.0.0.tar.gz", hash = "sha256:5837b58e9f6ebd335b0f8060eecce69b662415b16dc503883a02f45dfeb14857", size = 63042, upload-time = "2024-03-24T20:16:34.856Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/78/3a/af5b4fa5961d9a1e6237b530eb87dd04aea6eb83da09d2a4073d81b54ccf/pytest_cov-5.0.0-py3-none-any.whl", hash = "sha256:4f0764a1219df53214206bf1feea4633c3b558a2925c8b59f144f682861ce652", size = 21990, upload-time = "2024-03-24T20:16:32.444Z" }, -] - [[package]] name = "pytest-cov" version = "6.3.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] dependencies = [ - { name = "coverage", version = "7.10.6", source = { registry = "https://pypi.org/simple" }, extra = ["toml"], marker = "python_full_version >= '3.9'" }, - { name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "coverage", extra = ["toml"] }, + { name = "pluggy" }, + { name = "pytest" }, ] sdist = { url = "https://files.pythonhosted.org/packages/30/4c/f883ab8f0daad69f47efdf95f55a66b51a8b939c430dadce0611508d9e99/pytest_cov-6.3.0.tar.gz", hash = "sha256:35c580e7800f87ce892e687461166e1ac2bcb8fb9e13aea79032518d6e503ff2", size = 70398, upload-time = "2025-09-06T15:40:14.361Z" } wheels = [ @@ -1198,13 +735,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/fe/0f/25911a9f080464c59fab9027482f822b86bf0608957a5fcc6eaac85aa515/PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", size = 751597, upload-time = "2024-08-06T20:32:56.985Z" }, { url = "https://files.pythonhosted.org/packages/14/0d/e2c3b43bbce3cf6bd97c840b46088a3031085179e596d4929729d8d68270/PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", size = 140527, upload-time = "2024-08-06T20:33:03.001Z" }, { url = "https://files.pythonhosted.org/packages/fa/de/02b54f42487e3d3c6efb3f89428677074ca7bf43aae402517bc7cca949f3/PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", size = 156446, upload-time = "2024-08-06T20:33:04.33Z" }, - { url = "https://files.pythonhosted.org/packages/74/d9/323a59d506f12f498c2097488d80d16f4cf965cee1791eab58b56b19f47a/PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", size = 183218, upload-time = "2024-08-06T20:33:06.411Z" }, - { url = "https://files.pythonhosted.org/packages/74/cc/20c34d00f04d785f2028737e2e2a8254e1425102e730fee1d6396f832577/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", size = 728067, upload-time = "2024-08-06T20:33:07.879Z" }, - { url = "https://files.pythonhosted.org/packages/20/52/551c69ca1501d21c0de51ddafa8c23a0191ef296ff098e98358f69080577/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", size = 757812, upload-time = "2024-08-06T20:33:12.542Z" }, - { url = "https://files.pythonhosted.org/packages/fd/7f/2c3697bba5d4aa5cc2afe81826d73dfae5f049458e44732c7a0938baa673/PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", size = 746531, upload-time = "2024-08-06T20:33:14.391Z" }, - { url = "https://files.pythonhosted.org/packages/8c/ab/6226d3df99900e580091bb44258fde77a8433511a86883bd4681ea19a858/PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", size = 800820, upload-time = "2024-08-06T20:33:16.586Z" }, - { url = "https://files.pythonhosted.org/packages/a0/99/a9eb0f3e710c06c5d922026f6736e920d431812ace24aae38228d0d64b04/PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", size = 145514, upload-time = "2024-08-06T20:33:22.414Z" }, - { url = "https://files.pythonhosted.org/packages/75/8a/ee831ad5fafa4431099aa4e078d4c8efd43cd5e48fbc774641d233b683a9/PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", size = 162702, upload-time = "2024-08-06T20:33:23.813Z" }, { url = "https://files.pythonhosted.org/packages/65/d8/b7a1db13636d7fb7d4ff431593c510c8b8fca920ade06ca8ef20015493c5/PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", size = 184777, upload-time = "2024-08-06T20:33:25.896Z" }, { url = "https://files.pythonhosted.org/packages/0a/02/6ec546cd45143fdf9840b2c6be8d875116a64076218b61d68e12548e5839/PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", size = 172318, upload-time = "2024-08-06T20:33:27.212Z" }, { url = "https://files.pythonhosted.org/packages/0e/9a/8cc68be846c972bda34f6c2a93abb644fb2476f4dcc924d52175786932c9/PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", size = 720891, upload-time = "2024-08-06T20:33:28.974Z" }, @@ -1216,70 +746,27 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/19/87/5124b1c1f2412bb95c59ec481eaf936cd32f0fe2a7b16b97b81c4c017a6a/PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", size = 162312, upload-time = "2024-08-06T20:33:49.073Z" }, ] -[[package]] -name = "questionary" -version = "2.1.0" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -dependencies = [ - { name = "prompt-toolkit", marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/a8/b8/d16eb579277f3de9e56e5ad25280fab52fc5774117fb70362e8c2e016559/questionary-2.1.0.tar.gz", hash = "sha256:6302cdd645b19667d8f6e6634774e9538bfcd1aad9be287e743d96cacaf95587", size = 26775, upload-time = "2024-12-29T11:49:17.802Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ad/3f/11dd4cd4f39e05128bfd20138faea57bec56f9ffba6185d276e3107ba5b2/questionary-2.1.0-py3-none-any.whl", hash = "sha256:44174d237b68bc828e4878c763a9ad6790ee61990e0ae72927694ead57bab8ec", size = 36747, upload-time = "2024-12-29T11:49:16.734Z" }, -] - [[package]] name = "questionary" version = "2.1.1" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] dependencies = [ - { name = "prompt-toolkit", marker = "python_full_version >= '3.9'" }, + { name = "prompt-toolkit" }, ] sdist = { url = "https://files.pythonhosted.org/packages/f6/45/eafb0bba0f9988f6a2520f9ca2df2c82ddfa8d67c95d6625452e97b204a5/questionary-2.1.1.tar.gz", hash = "sha256:3d7e980292bb0107abaa79c68dd3eee3c561b83a0f89ae482860b181c8bd412d", size = 25845, upload-time = "2025-08-28T19:00:20.851Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/3c/26/1062c7ec1b053db9e499b4d2d5bc231743201b74051c973dadeac80a8f43/questionary-2.1.1-py3-none-any.whl", hash = "sha256:a51af13f345f1cdea62347589fbb6df3b290306ab8930713bfae4d475a7d4a59", size = 36753, upload-time = "2025-08-28T19:00:19.56Z" }, ] -[[package]] -name = "requests" -version = "2.32.4" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -dependencies = [ - { name = "certifi", marker = "python_full_version < '3.9'" }, - { name = "charset-normalizer", marker = "python_full_version < '3.9'" }, - { name = "idna", marker = "python_full_version < '3.9'" }, - { name = "urllib3", version = "2.2.3", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/e1/0a/929373653770d8a0d7ea76c37de6e41f11eb07559b103b1c02cafb3f7cf8/requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422", size = 135258, upload-time = "2025-06-09T16:43:07.34Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/7c/e4/56027c4a6b4ae70ca9de302488c5ca95ad4a39e190093d6c1a8ace08341b/requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", size = 64847, upload-time = "2025-06-09T16:43:05.728Z" }, -] - [[package]] name = "requests" version = "2.32.5" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] dependencies = [ - { name = "certifi", marker = "python_full_version >= '3.9'" }, - { name = "charset-normalizer", marker = "python_full_version >= '3.9'" }, - { name = "idna", marker = "python_full_version >= '3.9'" }, - { name = "urllib3", version = "2.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "certifi" }, + { name = "charset-normalizer" }, + { name = "idna" }, + { name = "urllib3" }, ] sdist = { url = "https://files.pythonhosted.org/packages/c9/74/b3ff8e6c8446842c3f5c837e9c3dfcfe2018ea6ecef224c710c85ef728f4/requests-2.32.5.tar.gz", hash = "sha256:dbba0bac56e100853db0ea71b82b4dfd5fe2bf6d3754a8893c3af500cec7d7cf", size = 134517, upload-time = "2025-08-18T20:46:02.573Z" } wheels = [ @@ -1383,61 +870,26 @@ dependencies = [ { name = "click", version = "8.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" }, { name = "rich" }, { name = "shellingham" }, - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, + { name = "typing-extensions" }, ] sdist = { url = "https://files.pythonhosted.org/packages/92/e8/2a73ccf9874ec4c7638f172efc8972ceab13a0e3480b389d6ed822f7a822/typer-0.17.4.tar.gz", hash = "sha256:b77dc07d849312fd2bb5e7f20a7af8985c7ec360c45b051ed5412f64d8dc1580", size = 103734, upload-time = "2025-09-05T18:14:40.746Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/93/72/6b3e70d32e89a5cbb6a4513726c1ae8762165b027af569289e19ec08edd8/typer-0.17.4-py3-none-any.whl", hash = "sha256:015534a6edaa450e7007eba705d5c18c3349dcea50a6ad79a5ed530967575824", size = 46643, upload-time = "2025-09-05T18:14:39.166Z" }, ] -[[package]] -name = "typing-extensions" -version = "4.13.2" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" }, -] - [[package]] name = "typing-extensions" version = "4.15.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" }, ] -[[package]] -name = "urllib3" -version = "2.2.3" -source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.8.1' and python_full_version < '3.9'", - "python_full_version < '3.8.1'", -] -sdist = { url = "https://files.pythonhosted.org/packages/ed/63/22ba4ebfe7430b76388e7cd448d5478814d3032121827c12a2cc287e2260/urllib3-2.2.3.tar.gz", hash = "sha256:e7d814a81dad81e6caf2ec9fdedb284ecc9c73076b62654547cc64ccdcae26e9", size = 300677, upload-time = "2024-09-12T10:52:18.401Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/ce/d9/5f4c13cecde62396b0d3fe530a50ccea91e7dfc1ccf0e09c228841bb5ba8/urllib3-2.2.3-py3-none-any.whl", hash = "sha256:ca899ca043dcb1bafa3e262d73aa25c465bfb49e0bd9dd5d59f1d0acba2f8fac", size = 126338, upload-time = "2024-09-12T10:52:16.589Z" }, -] - [[package]] name = "urllib3" version = "2.5.0" source = { registry = "https://pypi.org/simple" } -resolution-markers = [ - "python_full_version >= '3.10'", - "python_full_version == '3.9.*'", -] sdist = { url = "https://files.pythonhosted.org/packages/15/22/9ee70a2574a4f4599c47dd506532914ce044817c7752a79b6a51286319bc/urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", size = 393185, upload-time = "2025-06-18T14:07:41.644Z" } wheels = [ { url = "https://files.pythonhosted.org/packages/a7/c2/fe1e52489ae3122415c51f387e221dd0773709bad6c6cdaa599e8a2c5185/urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc", size = 129795, upload-time = "2025-06-18T14:07:40.39Z" }, @@ -1449,12 +901,9 @@ version = "20.34.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "distlib" }, - { name = "filelock", version = "3.16.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "filelock", version = "3.19.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "platformdirs", version = "4.3.6", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "platformdirs", version = "4.4.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9'" }, - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" }, - { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.11'" }, + { name = "filelock" }, + { name = "platformdirs" }, + { name = "typing-extensions", marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/1c/14/37fcdba2808a6c615681cd216fecae00413c9dab44fb2e57805ecf3eaee3/virtualenv-20.34.0.tar.gz", hash = "sha256:44815b2c9dee7ed86e387b842a84f20b93f7f417f95886ca1996a72a4138eb1a", size = 6003808, upload-time = "2025-08-13T14:24:07.464Z" } wheels = [

  2. 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 literal 0 HcmV?d00001 diff --git a/docs/src/assets/cli-help.png b/docs/src/assets/cli-help.png new file mode 100644 index 0000000000000000000000000000000000000000..84c9ca752c22f1c935070c258a2e96d319e3a6ca GIT binary patch literal 319825 zcmeEv2UJs8_b*}r1+jxDRYXK7BGL(AfXDWGskMRGPFzML;@;G$}z5 zkQ(Wo&_fRpAf&$=XXYE{`@(T4J-`;1Rlh7O5YJ2w_+rz-X zuvh)sWnBgaHZ}%^otDhIfKTq6o4U!sz^ZAls(M3RRh93ChpVlC)ez9{@X0Rr`-Ds?i#Y! zE*i75oH;vZ`8l^@_cpIS!zvk+j4y?VjEA<$NtUoOtol^lN_gPF`21``RP7F8VV$60 z;kD%ZJ6_#q;|e}v!58Q8_U)H#BHI^GP34IUH;a3?qK&EZ)VwR2r(d!#sJ!LVKGe9g zY(MV~2G@hvZ2TGar#_c~CkW|}b?u+~_WHqoLt*#Fdt`*&6ZTll6ox(i{?O#3Y*`Ne!d<50Z!}IWVPotVlm@rG|%{o@>`bmh#tAkmpq>C@v59}_G zW;iXzzTS6MLQ?O*!MqP@&O1EBnmJAF??=2qe_bKqkMb+?v0AD==@67VFiMtwG&9DR zy0@9v_*Cn7?Zs>+_n2!uM+aOzFG*t6TtAR! z!RsmVEll&_t3B>2RkHkymV2KFO!O7pB})tMj30cm?Rfl&tDMhvem(!F6>%X)3=r~U`X8xH2Srccfo_8!`XKthkQbc?=p8)Ndiyy8B(y@2`3w&2WO z_Yc<&@@9>>gY03@Fb5GAp_b6ul6vwLxz8HItYfnNLG#tUB*juWeS+VM3*u+ACxy&m zwfn+#@eeRNNAI&RGO(P!qqRNiBK!UlpDy3e3i>+xN49f*V>mJL9myJYZGP@WwWG*s z2I!@ej4PkrDS?$Ip6|owsTv6i@l4z@WO_b~O25^xONYO8=UqOg;j@J3lMi@K-WPg) zfLbGiY?h8shKdQpYzw3ar`}RR5+?Sfsu6+h} zN#PLIuggQQrReWh{VtbYyeBjme^M-Z@3M!;y%54hGG3i1p^>&kBgyhhu>+Wr^Jla9`=QT9LXOOqq{!a9(Rl7DZ>{b0wY>^^doCWa$%QsY zHuik{9N@_WdEAO5^Aj)iKHgjOmHjSLzGtucJY)C6uI=nTT#nVo`6(KTrQ@*Gh0@?Y zO9H9kvAim-85g5(tGjq>ymMytN>`jvLTq}#(Xy!24x6#CW<_?UAc@N&u*)N|zf8_g z%`)4Ol>;vw1Ht-olF>?z&0_+_YLoB4g0CANU8`yW31zJJ%-$X9%^ zPe5Z~`3HDU?%%Cu`TXR`BMmAipD@OUHmhkokGUrIVQ0qGb^eeSQQvmH+gtWP@v{7j zo^L{jRl9C-cQO}UQhVzZ{owH%_vsxMwkQ9>{+i``>OD^5(8Wu0-=n4lS9kSCRH;DD z-Osptz4@?bb?;G*XJ20ycwK+oQunk#H~U~#?XgjLi<LUm04xDG!+kNGs?iZgg{9iaXM7;M8 z9|*mCsx4uf4PJZFlHGlm`)>E`?)#Q^6ohZQ>Qz1QVpV5_t5nGk3EXQk7ml?&ol?_Gn{111&$Lg!x9=YBg`>wJjw$YaQ^ys)CtN-} z>zMe=;ZK6es_<*#ujAVHeHZU2zaX4okYK7+HRaT@r==#Lb)&AN!L#| zF*ND9B6HC7fF;bZG`^vyVlj$Wi}lV8!Y#JKjM$Dxs-z1Bqy?orA{pG4Ts zhUnMHx6DdQUDzw3|H?(eS&Hmr>&)(IaId(2zDlku$r{<%N@^cHS>{JVvi{dTy>^+BK?==;-6c62j z)Up+M7Bzj$$}e|{>@V+owjk4663!R4bd;a-rrcQUgHPM*`B87`M&Af@NDLNyFBo2) zy!PxxgMeX}qRdKSRF+;uhje;*%15`lnyFd0v$X3!1dV zobc$I_85p6mGAa`<5)OnDB~*=Z<1q@Uj7J@Nd)6eoVa}sLv|A@m_FB_tRmE+>eX~) zkcvn$4C*iEX9HPS1uNBo!|pW~OGH+-RN#kADh2|LlroeO1N#HD0`XNbRgt7-^24A3 zGR)mc?sk${QXEB_a-OP6!IZ%UZx0^YW~Ab#;;!QO+UHKd9siLBe1)&WUMIX>ywfwn z`B~@^Gyh%wvzJ_!!~7V{rScRyL0$&aGw0Uwd-GTF)kb|rKP=T1O!s~-$f_HDmLK-~ za;Mra*UTp}zY%YC-_&~>arsb6%G|T8s{c!dnE_7Sy*+T>M;aoC~gQ+JUoOIV!JufWB?+@`nZd5Nj*7?3GO*@=Am~;np zxBnr_p}nW3t}DuiDupV~sGQ-KlJK^hs1i;nE+-eb;8ewg(r`Gjkm zMq8m5W;JF8DOn+DVB=*=u#L6#2`wA*SkB6Ro~?BoQz%gAYmJ*aIW^xPh)$d0iM^-! zK`>qDxDHIZOv^!B^kuQma?%G|jS`XT#by!TguWeL@fwK?diLe&a@5$}DxIJ!l#qT5 zo>@~j(Kbk8(f15Do6!M$DE2tVQPEfBBg;CUmAekxA8vT+BD!i^YJZ^WTE%}fv zcIa7lb_)^rGs2?y50~>N#*isNV#G3EdqR7+jZ2fXn2=bU2%_wZ@0Bi%oS2qmZz`Hy8o8@E!^}6t4=GHh&3K@ z*G2dCj%ydVN-IvxR<>OxKopP;Z-fb%$U{giP6`vJbS~fqzI*`#=^yHkRATk(T{*qpHdOyhy*TU} zJYdFXDSG|mYJ5ZCEV>n$DE~k{k0e2fjNoYJfR{g|bP_ztnu&2t)D>b@D#X;c{%l{? zaF6EjG@@_0d(zoc=N9sTZy81jAx?QseKRXS952%eg~I}2gh#8X^H~c$b*^_&i)&Ns z>l*m;L8v^2UD0ZZUJT|KhWoKQ7`DTXXN>EkYpQ;E-}*6-nIx1gueyFjhQVP}InaxP zR9?2Tdf1u4=wcvv55vt13}cE6^5E4w+_Ft;$qF%#n31~@1**~}(}JOTx9r+^Nj&|G zshKQC`zb6>Qy!cj7~EtOjMQzlv>46+@0l5PY&*uV6L_}`_*L3={9o^{ZadAe z{m18w3=ARm3_E^nqYb>$ex3urw0nMi-Tv}10~7GyLEzW#HRJEC+1Orh|NZ?=OW+#A zMLkt@b>LOc%EQLS#q*x4*PUH{;=l*H-LBpCWME(yr2TGF*FCueJipiemXVi{)^&L+ zS7))i)~=Q|Vt&qUwC6A=`pE-too&4C^7%PCxp>O^flmBrArHK#eJp;0??)3aN6-l) zts8u*t{ygg(qiYt&Ye)&!^g*`=wWRuuY39GZ?^;gfll1>@^X_G7x(q`74wx8bM>$j zmynZ_6F+xe{QP-QpoOTXzl+yhKT#J?fnOi;`*SYacv^YbyLs8Wy71ASd)Ly{+Y5B! z1g)cg{royk8$bI$dUEmnZCbzt#c5Z>CB)8&|LfVnt%|fyxZpi?iUKN$8~zdv96?M6j$ z+T4Gl#jk|^@hL!Qr9Fz`|Kgg`p6jNyG-2YhzpQf$cm>3a_QO~J{5k#WEAW2Xyw2f8 ze?A5V6$bUo7jOA(n;$C3b#95}UF{fhaMRRg-ErBFV|_c{3wgnh-vhUwAnr7Fc%uH= zyFod#(GR&zO#&(_B#&v;j;A2bIkTGR;-k*Z*9F%g*IaU}XTGXmI z-kd2_=h|sH$1?SuTq$l*Man`^5L5w``wZI{cQEhgb2}SMoq%o(Sae}~sACpE_z>!X zGJZvw!hyh_37QgLfKlgMaRdw%OI>L8z_GJ$L{bx}BTXm*jymOgc0(CT$P%Y^M;HlUu0RNhm&#ij%+cE&A_|SXT6o+tP*jojQll z$!=VB;=S@aA%7q3ufxtevJpwiqT-5ndj%0JNXxw5!~Tc?pT!sbJ<3Q0<-|E(JM+i- zuoh0nR#H)BYkLvQ=MSFz`B6JsSvD-V6kTn1{>rg`yUKic|NE6Ml-38w6mZuT=AfbT zB&S?dvOlMRzqB2*EVd_8Ub6?>AHLZXWyOIBRm2~m3B$iXdOzO{mDi0dM1_40^Me9K zc~rp<*ut_P-zgiT$-X51k!FjmSrM~2dzl}i^q+UDj8xqJ{26O&K=08i_f@t9pAnzO zD84W7jO?tU#C>Z;P7#LU(ZOC(sF_@Acw(Ji9?r^Ia$oxV73NjiNS@Za0KP|*lNla75=Wo4klkj68b zeK(X3MYY5{xFltxQZI+KvG`+9{PmhJEv1UGNNdraEOi>R=Hoz zvhyc%#)9CIR|cc)3ZtfDOY{LlKceu%(4#?n*RN6HUVldK3b2-Oj0y)hA#=8+c*ID&IewpafX1T@%<`keH|lrikHRdqXv}`4S?;2 z4*k#Q^Cb2M&1ixa*dam|XGzmGwPf7qWo`Ip?NX_$$2l6;VoUXaf;&T8wC~4KOsxQ20F-c_4@W-go6ezKBO`3k!xnJyERXXa)VTAPA@;|Z)e*zQ1WWdKS_IMtl3%>5K1fNl5 z&^OP`Ta+9Bo_;apu&d|$#dwG7?nNbxxrXfTSDbR4dZ%K8#`_@#rQJBk^5+Ctkbo|! zKYRWveJi_T{m?ntQVXR1b$Zu>MR#PfZoB1QR`m%TrV8K1ty|IZ=968fL~Ymbo>KGM zuNw=?KHN<-A%r_(ZjTzH@)j=5LI~m4mK_T}Y=Z6f_tLOm5Xex1u0<{0|Ni`r8Fol$-vCWoT$xfX>_4) zyj1Qe1Ad0MW?D=4dheyzjr&z%;^wjdCa!KVaf^w+LZU5A+|tA?b4mv{|4nm>8Iv1d zLIC-QB4;GSS2M*fisu}JK*0{>8UWF~Q|>HIBJW2q$?8oekNax&ybVrV4P?L^*UTc7 zw8-dkoS@S;%}13S1fXh`&zZ;c;W7`S{$qyB3R5TtvL0W$f{ffQ2HI}zyL^j?6v{}) zD5Dk}^l4rsGl&;^UUuWAbtJ+N@0tku^hSez6w!Md@K>!vh6;53m5ay?n~jvlrZwNS zq-Ew+*5^ZAdJ7g+0bFTG?sfBWI)I0i(;4Yc?r=3FM8h!8Kl+@^#R!1wi!v}72mtlp z{s*X^|Na^A9#ofSUGO63{nD)T{=ICierd2WyBIrc{3!u=Owf2c420shU$|z9Qd^C1 z)I;e(fncWa9|SW$;0GcL9kzW)lEK|jr|39W((-kXClVm3q}ElXv*fx|5Tr`Az5hjN zRpc~xPg+$v1&Gn?{y~iPD?bg9oJ^nW7{+p84l=T`a1NBfA0T8l2Fkmvcz6f)O%)#w@#&XMFn!}FNGegGb zQC2K0pmSs6zO`AqzO9l?hVTK|jnILBs!M0-hidm#_5x5uif~eszNpCx->_kRO%o=Z zqJPCF7pm<34zW+=>HPyP<+&$sO!j44I=JO)r02F20{xhp6m7O7Q4I!CQ9W~^Vf4fM z5ys#%HM{_hMEie!<5b++=ZWr56d3Wi8GHuqd9zB@IB1;hq{)uV)xc-Ar(e?7vto7t zH+mC~=+MQD#67n-DeqT2KuAY;Oftwfm)x&sUBbzz---_Fx0|1lad|vTfEdgW2`|rY zmhQ3w=1@<{K1J6K1Yg;i$qEIKDGXi26ljM`c0{Zn?sI;u5`&dXS?2^mXyThs6qr7t zs_GrHzF-uMA1l;2fE^u$bVxpp!I!V9V}?v_I)nGE~Y9^ zTv(MpKl#p`y5r{7jC7!X+342m#w9fXdit9~zWc5ZmaRMLycn`&z9k2jbbuG6qe?k5 z=P{)Y&*^i4Ic)b)E-q|g0{zSEN8X<&-JF~R!+LmDx7e`7hAnN_(uTh>N+Zf- z4rt{)+jcNBX@-~bdEA2lS0=A^V3fvbX@8`~a-K`VQrsD|_H=2uPh@K}y&VV$EX!#D_f)BCu?Gy9F4*WwSW~iQ>Y##_e1-gi#=meGO2GK9#$?R&kSTGAv;qhV#h?kw-%MK z<@OwYAEcyqE2~pUcU-b34TF5amAQJliE4qFE>A)t^9?vPh}WI- zjIb#fBy!?bs+w{pSrWkwU;eO3u7`PE42Z9Ahh7KK9U;x5EY;JTnY;qv!)F>2N#bll zyz@?xU`1Nhg#)#!7;1KLBo|#+U#zhJD#~_4_FWK= z6oR0?kW;M%tX`W!4=w7%xclUf=<%*RxRQ6w;Jt?ua{YZh5KBVcxX4&WMqdyd^ikgd zlVS4+(i#L^pD;~Tvvb7Y7p9lp_t8x_0TKOD5fHcLfk>N_Qo5X=t)C>iK{LY&AMAt^ zp7V-;yYer^VEv2LKs3HT7@vl7>@S_e&%ephh3JT$9rRo$77C%yfaFaeNLRJUNC^GB z0ZC>FRptsov&%q$%gd!kt+-!phP2z~ z9McbRxIGFhM8QFFhBIw_{g5C9aKNA{y@Udd6aln~SI2!&`t_;7iNM-x8RgU<{LJ`| zY3Bpe288}IcMrug28-|G2}J%YhIhkZ@t{Hr>R23#Xh-$Y9RUV`BEC8UA~-FehzlFA zXPfi_jH8M+i~+H?^eJ$|lor#wPrX@HRxmoZ`sVI(VF*pR z&`~CfZMgr#GLv%*1wmQ1toqp&YmmpZ)D8~-&|_30&pH`c&s$`=wIaQC$8IoalX;~yS zg&y1 zjS%{hkI!`H5kNJ-B(6sKIy&7{~ z$lWae@z=W+5T=M@5=ch{-66@n{_p&~p zFcpl!OfBOmZLU>B%nUDTc(`3zD-<;u5acz-N$D+H7Y=Dii`yd$S8H80RUWH9qO6ul z^7*mIf>f6=1W8Gkz(1{$@sd3?_>=~uZ|P<=FguiJCE=0|-Twimegy8-D~!IJ6r-J= z8ka&oe|FSqj(lvd#OA-s3LTv6BVAwU@u_zK_M9M79KgA}%i~Ys0{TG;L91ps&nrD< zfl~@!@fEEoZTbPO${i*kiLc;wJDl$I-Wwyi;ysAWm@ZJ%fYs9EID^_JYNnqz67a`4 z13!U-8UNhKtYHD)wd-pUUm;1D**-nulbj;D59L$2V+eFw?qfbg_j+krwV6dORDU27 za;n5|?^(cC1KyE<`E_aNhpUF638k|j4@2ZF%(aSod@c-B6xnOM$<~7%K1YD!21j(4 z7QI|Va3ag#+9biSDCd)%2L#Bh{5m=6f1AmXCkb{Xm>$H&WTEnk9vt^WpvxD3?D>Iq z<$oDMqSessf#`k{rXEK?n(M0+tArw{E92KusBfkzYgMX|XzOnD*ZUfMK@kW{rZS05#~3SeoeD^A1>& zb?x~?2QnTMJ@xqavjBcgvHz9rJD2U|9Q9+!G%)U%oN7?B=D^sBF5(^q$af8KKzKOU zo30koSd+v7l=2NXZ?X~bG~XSg(f(7*v?23H0z;P9%y~T51=uY|g)dQdXP*PhoE2ts zn@ZJRA(`s@FGX5ov|-YKeXe(`@!p=S-Lmi=pNB$713vQAcYfvFQk#enpPM;Q7U(Z| z_9wCWDNK8P|Nh-aj)`As!+fkr8>UFnv0TGLZc2Fz%sQ|f6BIu-C=g(tm6QHL6q-sOWOkL7%HN z$vRV1B3Ev%#}^2Vur`?tNbB#Ad^ILuAmFH{B&@V@`}bFnV=|IQ5Jw-J0rqRp;!eFhv9@WZ~{zE(I^x-#hhF$9s|CTODtadP}%|E+X1er$1SmEd#P;GXEPp ziPdQgWgI~jZZ0V)Db3YbkbE4K*~ycL=8ZkDt!GehNgzrTvOTg1uJ1JgVEr)J5JdO7%h{1h!kURms@mhI2s`1uEdcgb zjj8$p3aShJ=QY8*fc-Up>U`VhpF7{hq}*eXML%Y^U)=@lc*tWf;-%X+vj{)XxnTd& z(8)~P=_5UoH*_o4Y1w}ReFs-hpUO0qW7-;h!!rOX0Tx+c*|znDO=zdeyhcPL&Tb9s zzphvc|JiE(6dYuq0m^8)TEA^_O2%UVkSKq}Mb~ygqMw6zX=L`m9Ih{SXKE}sw*ob& z*J{*-2NaT#w;;g2;Ha+o4F`Nu4o)9$h^J%+DIsA@xJ?4tV0|Et&F$y(-=v1-`Te-L zkPX;}QgGx!U8IWo8f{|3#`+nREq!YVjP|m^Hjs2|yn_y~#`7V8+d>pxxK?$B3h=lK ziSEOW(60*G&zGMGq#N`V1jOm58;%|X;{W|9J$6IP%}cYKr!&lH6Z-@F?G;LO!T?A1 zEdaZcbqor}vnD-@hYcq!CW(avyds2WknWZkfTsqutdfJ>#3o0zsWO`9@{U0o$AD6h za_R;K+Vi8{8j1mipi2xJjXYBX?YafMtqVw+lO}=jp(4DY% z;Kwl*0gY~f!JIYfKTiEHecYP9S;g|-SPX4i1BxMj9Pxn_u2}3VX;EoKs=12 zoq=M&-it4>nymV^NkJ9!-_;M=VK_Q+mP!*-fFeik)&8~c#o8t~8LD8g_-t@9z0U-i z8!m)Z(7%4?T6NQ!YJkq|3gBECO0>X~stZu|w$wZFTlvP;@PD;VTh#xzvRIlpZ3)lc zb8TC~^M65j(wN_kh8~8$yj-6q3_pzN{m?85_*AI=UD|&Qk~vz-Fp%9~)Qb8tjH|u> zFs82q1ljXWGHMK@VekADH!n91i`IFH{Pr1!vmXO#@h-DF& z)2T(m!-eQD2yHF`Ob{gtzBQRzIDC{S1l&u~_a~UrXAPel2aq@Oop~ou-%q~Q>7yCn;-foH0&xmVFoPMRomN;!$r!DKW* z_TSs71gojPO*rb>^KS0r`T?Ce^CQ$>8yQZbJ@bxSBL{xXBY#{T0@~4@J`T5L+Qc>I zmjEf1N@5L3FL~GzfKVJc*nKSuNC?E3S}^V(|087%+X~ z@wkBOjYo%q4yLI@EQriX1aDvZH4#tfRzFf_JX9=-J07(!Rfh_&p0o-ShY?`bH(93u}RQ+AMLfPCFyTm#R-UAr!o@BNLHi4x+-g8&=lQx>)aR zt+G2weNj|6_kjx9akaJgTmO;OOf=$`(MGvj7}qtDq0(`WO}0N(0(p(aA!rxfT-zOm z;92o>LnH!St)J&k>jG3`M}=gRjYo}|ko;LPQnz&1XEc{~mSeD8oVwF3Y3*Ap7C z<%Shl*ZLtymJ(f&-_LjM1Q2;%MsB(b|EG$JKa1)HwXb|%e#TSJZPoB6C!X%yS#bIL zevyj@SPX8>?>+urz4Ne@%RxsG_0@#;5^3>+uPig`j1HPuazJXIT3+12a{7eN#r%}} z9=Lf7PwOHAI`GT03dP92cu(7@0CaL6==f0NADbG#-(ft+blmCE!%cVH{lQrJkpM9E z%mdG5jlyA7bj4xQyMEG1K9$#>cbsIC?tRD{LO%rhQ{&AjcT0fJJ^vUeaFdYc?>t%M z!R~8ZPWihJu>F}Qe{UAQ4eb3@m9aZgU;_R1{l7B|hTvU?p3C;$Idp<+6X~K8t^WsE zZiL_e`q^Q1b+fSZ@9=ByDS)P*PhFP%JB>GK^ZMAf&<9=9Gn-Xg{vGBXyAIIwfz}hZ zzteb=HY!qpuxGV(Y?d1M8=}s9;T1sBU5Wcg|4!pg+5|fQ!fud~zR5xEo80whfxLGP zpy^&|{x5&%^4}4OKey>(zQ&b(Rmb8V$k>(v`LnQX8IXT7m0Jen&jx?Xfc)9oY#ER( z1M+9rwq-yz!BM{gye$K=WkCJ|>i>l6wh+jc0r`gpge6@ik|+5s1b4-x5+8cVt^_=+ z&bW3kUujOzakIs_9}>7m%LMQmrqGXks~Jx(Wm#l%6ItiDvv4!)&%}o_rrCI)0asa% z`kAyz#H=t@LVP38@Bsx-8H(atYZHfnbsuSDQM>>i=)G5Sq!CV~8?) zqy}#3DAd$D$-spuo#c4!Q(eEjHuQ^#3( zZ-=L;7nV58{lr@psC}~d=-sL5$I>VhhZO4i9Yqr((eZY}p+SyA7c49j;d6xv{>o_H z?c<3|P=2YIZ(vOY;r}Wq-CzacND}Myw%&q8Ce9f?zVT9Xd4xczHc9rd*t%E?BZS5qshy#=HrhkVSW zpdM4ras}2US&cGYAFuJLH<|?D$G(2%F1CSzFM6ZE2x_tYS%1@ ziT3`CKVE0Jj}XwWB>b^UXrR=ZvkjRL*{ z7u(@JaWfK{d7ih02e#OaYdkAy6@xVEu~aM>J}+C0a!GxQMUlG6?u%vON4Onxbe|PP zYn^N|pIbB4?F*YJv6 zav9x!4wHUw$bKq#xKg1Wi(E(^UitPSulD)EqV}Bn-8>NFD}{&)-Cp(KYTI%MufKpa zkC$3o0rHX!sg!&C*_=osA|}optgO^SBp|;y2WH~Vx!vh8aw$to#vbedj2bj^S>!zj z%DHE9{L_Jf)KS-h$#8e-d*2QMNo;kxO*pMeTBLG*2v@;l;_7K=jAZ|S$(r!{fSpjP zxmu?sgZw7#SZKOne9W8ryw@u#Z3w-GL(^wQVScGi!lp6l%Nx>MUQmG#7nJl#!m2LY zsH$G-3i?>8N9T*cv3&^M=*Jy}Jx3&*`zw-fb{xXKxq)1}-BMu}#fg-6ycB@`UVyz= zBM3wWOEY_{m5E|xuo9Z2kpz_EP|BdUI#P< z=fyBAemBj;RSQ8GBo&H?s!Dnw<*g4LsUbl+DC>iQQ_=|{)k zW#!)kDHb4=yR`ct4_&M6AnZo=POQ%@&rV?L>t?gnQ7+QU?sJX*7$|x$ZkKa~by(0e z*{eB%{pD8}hXpDBRJqe$&JRw5?gJ6_%#e9+wXmbhSB>-1^1DV-ty+`Hq)_}W*p^SC z`>hPD40ByY(Uo2#>v;()+gP65_vTG_|LM=pRw>~I-|AnSMCE+yPcJ_{C1vQ$4w+vr z>$I73c6nNk@fXV3H;`^;3ZCh1^KY9_R+a(|HY?ziaH|>E(}iC*{&d{jV-&*;lBf9D zHmN`8+F{t_uQPV-rOGF-+wX3Fm^@U*t=ogQ4(UY0p)v+kQh3)xGkw%m6L>=l39mC( zdp9IEX4r5>G7Cx-lL#V(%;3R?GXv|oz@kN7kzI9t?WN%!6&8rvgi7e10{wEfSvj?E zf}+O!>>5|@BrX-)3K1O_$*%q4ScEkva6E_(T0fFI9r|%6DmBw&B6Yb8JUOny_aFkl*rdw!+e0nTUS8n#3 zk~?W1kt5mIA)~d-k3%O?u;KP3g*3amoU^DKyE@aBqL<{k{<_ztJm#%Q$*BiljMS6R zBy7Aa<)IKuNdH>GNom-t!hrxRPfOkPT^ma^kz>pCs4#3RRGLDH6UGKMTe~1P7Osk# z+h{ww4da>Tn%%Z?P?y%gwr)u8n;; zI2;7=XuaUSO|qogHTM40(h=1m)E#u(?Nro)>B zLFlQ}CG^v?>0g%uc|~rW4az}R@cPalbDuci2-y0er(?&dUlZL2-S^c4=Iu#5X5o;g zNWnb{NwlQmpu&QO>&*fD?TlJN_F4rBf|D+&Wd~tdC2gCZPC`r%*^!;ey-=#s3?$=@ z*PL_SSAGDLwPB$p{z&GVTg6!J(WjQaa=J2>Ryww zWW(cijc0we#Br!5SR@&7K|Uvr-2tS=GKQV*NzXgP1Wj>m6Z;U_5o4$odbfr*?4&x; z7vV^lhl7aYM!uCMnw*JUhk6_k;$5D@EZcfcv|48yBZ<6FgbOS0@JFl@fA?e@=B3i{ zmsX;IaPCB6Yw4WJ0z{0XZe4?Z2*y$jK*gO9%4NFCiNS2Uo8zSv*~!*2`8^g?K5&lW z+b+tuXXt$klC^KvySt8|j~mz&aYN;r^20$yR1EblHV*L-49+$kjfN|-D}$UZ%kPOWS&EHEyv|b*= z94qrI92e#GQ!G(p`dFaUw3bY4tC|_@(Bb6}O6v8wWYzzM?a@9vHqApPE#L`6l2OJC zc3cKQu?(P=inE(7lUQKku3V&hZ3W$DicB?$Y!(s}B0Q&~sU=~}-D?JX#W?Td4Wz%$ z%R9UFnHO|@XOmr8ES>(6(=Lr5b(Q)EmZfn!n7#)@b+SUJ1UK7Mu9jyGNWebjm8)JB zF3WGN@w&grppuTvxw-|GzhrX6hh?FSGxd{rk(@BiQWuTvs-?H+vDbM@rj0$>l=VbN zZM&w7U@J07PAGQXN54?INa?v*NP|?l&%)sRLAzur{wnfdnPQCw4$~bFBdjOm;6bwOnI>=^G^VIjUx{mFhIkr-1#CFrE8&!T? zM-uDIAvp$Kvg&(YNiWm{v>W0UpK&CYFQ>(s3|$c{Kcs)NUiu8CNv!ycsuS-Sh;A`WrNj>ux$S zD>3!NQ6_T8*Q980a;4s-bUC%x8Amixv{<~HgC-Z7FxC4E+|g*{*#~PES|oBd_l^T%3-!5IGq13z&jW7H3ma89hSQfTmMC1)}b(`!=E4y_M`sR!!DcZ+*;hO4s5)W*bsmS5d z1dH_bEkh~k7RIi^{Nm0x9$fk`Fyt*zeD>JPBaY!`)-t2kOvUZWd6m+VQ_bM#>rAfT_{K=mIMr$6`&p6%Or_sEZ%UrB5lG$;-bKwU#A^iZQgu zmtV`NqM5y@M>n!$S)OHfW0jU?lE+yr?#aC=bQ|)>vxDJpae1$ndZcr0QgVXKuO1w% z#D@e+-Pvojz5D*=FYsk4H_|>OWtq5JFDTd^1nWKTRw$*gsJ&Pn0m1a8b*=jjSLxp* zekn2!a>tbc0dd}Y%=b5En_C2N&E$LQOK-;?K`oL8K4;&{#-WBFi~J$k#+}k7Sw=S# zC%|RAkzzAqchoS0pBU$`c?X+s+;dmjvK{Srn`<_5Dz* zg15LsRJgcYT)1ODjlStpGSexvTuJU8v$I_ZQm-1YS%~sj z6u);ZToYX!3s@~VOi@_jog0z<;$dcfEv>aT)ncjUy7%U~T&=RVIaVLb-?jOR(R6q9 zCEprR3KPpSl<|Mn61WzOTsc-sXw-TZG%;knV*GM7ntZ@RSNkQ|80+ue=+Z(sxm!GE zt?w>zG9g)9OT`b9TxoKhS#hSG{503U&Xp*0JTG+)he4&jcXeUP@xf`;iD;Q}DcBO( ziE+anKzhNoz}bZ<_d@Q; zgj6!*NUeE-Q*CZ&u&52X!oZy}|8WeV$Oj2;UkR6S zx@nE*fr0v0MYvO5f?rmcy~0j_UUFMC3k;;AJ<5du!@cs<9~DxkRIJ)o_T}i>tCUOG zk9w{K@CZWNRQanWq)J%aZo@r7KS3!SV4Hzcv3(L*bF{(0U>kBXuzaqmo@0US@R zIJLX5&(RtwOr#e7SE~QpwPyhzm_5WP^h333yW1l(LcUL>dQ4AM)?Q(+6cOdvQm?a|IP^%clw|*=^}O2R4#JWI{wSobl(W^fV(rKc-(N}p`qBa z%4YoGwv!){XFE(+?yu=0NPhHXrpxZOX zjSE$rs*kgy&8LLYmDtlMUY5pii%09t5EqWTUY`N~g2mE~9QQeA*Vw%UomLayfb^n| zZ=AD&GF!J}VC=A+nv$vpnu3S}@e-jKByh8!bKS%Ab&ZVNvZ+VCj&P=SaM>jv?I>)F z(s*O|P=CR^_W+jjrL%=rQtDNvz%^Lu(p$sCM+pN5WEM-E>sS5MU^VvXdsy-+&tEVw zbq@`|JQI)SV&dAkA+PI#Yc;Z3bHNkLd=cyetns*@hJ{l{O#)XGtJaDQE$fpPwTSw< z-x5kLsIfF+r-w>#5vj2b;Ps02{$?Zlm^tH<4GW#eE5Y7c$dXk~gE@@mS_00vKEAp+ z(jPIE*ICBn7+1OU1=0ptTWNSPN$9p3hJt4k+}k6W-o+6Y-=vIT>?&V%7d~pA zi1TJLJw9F!edXLf>fypv1th7R+k?2(e`y4hHr`1rV=WY;BCz&{Jrq>xUTR7UMt$@l zM+{myj^FweYu+IEAv;>#IzwMEr`8ypTZx4wj~6T1L9uhRq-E z4C44u&;uj`5smmM;>Q-C*4kgTF44l z5sK9I#A#UYLcEAa&%K5iV+!l^^_2_TKlh)u9v=vtUT`Px?dafvRs{>C%&s$IkUR*(6$L$dj?EMOAEMKsvOEg_b>r`p&-BrG;(;MUQ$n>@LFNel` z!o0h0OM^@oL57il7`?)Qzy1&-C?R9eg0o}_sF)sjzkQESUg(rNm}i6M9*?y#o> z{fpIh7JNk2x%J_Noz#TG7SyZQ%famwWd-M)jkeIa)DRtFUoS1&ZeLmX$O2xaO&TF$ zeYOo+N{@8h0s$8IXz!e!`Q*L2a>^##7;SIbX(<*0YNy{AC43wbnfa*ki zhkS?o&wlbY5rNJY4_JhA`&6Wx7TVSW;YJ@(n@d4F$iL8$gDnYPzc%)yrsvG96jR2_ z;FYK^q0|8xpTWD6(*wRUMz-;_D+)V&8YfUbi%A(1gpYR3*3<11;jqfwC&2OpWg-*a zs<|F$@Pw~#&1LrEK1G(M1CMH%oQG5-6I~o9}n=Ez*~>#+xHlV-vN#zhCMM1n-2Pl5qHq z_Bb^=of6~Lb?2hHEJ79m%VeV*rGKh ze?{oef2(Oo_#f=OcUV(t_bxo6qbMpkAc9mIAiXKQ=qM^hQ0Xn9D82U@L`0OTBE1R% z(h_>;y+}(a(t8I31PCnBU0*+QVXJ|g~Z|1i@)Q;7G=-h(SdJ5aPjyitCX_2PNy|dM> z7OyjhNj=_>nyAH7xlQ7kK<3#amQROh7?m?=D-*q!!{6mi1t`qK-w91P8*AxoB2MP_ zn{#_zUPwg*44T0Rc?Cj@)9``#Z(6dy9>Iau^SWGn_jXH{KRu)d< zw+8i8n9<9JM3b1xe=_#w_gZm7H;GWX6?Rx`uZ)T%cw1u&^`_SPt1Dmi>2P`OTVyr3 z&0BYAhY6#l)dbBGe~o0z#E1WV7xBw$X*s>pZ;Lz&+3^pZ&9du`>bT zS*oGyIH|t)?v!vDZ&OfoG`QR+i?M=odA;4lmbF=gpib1=PMkbs>!<~(}yYKkLssPF?GxH_O6)c z%zNz?N~L&gr)>)S4%zys84F%MM^q;${H9mxCHG;us+QtvcK>d+<5*ZHsb!sNIMCy( z42*bFOMVLWwe+6JT+6W;PaGcHOf7_Hf9MtBJ%{YG;9#)enO1C)+SkA|PSg&L7CQUJ2D9ds z!Hk21ik^4{N?zSS3+BO{t(P(c*nRgad(8JJIe$>ge&acBXZtPzCi4AYyU1_7MA21! zV86KBx9i_H$Z{KMH~W^Z3hTRAB>wOt@!0<7Ea;0$f2mIM?dcG`OGK;)L#mZCi@QfT z)uNJg1~hIrY_kW(w6@bcczF7i4QkkG#fK~{b-EB~yMKzWQCT^5z!;~Zv_k8Ft<*lL ziSTgz{FcDAKj+=YWNQ_~0?1Hm9>$F3sFqZegp2RaZvSqY#_|g@skur=jSMWaI42R- z7ii|0>SuY9hczjpDs-jX#+G~L(-fhQ~6YBP8k0dgfZFiUQ+-ukujg%@~FpNxJmLSzIFS7%PT}vbGjRqFYYGK`l zdeqTpnB81q(tq2-c`IgXmpQMFTyNcA%;n(IfW7VBoBKND2zhj`#TR7c^~hz&V|#Qk zZzI1^Vmf>b(;;GgPGY6R-o3=}UOKxp$0KZMjESyP-$UU(?M5xSf~(O>Nr*9OTF8bu z(NTDE??>m0xi( zReT%kT0dy$pUpp5ADv)NZ{LFyPAegsa*&nLF%f5r=_?#ZuG!CTtgd?9X`<0kx`&Z_ z#|&zk0Cw|*Q0aktyN96l7W(nQ=;h~>n0T3ut~(AXxT$a%kAi8=?;bUJQe&cU9$#*= zU;oz(z?Z&$mELtbzH)w!N^Sk1Vt)>DEgmyMnbMONX2G~$*~`UTecEV!7wsTy>JazZ z#ahjAd5gHWg1K#(uoa6RleU7eOITaG6cyS~nQZAwwUsZI5k_=u&gnWX&+KYIOU)Vu zKH0bX-?oWuiWsg$+!W|F8dD~WSD8s#b*S))rG2pC{W(XAz`kDseGsdge4{{k5HCZ> z9g|(A#w_6@T1ziiB*X47ccts?YttjnHjl^TY0&rVVOR8o6LhE4!Dw1(j14Bzsz1S% zQ%?ctms)4)7s!fpM4$f_2U?b;nCh9SV4dIs$9sfLzQfv9U~@1dQoji204saVIS(n! z6aD60EP70u7(CLJq25lWS<4oiL0SFUob3)dQ`|ust{w2+6R2^1oA6=3tD6caEYNFn z=+8D~&RPh=b*Xf^HpkayOJX z8LHgW)f}XZnI#AGJ98j+cOf*M_R3e!j*ujQp={3U44wKPxQDg_w4V;t8Yq!tAnnsMSaW1M_ zw{JX+{*Bj;6(sx$y~LqmKA~G3frIGK2)G^el8Lpm6Nbg; zjxOmfVdKHqcE<)@D~MR=0G=!u$1*QTeSljQ=z!~q-Y=sb=Pe&QD>5pXV(VU2)#pIU z6vwY`Y4IBvt_ayJN61h+$W_>lzF2;U^xpS)=(&sueZSfLTTX)ACcwO!7BnW#?e7WQ zC(0W+v#u^LiOl6K<{d zf>BOCBhN8(N+92mXcZx~S0(Tva-)IWPxm)B?t*qh{Lt_Hg@`v>-|pVS%DKuuyR+Hm zQdmE`0z~N};=)jo1F`dzNY$D0Wohs6z(LKo--j?s0!P5fuDOaA0pC?9u2F+LuKp5- z8okJbol;{dlstOP1XLY{$t?WWCB z?tYfCo0LVQZT68Dn4Ahl1q!n=LYy{F3LP%f%D}5QL=7ELIqg2MzOVkaR8nI5)5b&5F^f4OETSI9ISGB#gyJ% z^fu`Aa_pz9&8+?klj(|usrjiIUuLB`p1t|s>5G^?NO#hZ2dBqtXXfnr-S!w&+&RI= ztsY$_!3^3JDSIoUY{KK&Cho9~B18zVyns&YOYmqb__>1MF{r4+#JgD13|o$JLGMYk zGzUckuS>70G6jqtvzDF?KgYiBdR;m#Lq+BVjRyT|KK6sKVYjO!>zrrhh|8NLajxLX z-_y*093mk(tXB>e8u%K}N(@n;HTAfg1JqTEF$*S>pVRtq5IT{)7(H})qBO6P=vu~- z+2ilI1Avj^G!+@oq3{08v*`%YsrI>Dr%$3Xc71sK9F57rbYmgJYVvmq(NexMCTe)m ztV7+|-5jGm$Z}ogE2Gou%rPpEnX1>>>WpG)hs={iXqZQn1J5-pXF?|ye%2e0OIuv~ z%53xjl*`bcbU((_Wzn0hIkNhp-bK?Qqm>Gk?UJ?U%RS}8&U-pjD2Z`-j1^5j?m?DY z;%05Gre&TI9vIIU#UHQ3^M=e7W{0J>27>5H3~)?h1p?9=oeTn|J?j=i=VpR4JQ~*9 zTv|dS3CcR4p((9fMpA@WA>$)GHDU(d0Pe0e^?2F1gu5eQt$n@?;@;V$(Bw(I zk=|TrkamAryA}0VaB0v)ImpI)JFlH4hBizuyHCfZv}CF^qeBTa8U@qRZ}zf>Klq`` zNL)0pTY)mY#+^6!dz7wme*(}%2%9RW*s@%_QN?lZeKmeA(r8`}YoYc*9bK{%hun<5 z-(qqX6rx7aY2^NNR7yXGR2%}0orhj{!C(VgQNX!+I(?G|SOh%yPRmt5%8!uke?w)amngY6m>%Oqx@?(d+c}K-7jqS6G;_cqx24((Z&!beEdVP=g?osh?IkuUb zhtcU#qUcg*(NtsPSSX2s*>J3a0hMTa8EMjN;2#>op)&W@DvYt6&HwTysZl~6{?z_{ zU`bi3$Y|ekknd!6~j&PpwoX@EQZk5Jv4{oHwV2zL7 zbeRP*SWR6^&?@o_N(wu;Gk1Xpn-FakH+qd*jEL}74nTPAzqSm+YcucH6z8oqalP-i zw6Mljn#2wm;@rwh_gA)+oAR2AWb%rKiZ%**`T|(uOCa<%4@D=R-I>}LSL75||8RyX z>l>-%SHEZheJ)09q!Z(ri!yGg$e&Nlikc5*w5og+y_?27YRc)*4`+QCVQKWjTOx^Bm z6IaDI-h#Y$V{>yv$-7ceVn3CA?xq2d@fzr}T-u-+SH*U|QU>eu@N!}*U0L(K*{#7_ zBh4&{zaBn%mi=YFMMyq6>Nbq|@w8%R)#mcvbesc3e&2ZjR$8)Dt<#*}#+$&bK>pPq zi5q&X91)_`0sK!L9#l5K0X5?7+^*g3VK7o>vFL&O-B8npJ*KkBRu5;1K zK!6M7`rM;E+sY*zT)C~yGyVt_7iyHpt5Miju~gbdESEdU(pSDPk`k&E>Vb`=4`Z)p z062-+BD;&HPY2-vV=wrvo@8pGAR6O;$sc5)2t>ulQt`9jb7yCEcXbb9lDGu%vNGO4 zEk8%%jirp5nKXD$hI?23UYTOB>nf(I7y)mW+XtG+1AD*8p8m}~9bWg%n8;N(Ob+7x zJh|UYLY0H5-9_a|T_ETK=K*uIgwb@}D$j~^#MQgb%I?I{%AVrXmsEb#$XVw@BfJIF z`s)yRszabQ{pz*LO>?t&kw(Y5)bO2K7v`JR)0G#&nOZK*x;%%9XHZFp(G{4W6>P;f z(~T_39849~9=S-z0^9LIchTl{o4RjgNcruRIEw8t4~OJo!44UR&qWb$PDHMVN684! zR*vZ23q5Cp3Sj1Pd|A{F5hgiog9~&on%d_>aIiI522crrBWM5ptIID#ShkHliMUb2 z<`HXizlIN%DSgs6^OrxX!JWMTGtVwrq_TlQDi-Ke%_sCv&*=bKo#2dOFQ8!7B@ivS zUZ?Zxldzn&0^kq%AzRlh?u!yfZ{BGfM`w<%H2T>M<930_V0OrK5z5cMyeVbqH{v0Q zclh0f8yiI-wz9^Qd_WtUU=XP*E>>lKea*TO2zo~r-5kGp8{Jv`W(MOWz16kNUXB#N zIkXBs+<f z^5)bo&iSt8J1yd>49bm-I6rKpZPC3n5~jQaoG?X}#GL|k6*W{7mu74=!J?i^6m zXP%JVtv%jH^)Vm!X^76xK?8D)_4z3qFOz8PP^~fsl?xGD719X`FX(fLIXuESvlUR- zAe(??Vp;=AjHM&E@oaTPBPPM#zIvyH1Cu_lBmZP!yjmfMq5RGeyr_;uAXd4p(sr}) z1V;;B;Rq`8zH3<~*At?}n%@1HEf&I(!s0HI)1UQ9?W3`E7i;SG!Su``6ew%o8+#tWu>Z_M7sNmE2jOz9EmAr>+ zVv=&^P;cL<(cM-674w$nA1-=`c)&L#T0F2zObWb%Vk~{gYN1T6btkDg(;FVll`*lH zCFn2r#r@^F2_MTLp?b~`R`1XI+w%<%6-1ON&|6u(+o?+c+7f?$U zTYU8&nb8r$I4^-=Nc6WT_@fn0S_ho6m(js3T7NfY?qBA&OiUtDrBmq|9YzZk6r&K$b#+PaHU@1nd($!<#?x?6-QLvM zKegC-MsZBpB(X?~yV|qIT0M15hOo*YU^!ksUEytgb{Li~G5JlE87l199X}91zcq?f z4(#W=7h~#BL(cGMo-kwq4U*bs?wz|Uf&C<9U16|Ss3+#TRAN@|e0HcH!hK`m?cUO` zVDXqaq+73a656)BfJZwd22*>h#tlSS=^)&csTdIzhIg~eKED}kOPwu1C(zkcUE_kS z?h_aD@Yk@5M|7^JmPum-u!90&dNvvmw-(W<)uPth#1RMVobv}JCIDp~Y0=n<$T!%6v%%#wZUl~r7U5fXO zATQdfQjMx6h0=<4Lv)ZD!i}#X+Di%-ifPoSs&FssG2YUBD7~^r*?6uxR@YrK{`&!T zmWt$gYq?c^@4Nj0x9K6dhaE1}<;EmCH;JKsy=0D4wDzyTp%TxyjN#R9j-upbR%l~w z#x6x*$5@fL-ixK0G6A#>Ex{>wlrgKJMb+!GkUR%#_QYNd>{$gD3}eB3d$5ari%Cm} z7cIf!AuwDO)NeyV1tb`6Nl0)X!@)MT)xj>(Vg>6*Rbb-92(kjT_ulZc67Nst%M}V8 zbCK8I{DRvz>JK_4qI)4i2X01I2i#;#(@oXqT0&BRPCKx2A1HHxZeoAFQe`f^cu6jw zac?I`bT?{kIYgm;?vUKn1~Bb}_U<{hJ$@mpm_V@R?IH~7PW1%M1->Oat0O8Hk&{<`p&Mao;lR+V+x@ ztYYkzowmkzVL553=@r0?52Fr$)9)sZ|48|(87Dk{=VEnI?FhRf)6+ZD35po<6NxoJ zB3tdtV`Z+yrsk0NUxB-GxXynfSuZX9u5B?hUm3}rv z-Eo+H*VS`z@ZRdIhH=wF1*edo50^D>4d0ELe;$`G=n${IWnbp43sm*83RY)bN_JDe*usbxDj&hT#xThgWHNIU#@}4-2D= zkeH?W?)eLFiU0EGzYm`0evIT6I6^e_A%!JC0_$l3^Ph6ZX-$yq2x=GXy}TS z(F68v2_%v4R=QGPL(sVbL&A>8G{W0svgcHL?+-%lC!YY)$d`sR>L0y}Z}0wxo8#E& z|8iM=w5q>fnFh=^%6@T={ky62hhh4M=;OSDd$H|@#TMAHzEfIjoRIQ{n0lizIXF~e!vfR zLGF{a6#xFG5dL~izdor?(-|-`DhhXz^B*kk{ny|CL%@LJUvK@tzMo(Y@JH+HV?TsrsbtGKYs zH*VE&Fw4JXWMvk6aYyOmd9CZ0(|s?Eh+ONu>7tBYYF}v|TUr@Lr;MuU>FI5%J7Jdu zs(F52#w4L5zfd^Om6-mMK5Zf5NlmSFUg?W}&<{AKfoq@`X>I2TI6%p|Wb(NI5kF5!tt@G`Gk!p%g_p0C zt$tEbrlAS%e{vnVHe#NYQwJQhRBW-9`Kv4C*ym&{p8P@d*D`&WjROgjl-|d` z3q=NOmw|_~FP)YVvmD6H-RM^EUrdYT1uh$5pe898%zS)3YOV=Aw{7i&lC5Oxgl~Hy zoRW@+&`Y}7YI-ae)n^x==-J|I>(j6I?#UWE3lv{c#4< z!Sf%V9L&#B){A4tV_Oucst2659{$v&E0m zPEPnzQrJNY8?Wa(pru5>lN^^#=W=Ui_ORSp3-#8Oo2QgMAmHq;_vzSF(m-JNS=;(k zBF_p?;#|<|H$)8dVCct1b^128eYc236VE8s@1T4amu?pW|GpDT9ZBwy!y98Uc zS7!qR+~MHd)Kl8a5AV~ zudTs!<7n4pnrY@{$q+9Xmv;2EqpFPpA+@S_o};IlCnigZQc#5bHycKwQfJu`J=ZU5 z4K@pd;ejjRj$Jp(=RB{*n59JrSf7(7?o6+uB(QINZ`qVD7uyb*rPD+(K%;X!(d=Fe zEp(0IQ+xWmi|NXlSwqd+o{nDooBj1dXh~|~dStcgoT1vJ__=0A2SrV%UbT71(J792^eeThqRy$9`xH~3i z)=}bf_Q(~d`xp~BZYtl8&ncK^|?|rV5^jAOZKEGy9f80LX&aABfhjt_$ z?fB(IvxSHF?Yt29(3!RwBzQ*g20SoPZO<#KrA|v=KBR<@t0;**?k!CY+7WsLk{pM) z8VU!`lAHd!xpVY1fbOTRMh40FX#4!K`SelQ@X!ie)D^_OKYlJ2(KbvmLqj(1iR)0j zuW|B<7=9)U6Vuq+cRPsg0aB4Tvy2>PE*^8ofK4$PUsL-&83Z!-Qt5mG*ydOZAK#pf zY?@m%22-seCUJJRn>g9lf0imbM8;ROGnKoL9H_20u6EmX>_k*}D~`ydNm#(8TzIp=jvZNeulM>Gy4 z!N*;>(JhW1H%KT&Lf5@8Uf8{P!DRm8GvF>TV17V=S~K%)n5QYL}LJNlAdFx)e? zd$V7HStzZrdo#wO?^hAcsyruJ0y3#T z*oJI9&9qR@JnQo}(rh^&oY5D0b(m~g-qudG#JCuk5Lw%Wb)2tt--eHSZI9m64d<%f zyll(gN275l=tgo&U;iO8okcCa7o0~|vh!OxkE=XRq+H-2XS6haTp`~GWx7fw8dW_v z;($KY#$BMu=HW?3(bUT}t!v?&MHBa_)sD{{!MYrT?zd}ZioATY@=3| z_<}RzR}`f-KV`%%O$szKs)*b#)pMvyP$~8sR6WV8>pb|lAi6THRiR1sZ}O7}5Q-PGi-*kRUa!MISvU!Ps=~&1v`|T8)G@ju>V;3vBF~u7uod#2 zNqDHvGHD^kY!^D;O>Xu>(S?`B50YzYE#ReW?Go6EXpG?$xEoZv|Fu5NOQ5cb8w}(c z%-RJ$-c^{G=uwtoBGuV})XZfcGUj8-Qk$wf;6ZN2?J4k&=Te@}Sua#*BNp#_Te2nCF= z)@-mekT-k22&5>{(V+IV*+?k!)__r{BE*Jm9qp(LB1zzO9u_a$Sh0t#mH`unJq(gx zvT>4yQk)aKtSC17c1^WceS@*_H(42(H-S)q4o)X_?4V)|o}a6e#I>ssq4rfDl(1#D zn!i6N?1$UMN1c45t)@2GIOa;b^zfs}F>lWS!7R7uiVt_YiO(kA`O8?##dDoX6dv(x zE9c4Jg0@^dq1>16JcnT(H}moBy~GcYA}#zW9j-a(oC-~@n%>PlhxJ;9j-ziIo_&F|- zWsz$9Jx!NUr=E^>MiF|^fl+ZG5iV8=$<>Bxx_#TSGQ6h-zDltnUVjLu-%kQ{SNb`8IhaNb&Oe(&yJ z9tliT?=Rbg+qc|!P`Nh3axS7*cP0-iw*uu-cs)ng|jAzOwe)2Qvh0M&Kp9ej3b zc-B$>L6gMHLigTV;e?IafxJY2@9@tO+avRJ!6{>MiJ5MmBLX--8ucA@j-M7Wy(xxL z-sM~2wmZKn`@c5fr8nM3or%Vvr4CB@*RwSQ-S7=vcTfxw5c4MfWyi1?Wj~Se9Z@iT z*}MKhHPNNFv?{7gabg0bd^+P;t71iw=3oX53c43Qbc@SLz7*tkz4`EBE_g{Y|COXH zOu!+_7%e+~c;B`8IEM%uYG0J|nA^N*1z&~J$ahpWSAsln`2nCQfl!-DwWqZCbnA>fd1 zZtc-tuFGeSJb7gOQ2xvj?_g|At-6OZ&8tk&h5VKz4(Oz2lBW+(lME78`1 z`PH{~SX@R)ZI9%(3${H%StCcC4L*H%5M41Q-=MZ;2wm6F$l_>9Dj}g+Z!Lql~5Us{%#o}O*u@c4+*ESxc>X;e}Y{#JYv-Kv(0uM~O6CQbkBCqk3KCEIOayCMT zS1w{(_UC3fALkA{{192#9@Mt>$Se(8m}7qEjTiw}M^8)qe9_>xXIV!MU5X~O>Yf1N ziY@=qt;V0`31F5)x?f3*rTZ|LIas$fY?FxMWElqt-VeX{)Fi>p_yta?nx@F%d?jX` zx%=8Y;p#D^2EhOh@mb~%dR=RS+AVfZN)#w*k-(n?VqaNwBFUR3K66IT zp|_L2M=?yJ8}CcD;w{uJa!{D6c8ct=lAh<W8(_5eKL~MpZr>_d0#B>!E`~U&BbdRy)wI}5`kHy)XLi_yCr#G- zgRfi)ed{sj3d$Ad4_i(h>G*|0dbQ@T0eCSvBl9`PF>;}H{+q1vj1524g32KyXS}tj zmL}*OqAJ~@HGH6&9V%; zOt%f9qS_ovl^eIxd?{3tic}31_b^8&ijz_89r7=C+Lf+$^?RQ=e>6G)v>yhcQd=L- z?6*OQR1{Jhor;h*ru}g?pbn|OawKTwb=_uQ?O5vda*vx1j&(!NGYka)a4*^I&nvJe97zU)tP}+tyj$Fuey~TFV2%RUkSlGG@Q(WZ?oTym7Yk{tcy4HWc92I=w6ndS;P=YzqN z#;e?*9gSZ9-?RXTf+jcW!$0AM<+*asKwKyNJe}D_K|xzy7f@id&F%oJx1UhLfbc#H)+npa!Q`pX*f z3(tU#@T3qrZomGxzz5G3*2wI_0ujn}SVzTt&$4AN=n8RG0dC;#i7PJEC)nd1A68`N zH^S~+>s1YRlyu!1G^r1TZKNndgkJg(;1*4CT7Q$akD*@Z@$pT;GBLBo@jG8AuiQfo ztk(J``n@E(cRDTF`3(SaPz3iUwTX!j3=t=K?j@dLB+P`N>!U)YPb7Lv^D0VpG#I>* ztAg{D;)ZR!s9+_Z^+3HJH*d4?*K^K*M5jGW3iJio42u%D0_KP0^4I>->xE4&yPp*= z+rQaZQ@g`@08m;=ri9D5mkTJbJeliZK~;33qF_{4H+gttmL?2zeFm)@SsJKp8p}x0 zLW@MoG16AOQo~nVpbn+yfvWPtC50UqIys-yiRNz&S!m4mo8K(cPd`F&c2lAl34VtI zdgd05#wT6SJ}Y1sj&m_Cdd$q<0y$py9Y6f7Mq%Xvac}ZDgY~gy7H`iN(|rLsVTZ_+ zCD$5qQQ{a?CoU^Zr+lT`m!_ktDqgS40zknBZ-}-8bcqMsD+#z~*{Jg{YkJ!r$k-m* zCcDP6==J05ai^64s9zHB8Y;+wsnsFM; ztF3CsJ6=4_81(b={_$0LI=4Qq#h%$|?b;^{){Y*oD|ocvETYUadUaW=isIH?r7;ie zL7l-J$zP2Vt@3l{nQ{JN^Ks&0;e!AhCpfom*FRM77E-b#;Ql$o7LaMr29ODsvcdu%tpJ9Q$|%<9Z&EuF33|}>qF_{MyDXG7 zV7ISl{>lLaK$`8kF9qo*m;6Q#Md86mvyVJQ8h^?%K1>R=?ue3VK*0g>(Ab-o4f`CR zsf*lz;aZ$B0MAP9GGcd!jgM{U+I%cn!5ak_L^Vup_zh7t-qhhXG1_`gD$!aytLaK# zw2ex;0;ujaGl~04CI*$8eSztM!=wbfP97fJ{xJCiDmnZ(uD@4-a>hkZigx~g;Ftca zEG|S}2dQJk7^5Zsvo7wD`@wn}%X4tjMIlSRnT8iI9EyqVmtNZ# z3H=NRb9*_>N3UfCJA$%0W^r#034FYA^yv)Jlm8ybFBNlu4CF%0i7mbldtU2H7I_ef z;7VihCal%bOs+rv9Yz#A{QxRKg)K;_iFUstNQQa^a7>vBlmKDd0v=ssT^Tg5@->#MxGZ0nF*kM+ z1%+Swc@LiT^wo_&$HZStm)F~V*|nUQ*u|jeC`6OQpG;NljUB5NTWjGxd_Yg5Yv*Ss zf8$7xe?~gJ>MqsJt?;%lZ3q}Ut}DyYQnA_BU&rhr_4;!Ca~WpFtx@)J_Xm>rgW@tS zaP)vZ+cGNGBZ})~8EN6Z3 zsTYSW|LDrh4j`F1PO>SYT#B$WfECH5*0>ck3|N4S zmY(2lo@!~sG&2m+NlUK=RIiBs(aDMzJ`%DzCqDwBjVV)U*4NDZ2!*rFY(D!1r^v6U*sy4zg0jS#wr{|)iVj&Z`qLFATI!7=`{+(Jxab)g|6Qnw zIRYX;|NRwhH@*w*^UKP0J?ILk_PIIlNwi6I%p;M)aWAA;op~0loRdE{EAUPz?2={m z^rdjaJB-50nqHfhs|`^CiGH)*wjQa9yGb8p@HMs5q46>&SrYVatOoKm`GMk4pxgTk zb;E^I?+6D_=I4!P_il^v?Ry7WSpVgN5qQ-Ypt3TB`sj`t1rQVAUyiW>mUY#nTG zxqnvgbI#rV*+wYM0*HnU`2YYIZoSBwW*wHL)jI<=bE3TCY9$i z37MwIF?Wj>XgiqFrxT2dj7s8*@4F?OHu+6ElP+h?5m)OeDNW*?)H`sp?BXC^kN(tr zy?A4*mW)MpHWl43VclHPPtKUVY1wFE3#!VB`j?g0o${m;w$yyXjU@>qr!_e46%#6g z@OYOy?G|4!3P0RlqcGX}frnA-aOLcB3|Mk2i~lUS1&hWUp%(#D!#L6jKDzsY%VZ8I zikRkn*V5PPRZgGcvjJCVU;5EGn(q@Er%fxbCsHsny3Hl0K1p6=c<8p?;!@vI?IAd_ z7fOkVs3yEg1qJV(7E&=MEL4)9KHxs=&zY_)ZC0B*V(-hf=(_qji^Z>~4^L7v2-8@u z=P%h>;UB^&83{csv>Zo5+F$8*FYgNvk1;X3?@U`mWvX~BuiEk#WBI)C3ZfgGH_Jyq z5dj1RQ$20l1)3d)-tpfSc;GghuQ;di@+O7YWlQk=47K!i zANrz0uQPcSA2&St1f&7h2AXC1QFp2t4Gi;_-MsnqgCR@z^uc0!;&Y&+iGyyK`6kTM1}x@?*F1S@_%xgRn^`Yu+tsJI zh+_ay-%C?;p}NDkcDH0HK%~rJ(X}!SY_ow*FfEo{5(saj<^?2|7Y*bsWin_SE+1Vy z#UfpiIi~GHTfH}mt)mAc6CUG1eoXY*(sFy;LHC~KaKIQ4TYzxD_l%@*=z^N8w&@(+ z6?VQ_+iCkf%Gnk0Md45>ED(V*wZ#g--)ndbc08rs<607n)6%-MJ!FA6jU8Q3Ka&mE zqG7)WDYvg_%eJ*P)}(^59;umC+PJDrecqHWOUgece$alW-gI!3q@+aOpBa8T<5Cp5 zKVsj;Bh>giej}-3j1f>6Ua{OTx!mD>W-^=5dKKsu!*pgbch}2@XoDYAqvF3%*-J)GIsuB)m2+|Gl=JZgkl%>y zG>6$9py61oE7qDW53W{$wdModO}#r6iF%%P68OLs<7^Um!x(&;=hj>|;QWjaks0wD z!+JYbvJ0aZH7Th;jcpz-b`LU)C+P*3LPReHF^UN?M`*B;_PDmR(gC!RCUCmk{EZx& z94#f_i!@0Dw~(9M6rfHh1XlSfdw22Syef_(EaOhH`)}|3O&n(N%Mi0@2~MfNF9*2` zNh=cAu^ybYX`5kvd6SZvs!tmuLGlui%5!VhNO%jEeD+n(q1;{babCnn5lptqSsIS{ z{b?4PXH3rSmmP=;m*#nLRyLLuA&Mh*&EEBVFs(|%QC3%fZo69`oRZt!hL*69nsDfvH*u6b^8)axi@cixKH?y)fM(A z>2P@LEhGH_OIQ{Mn|jGE&!q-qYH;t8rS&5@0X%tGt_plD396qLb9_A|VvaNF+BMSD zN1G&Q^?nki1p_FHXa^$+9Qs~+;ElTn+ujGXl(9nq%aZ_T_2xkduByjGI z?jkR|P(r%c(*xAy=B@vPiQ|O6;y6eh2E~K<-V+z$!V;IgUK~6bZ7=X3D;^o7Ev+bY z&$%($^Be5ff0rq~z1zD#Ij1w$F>_#!7OPi=36eV6bsyh7Fa~_UwtlJg8le4!PeSpi zObd^gyw99H{^!!rTLOJjO~0<{ z(y}(rnZ*4XBDFOjp9fYF=)hod@UvV{{?&%U7#qSj4E0BL2G$+Y27xXS`rztEAT7-v zCQC8eXtx1@O zuYcSu@OkB3?a|1;)y(U)*UVMT{Lo^8>ZD>H1w;`+x1y(JBuAL-_Na?VD+Pe^>K?*Wx2^%H zGg70i?c{I3EFikG(WC4S#_5PL0=n2QOCgPy@8s#SwI+solFY)ZzFpFz&d42;l6QDh zJ$x8!y?VgfKsPNLFxpZpUaYpZ!1=&i?VEDLJ&WeaIbSRcaNO?$BQ)F;$UXz95fI;W zzJpT|Ii^{?>B;#ys5Y|2Yt*6xAp!yWBxw<>zY(M>)7Pjup;)!$tBuwUF+0WIlN^}=?1L8MM>UW#_5 z1h>B$sAobMYq>sJH&Hqr>Rn+QULI?sD@{mIZI<4X(&}*>e5c|!9$%q4NAPEX(Zh15 zn4&Afly&*Jk)FLjh)NRJ|&%PbJj+}YwIicVFmEci~Im3Ykc`MKs41)3Ff_q*HOS~*R?3k82 zR#p&E^-;>HWVyJ%j&IxZqL`Y)xW-{J@3lbaGoTixW2 z#eQL3K=xM$+R;(>i3vbnG69=Xxuk;YY`8|<>pRR^?h$Y<#L=y3mV=Va_Ht|$!&x26 zyi7uJQubGzP?%|{EJy(=NiJ~em}Jrk87p$!cdJ!|eZCjD6wfHsF5DtLW9({-A`y5yZPzZ^&@;tTA|V6c0mLBoq*qlpdY6X+JM zVJmRP>qZxkYBs9X(~pYt0EZ(Z>Hf|N9{^?X7_FY;gBRF{lEx=8}Y z9DS2};|H)RS1~W}SDx+QW;449l zL&sOw5uh)(8;~^E>@`_bN6PGP1m?EqBhNx&AsyIW4QX;^863=YcX7Ke3lYL`Wa4odiT{cV|Z@h#)7^|c1r%B;g~AYbEFhr<%N5uM2HRkQj7D+w3S$Huf5 z$pIzEw&R-dF@L7AyAR(ldI2hzLMHK=rH=WXuB|Z-qk0R37h_Wpo?B6T@s`2vBHQut z)*SkQageCn0D_=5j(6%i*#-O^EN8XeyK}>YTD{@ciF=bUEhU zm(JN#ZmMhAx3HcFEbcBag^{cx2J`VQsF6LAIbsKN=HbBfsdt2eZFY)CBK=6}Gr;9? z0Pm=i*|9&y)r!f%a=ZY8-Q)~7td|DhwljKXV(>+~W36^rE+1cDz){%&`co|U>h|V< z<9QAHNx*5}hfy{<0)rz6S^ER`y^=$iT!Z@GPQsX>I%Cp+c$_an$XL5<(I zVa}3dOg7j9uDyxGlDnF&ljq9dNl6XYk1^_674?GYhX;F^W6j}CPGg)nxMe3{VXEI-Zlu49b23|+CtsPkZX88GP=fVPW{zujU{mnPeqpHI*vw3$?` zRfpCGjmL3^=>Y=stT?{mNWFa1fQogqr*r+bj4+X z{4kT~fEnmUpKJQB?pc38@mpR=&FAo_gf&Pl=qnal_JFc1d7 zvYfr46jzaHsc}xA(;8S;7Be+_@k-z=p9Ld=%?MQXuFb*vP)oyg1wO0rGq`=4biwlkh4MZi$(NAmkag;EUp-j){%&+S} zC$BMVGvkmQQ$tO7c-Y@4pW}gu_{tigH;Bd;4L}71bE-*i(YuW{*WgXpuQWQ zCVf=;Z#aJ)ldc0*t*MGn!Z9;EnQsTVasoRfQUQ87QCKAnGNI2+ zcbHmaK);wD7#YK#8nBV)!8IV~RJ1o2Qf*Og2tSV%?F)*6Ew`e@(UQ1D+s})9kJr0j z#=FGu5M1{M&5K3!w!nbEV|l@(o~~rGc)L5DJQVQ_|HU^(R+Q#?+B|B~PukxaMtoM6 zy>Z@`jFMt|#6ekYPy_09jk}t#9!^NU?$g?Gl#(7eiqvU_9f9r2|8ayCo1(Cm@ak1B zkk-tCm)3wTM`yS?|5imQTI#iYV{e`Cuw{X&(&oFGTE2VQlY@$<)lMb_b3K|xf~eT3 zU<4sN`xBgGCH0n5+XY#klgyJQM_5~}>2PFpy1|(BtBr6#T3dvGHG5fV| zf8Xtyd)w~0-;a5o=^t&Q1zPW^efHUV?X}jSrt!T}jI^oBCu&qB#HDgtA)EUBnoT=l zy8*Z4syqKe9}o|8J!!`l@45P2>iT8A6oC#W?a$5u>+lz-jBUpc(4JviUntAYpwI{cf_LAvncI}Hg>AuuD@wG_+y(iJqlUvJe zK=Wqnla)6W`?}U0g-+UhqGRLUX&_6(%Dy}kEMM`<7H1YUR2x>II~M8FXELtZJpRZ` zeS*O##wOQxebB|&yqG}TdYp%MDTp+UI;WZcaQKj<=wY6+VLu*%y201F_rhlQALO&U zFLG|x_-~$myG~5O9qkrpkE}S%|5I?Ni9qb=#dBNJzPemwq) z_j}|N)~~ulot#!suUAgmMJkb7WdOKZ4fg7L!1-w5`%7)V%)+uAMh1W1V7B`RnTqve zwl>A+Kgk_nxFt-xBUDA*F!Vgodmq6(|Fk>6eW$Wt(|Ok+tz44YwRJh>)hEKQZcF}> zKO#1Ch|%ozp?SsvC<>oKb1Cxi^2B$o3drC%^yhCp$x3yN%{eqeF69|oE3>2C+qdOT{Puyl zS*tVX0D9x%hF-Nu`hwxXNi&KY+s{sk!(cZNnLx`J3$eC1dLfCAt7J6DVGg*+JORO! z=O_jjkG}91`Ib#6KGk~iuTfsgPlMW!HX^v{ospG8(bG^s7=RZ4J=|iaRpc8?`OBj( zVnZc)Rb|Q@nm%Jee85w^<7HlK|vcfY@O0Mk#EWk>bbR_&kh{z-Yz zV7cABC;-g8*S+aO`|UiP(h>e=$J-Iktu=PY2AKD0DV2Bfe2@I|&;6@-`Geq!j{{k? ztFVQ5(UPLl6SuATyU}wAuK)LM`?wUm?cHrA1kS&>*Z%1lmfV0Kzv=nRA@KkF$p7r0 z>v*VE@}O^miut{eklLLG!zl{_pVkJ3M~B0)L0c?^fXV zi}QE(_}$|CKa@R|`l{X`8t_}^ugvKDU=9?+_|Hu=8$o=KLE`(QU^)6hK!>eC<^C8( zMP)V1g=G&BiRUc<(Z~9>~o5}qO0@&;rgtvq!mXwjE|31ZzsiAEmb)L{$Qz897?j~3fXcm*EGdS<> zj^+NcXlxu1(Df5V0SJI#M0kGJ=cbG8x5mQ6VM_W{5=~MF&w|^qu6>ZlklLk7V7zgG z8aP%##OW_UGj_t&f^`N{_S=Pe>C#AV?!wQf5v?XwUK77&Qv-Pok9h(YGTE;)UE;KC zeV$(p$}DC_V22#*?02{Xe zxLB@lWkZ`h8{eLy8!yfSqk{?o!dOwUf}2b2oQr~W0b?T${1iJBs_ZTvlq@fY3Gkcp z3hmA~GDAln_9)^o!Gpe5#0z9!RqWBSD7ujecc&VYjr=a{JqIV}D1cqBFSyvq$2p*d zAV(tsXq{gdb_$zVzFCsp&gGgXhBzV!F4VGc7WrcGxykeVnnMSr&;m^x{w)HoDWShB zO@CjQAupY8*$K=0O?Qi=digx2b%1N=>v^;VThy81hE)!qmY-DPvdRF#0>z zjaYIw(lD$pKT#(kRM#}y32TJMal5X|TnmRA41k95_?)a|kwR%slY1+R2jCI)*2@jv zRH(P-xj_9NSs@0`bGK7jwP_T0WF8fOP!Xmwzty107Z^a(6e+rgV#f_wuG!?{zv{vH91A-?tPR)8XhwlUfxq{ZFP9JvcAad%E+NZrcJxo zezH`T7Jq;R9) zh;QU#)`p^8@-P!?+p+RZ+$msAGKhv3X~naD;TTNnS}a2VyAS(CGSe9;c4tT#P@mk6 zZ{0>eqcd&F=jAQVS?GED(}Zz#!r({r$-`TLQXuuEi;b}|!V=B+D(@xbEK0IQ9kQx0 z?=6kIU`m$DhIDqhn*t^c-$01I7k0dJ_ibr=-^-*46RWKgdNn6~pFUZ7TJ=uObFh7} zlyUY}_uS%yv-5-gf9rbxj|AC!u0_GidkwXxCTq?#xf^ z!7~eYd%RoOn=;`bGAJXCDRkQCkoyS;FrpfNk79Qb!r=g$0)vZ)fzf%;5#G`%JA%xF z1Yv^CTl8F4hY3JVRuoonIyJHW%A>UnIjNLNt=2wW`svxKcSP3|pnW^4zOm8@-|ze) z&D2U6%|-16G=dTH z<`d=cmF{NJcusAco zJnqi2X0B)#gZ!;*xb9 zCp=IP<$PFOm}Pl~`PsFFEmbJv6#N-S=8fC!su<4i{&W9}7qQcOnGd=VEjYU#TDoe39s- zbw^XxO}92z4q`gP!vpFt*eU%_+)KT3O6W1xAI>BEzKR8X4P=cdZ@-`gtxW}>E;m0?#*^f%agAD z6@`;^3gt(4d#G$E7FK$ya777ZY1p(FS9g&I57nf1q6IXCB&JF_{PEP4K}1Jcjm5AH;#vah4X3mrE_rAfT-=AO1Ockc1wE>w$v(Ob|=JsHX#>TWGN z*$>!i4Y6?jYyRS-$%W%M)jjg`-$7j(hPE06*2qnjYwMs)7MV6r<=aQ|qVg&0h#QQk zo_-hF1ganv?s9%(C*(mn&@OVm2k}u@-Q2m>sSzd&UKjYn1ji9XX9s^JMqHu&N;l}CYhMk?88EM}eYMbqUSjW4_rqnBqH zX>6Jst2q&>R%X?(w|v z+4^G2sM0)gzi-2x6=i+kQQ#>zXhNU6tf5>&R3xc!od?a1S_y99F=RV6pf8=^VXllR zg1~c77vE*FIZRubs>!pfBn!AZp}d=rpp{3MY}y>EQEx%NfTj+X6TV-~jroSS;DoB` z2w}DPVzbenbQe6oIwtz@r>l#{3C`xXr&l=lWtW6pOgajOyA4Qho;30Iaivv^i|