diff --git a/README.md b/README.md index 2f8f182..1432519 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ The package provides a command-line interface with the following commands: Download and extract dependencies from a ZON file: ```bash -zig-fetch download examples/test.zon +uv run zig-fetch download examples/test.zon ``` This will download all dependencies specified in the ZON file to `~/.cache/zig/p` and extract them to directories named after their hash values. @@ -72,13 +72,7 @@ This will download all dependencies specified in the ZON file to `~/.cache/zig/p Convert a ZON file to JSON: ```bash -zig-fetch convert examples/test.zon -``` - -Or use the dedicated command: - -```bash -zon2json examples/test.zon +uv run zig-fetch convert examples/test.zon ``` Options: diff --git a/pyproject.toml b/pyproject.toml index 83adf1f..2426c02 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -13,8 +13,8 @@ dependencies = [ license = "WTFPL" [project.scripts] -zon2json = "zig_fetch_py.main:main" zig-fetch = "zig_fetch_py.__main__:main" +zon2json = "zig_fetch_py.__main__:zon2json" [build-system] requires = ["hatchling"] diff --git a/zig_fetch_py/__init__.py b/zig_fetch_py/__init__.py index 3742613..9bb7f12 100644 --- a/zig_fetch_py/__init__.py +++ b/zig_fetch_py/__init__.py @@ -3,3 +3,8 @@ zig-fetch-py - A tool to parse Zig Object Notation (ZON) files and convert them """ __version__ = "0.1.0" + +from zig_fetch_py.parser import parse_zon_file, zon_to_json +from zig_fetch_py.downloader import process_dependencies, get_cache_dir + +__all__ = ["parse_zon_file", "zon_to_json", "process_dependencies", "get_cache_dir"] diff --git a/zig_fetch_py/__main__.py b/zig_fetch_py/__main__.py index 8c4d3e0..c2242ce 100644 --- a/zig_fetch_py/__main__.py +++ b/zig_fetch_py/__main__.py @@ -4,6 +4,7 @@ Command-line interface for zig-fetch-py. import sys from pathlib import Path +from typing import Optional import click from loguru import logger @@ -24,6 +25,54 @@ def setup_logger(verbose: bool = False): logger.add(sys.stderr, level=log_level) +def convert_zon_to_json( + zon_file: Path, + output: Optional[Path] = None, + indent: int = 2, + empty_tuple_as_dict: bool = False, + verbose: bool = False, +): + """ + Convert a ZON file to JSON. + + Args: + zon_file: Path to the ZON file + output: Output file (default: stdout) + indent: Indentation for the JSON output + empty_tuple_as_dict: Parse empty tuples as empty dictionaries + verbose: Enable verbose logging + """ + # Set up logging + setup_logger(verbose) + + try: + # Read the ZON file + with open(zon_file, "r", encoding="utf-8") as f: + zon_content = f.read() + + # Convert to JSON + json_content = zon_to_json( + zon_content, indent=indent, empty_tuple_as_dict=empty_tuple_as_dict + ) + + # Output the JSON + if output: + with open(output, "w", encoding="utf-8") as f: + f.write(json_content) + logger.info(f"JSON written to {output}") + return json_content + else: + click.echo(json_content) + return json_content + + except FileNotFoundError: + logger.error(f"File not found: {zon_file}") + sys.exit(1) + except Exception as e: + logger.error(f"Error: {e}") + sys.exit(1) + + @click.group() @click.option("-v", "--verbose", is_flag=True, help="Enable verbose logging") @click.pass_context @@ -77,7 +126,7 @@ def download(ctx: click.Context, zon_file: Path): def convert( ctx: click.Context, zon_file: Path, - output: Path, + output: Optional[Path], indent: int, empty_tuple_as_dict: bool, ): @@ -86,34 +135,51 @@ def convert( ZON_FILE: Path to the ZON file to convert """ - try: - # Read the ZON file - with open(zon_file, "r") as f: - zon_content = f.read() + # Use the shared convert function + convert_zon_to_json( + zon_file=zon_file, + output=output, + indent=indent, + empty_tuple_as_dict=empty_tuple_as_dict, + verbose=ctx.obj.get("VERBOSE", False), + ) - # Convert to JSON - json_content = zon_to_json( - zon_content, indent=indent, empty_tuple_as_dict=empty_tuple_as_dict - ) - # Output the JSON - if output: - with open(output, "w") as f: - f.write(json_content) - logger.info(f"JSON written to {output}") - else: - click.echo(json_content) +@click.command() +@click.argument("zon_file", type=click.Path(exists=True, readable=True, path_type=Path)) +@click.option( + "-o", + "--output", + type=click.Path(writable=True, path_type=Path), + help="Output file (default: stdout)", +) +@click.option( + "-i", "--indent", type=int, default=2, help="Indentation for the JSON output" +) +@click.option( + "--empty-tuple-as-dict", + is_flag=True, + help="Parse empty tuples as empty dictionaries", +) +@click.option("-v", "--verbose", is_flag=True, help="Enable verbose logging") +def zon2json(zon_file, output, indent, empty_tuple_as_dict, verbose): + """ + Convert a ZON file to JSON. - except FileNotFoundError: - logger.error(f"File not found: {zon_file}") - sys.exit(1) - except Exception as e: - logger.error(f"Error: {e}") - sys.exit(1) + ZON_FILE: Path to the ZON file to convert + """ + # Use the shared convert function + convert_zon_to_json( + zon_file=zon_file, + output=output, + indent=indent, + empty_tuple_as_dict=empty_tuple_as_dict, + verbose=verbose, + ) def main(): - """Entry point for the CLI.""" + """Entry point for the zig-fetch CLI.""" cli() # pylint: disable=no-value-for-parameter diff --git a/zig_fetch_py/main.py b/zig_fetch_py/main.py deleted file mode 100644 index 7316285..0000000 --- a/zig_fetch_py/main.py +++ /dev/null @@ -1,79 +0,0 @@ -""" -Command-line interface for zon2json. -""" - -import sys -from pathlib import Path - -import click -from loguru import logger - -from zig_fetch_py.parser import zon_to_json - - -def setup_logger(verbose: bool = False): - """ - Set up the logger. - - Args: - verbose: Whether to enable verbose logging - """ - logger.remove() - log_level = "DEBUG" if verbose else "INFO" - logger.add(sys.stderr, level=log_level) - - -@click.command() -@click.argument("zon_file", type=click.Path(exists=True, readable=True, path_type=Path)) -@click.option( - "-o", - "--output", - type=click.Path(writable=True, path_type=Path), - help="Output file (default: stdout)", -) -@click.option( - "-i", "--indent", type=int, default=2, help="Indentation for the JSON output" -) -@click.option( - "--empty-tuple-as-dict", - is_flag=True, - help="Parse empty tuples as empty dictionaries", -) -@click.option("-v", "--verbose", is_flag=True, help="Enable verbose logging") -def main(zon_file, output, indent, empty_tuple_as_dict, verbose): - """ - Convert a ZON file to JSON. - - ZON_FILE: Path to the ZON file to convert - """ - # Set up logging - setup_logger(verbose) - - try: - # Read the ZON file - with open(zon_file, "r") as f: - zon_content = f.read() - - # Convert to JSON - json_content = zon_to_json( - zon_content, indent=indent, empty_tuple_as_dict=empty_tuple_as_dict - ) - - # Output the JSON - if output: - with open(output, "w") as f: - f.write(json_content) - logger.info(f"JSON written to {output}") - else: - click.echo(json_content) - - except FileNotFoundError: - logger.error(f"File not found: {zon_file}") - sys.exit(1) - except Exception as e: - logger.error(f"Error: {e}") - sys.exit(1) - - -if __name__ == "__main__": - main()