From 05c47003067a34891317711adf8f147a606d2e6d Mon Sep 17 00:00:00 2001 From: Sean Johnston Date: Fri, 16 Jan 2026 17:11:58 -0500 Subject: [PATCH] feat(cli): add option for a single output-dir and hide options Signed-off-by: Sean Johnston --- src/fromager/__main__.py | 54 ++++++++++++++++++++++++---------------- src/fromager/context.py | 5 ++++ tests/test_context.py | 45 +++++++++++++++++++++++++++++++++ 3 files changed, 83 insertions(+), 21 deletions(-) diff --git a/src/fromager/__main__.py b/src/fromager/__main__.py index 437fdae5..afb5fba6 100644 --- a/src/fromager/__main__.py +++ b/src/fromager/__main__.py @@ -65,30 +65,16 @@ type=clickext.ClickPath(), help="save error messages to a file", ) -@click.option( - "-o", - "--sdists-repo", - default=pathlib.Path("sdists-repo"), - type=clickext.ClickPath(), - help="location to manage source distributions", -) -@click.option( - "-w", - "--wheels-repo", - default=pathlib.Path("wheels-repo"), - type=clickext.ClickPath(), - help="location to manage wheel repository", -) @click.option( "--build-wheel-server-url", help="An optional URL for external web server for building wheels, to replace the built-in server. Must be configured to serve the path specified for --wheels-repo.", ) @click.option( - "-t", - "--work-dir", - default=pathlib.Path("work-dir"), + "-d", + "--output-dir", + default=None, type=clickext.ClickPath(), - help="location to manage working files, including builds and logs", + help="Location where sdists-repo, wheels-repo, and work-dir are created for logs, working files, source dists, and wheel repository", ) @click.option( "-p", @@ -143,6 +129,31 @@ help="Build sdist and wheen with network isolation (unshare -cn)", show_default=True, ) +# hidden in favor of -d, --output-dir +@click.option( + "-o", + "--sdists-repo", + type=clickext.ClickPath(), + default=pathlib.Path("sdists-repo"), + help="location to manage source distributions", + hidden=True, +) +@click.option( + "-w", + "--wheels-repo", + type=clickext.ClickPath(), + default=pathlib.Path("wheels-repo"), + help="location to manage wheel repository", + hidden=True, +) +@click.option( + "-t", + "--work-dir", + type=clickext.ClickPath(), + default=pathlib.Path("work-dir"), + help="location to manage working files, including builds and logs", + hidden=True, +) @click.pass_context def main( ctx: click.Context, @@ -151,10 +162,11 @@ def main( log_file: pathlib.Path, log_format: str, error_log_file: pathlib.Path, + output_dir: pathlib.Path, sdists_repo: pathlib.Path, wheels_repo: pathlib.Path, - build_wheel_server_url: str, work_dir: pathlib.Path, + build_wheel_server_url: str, patches_dir: pathlib.Path, settings_file: pathlib.Path, settings_dir: pathlib.Path, @@ -229,7 +241,6 @@ def main( if network_isolation and not SUPPORTS_NETWORK_ISOLATION: ctx.fail(f"network isolation is not available: {NETWORK_ISOLATION_ERROR}") - wkctx = context.WorkContext( active_settings=packagesettings.Settings.from_files( settings_file=settings_file, @@ -240,10 +251,11 @@ def main( ), constraints_file=constraints_file, patches_dir=patches_dir, + output_dir=output_dir, sdists_repo=sdists_repo, wheels_repo=wheels_repo, - wheel_server_url=build_wheel_server_url, work_dir=work_dir, + wheel_server_url=build_wheel_server_url, cleanup=cleanup, variant=variant, network_isolation=network_isolation, diff --git a/src/fromager/context.py b/src/fromager/context.py index 996971ea..016581a8 100644 --- a/src/fromager/context.py +++ b/src/fromager/context.py @@ -42,6 +42,7 @@ def __init__( work_dir: pathlib.Path, cleanup: bool = True, variant: str = "cpu", + output_dir: pathlib.Path | None = None, network_isolation: bool = False, max_jobs: int | None = None, settings_dir: pathlib.Path | None = None, @@ -63,6 +64,10 @@ def __init__( self.constraints.load_constraints_file(constraints_file) else: self.input_constraints_uri = None + if output_dir is not None: + sdists_repo = output_dir / "sdists-repo" + work_dir = output_dir / "work-dir" + wheels_repo = output_dir / "wheels-repo" self.sdists_repo = pathlib.Path(sdists_repo).resolve() self.sdists_downloads = self.sdists_repo / "downloads" self.sdists_builds = self.sdists_repo / "builds" diff --git a/tests/test_context.py b/tests/test_context.py index ebdc856b..4153b8da 100644 --- a/tests/test_context.py +++ b/tests/test_context.py @@ -28,3 +28,48 @@ def test_pip_constraints_args(tmp_path: pathlib.Path) -> None: ) ctx.setup() assert [] == ctx.pip_constraint_args + + +def test_output_directory_creation(tmp_path: pathlib.Path) -> None: + """Verify output directory creation""" + + # default behavior + # output_dir is None with sdists, wheels and work set to defaults + ctx = context.WorkContext( + active_settings=None, + constraints_file=None, + patches_dir=tmp_path / "overrides/patches", + output_dir=None, + sdists_repo=tmp_path / "sdists-repo", + wheels_repo=tmp_path / "wheels-repo", + work_dir=tmp_path / "work-dir", + ) + ctx.setup() + + assert ctx.sdists_repo == (tmp_path / "sdists-repo").resolve() + assert ctx.wheels_repo == (tmp_path / "wheels-repo").resolve() + assert ctx.work_dir == (tmp_path / "work-dir").resolve() + + # set output_dir + # should override defaults for sdists, wheels and work dirs + output_dir = tmp_path / "test-output-dir" + ctx = context.WorkContext( + active_settings=None, + constraints_file=None, + patches_dir=tmp_path / "overrides/patches", + output_dir=output_dir, + sdists_repo=tmp_path / "sdists-repo", + wheels_repo=tmp_path / "wheels-repo", + work_dir=tmp_path / "work-dir", + ) + ctx.setup() + + # verify output_dir created + assert ctx.sdists_repo == (output_dir / "sdists-repo").resolve() + assert ctx.wheels_repo == (output_dir / "wheels-repo").resolve() + assert ctx.work_dir == (output_dir / "work-dir").resolve() + + # verify default dirs are not used + assert ctx.sdists_repo != (tmp_path / "sdists-repo").resolve() + assert ctx.wheels_repo != (tmp_path / "wheels-repo").resolve() + assert ctx.work_dir != (tmp_path / "work-dir").resolve()