Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## Unreleased

## [0.1.1] - 2026-01-02

Dropped `typer` dependency for CLI.
[#39](https://github.com/pyodide/pyodide-lock/pull/39)

## [0.1.0] - 2025-08-16

No functional changes. pyodide-lock is no longer an alpha version.
Expand Down
81 changes: 52 additions & 29 deletions pyodide_lock/cli.py
Original file line number Diff line number Diff line change
@@ -1,41 +1,60 @@
from pathlib import Path

import typer
import click

from .spec import PyodideLockSpec
from .utils import add_wheels_to_spec

main = typer.Typer(help="manipulate pyodide-lock.json lockfiles.")

@click.group(help="Manipulate pyodide-lock.json lockfiles.")
def main():
"""Manipulate pyodide-lock.json lockfiles."""
pass

@main.command()

@main.command(short_help="Add wheels to a pyodide-lock.json lockfile.")
@click.argument(
"wheels", nargs=-1, type=click.Path(exists=True, path_type=Path), required=True
)
@click.option(
"--ignore-missing-dependencies",
is_flag=True,
default=False,
help="If this is true, dependencies which are not in the original lockfile or "
"the added wheels will be added to the lockfile. Warning: This will allow a broken lockfile to be created.",
)
@click.option(
"--input",
type=click.Path(path_type=Path),
default=Path("pyodide-lock.json"),
help="Source lockfile",
)
@click.option(
"--output",
type=click.Path(path_type=Path),
default=Path("pyodide-lock-new.json"),
help="Updated lockfile",
)
@click.option(
"--base-path",
type=click.Path(path_type=Path),
default=None,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is None accepted as click.Path? As typer version worked well, it will do so, but I am slightly concerned about its behavior.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it does. I believe click will not change the None to something else, and it should be fine then.

help="Base path for wheels - wheel file names will be created relative to this path.",
)
@click.option(
"--wheel-url",
type=str,
default="",
help="Base url which will be appended to the wheel location. "
"Use this if you are hosting these wheels on a different server to core pyodide packages",
)
def add_wheels(
wheels: list[Path],
ignore_missing_dependencies: bool = typer.Option(
help="If this is true, dependencies "
"which are not in the original lockfile or "
"the added wheels will be added to the lockfile. "
"Warning: This will allow a broken lockfile to "
"be created.",
default=False,
),
input: Path = typer.Option(
help="Source lockfile", default=Path("pyodide-lock.json")
),
output: Path = typer.Option(
help="Updated lockfile", default=Path("pyodide-lock-new.json")
),
base_path: Path = typer.Option(
help="Base path for wheels - wheel file "
"names will be created relative to this path.",
default=None,
),
wheel_url: str = typer.Option(
help="Base url which will be appended to the wheel location."
"Use this if you are hosting these wheels on a different "
"server to core pyodide packages",
default="",
),
wheels,
ignore_missing_dependencies,
input,
output,
base_path,
wheel_url,
):
"""Add a set of package wheels to an existing pyodide-lock.json and

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Arguments are not printed by default in click. If we were to provide consistency, we can explicitly add argument info in the docstring by appending

    \b
    Arguments:
        WHEELS: List of paths to wheel files. (required)

or something similar.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. Thanks for the pointer!

write it out to pyodide-lock-new.json
Expand All @@ -45,6 +64,10 @@ def add_wheels(
this will fail if a dependency isn't available in either the
existing lock file, or in the set of new wheels.

\b
Arguments:
WHEELS: List of paths to wheel files. (required)

"""
sp = PyodideLockSpec.from_json(input)
sp = add_wheels_to_spec(
Expand Down
8 changes: 6 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ dynamic = ["version"]

[project.optional-dependencies]
cli = [
"typer",
"click",
"pyodide-cli>=0.4.0",
]
wheel = [
"pkginfo",
Expand All @@ -33,7 +34,7 @@ dev = [
"pytest",
"pytest-cov",
"build",
"typer",
"click",
# from wheel
"pkginfo",
"packaging",
Expand Down Expand Up @@ -77,6 +78,9 @@ select = [
"PLE", # pylint errors
"UP", # pyupgrade
]
ignore = [
"E501", # line too long
]

[tool.pytest.ini_options]
addopts = '''
Expand Down
3 changes: 2 additions & 1 deletion tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typer.testing import CliRunner
from click.testing import CliRunner

from pyodide_lock.cli import main
from pyodide_lock.spec import PyodideLockSpec
Expand All @@ -15,6 +15,7 @@ def test_add_wheels_cli_integration(tmp_path, example_lock_spec, test_wheel_list
result = runner.invoke(
main,
[
"add-wheels",
str(test_wheel_list[0]),
"--input",
str(input_file),
Expand Down
2 changes: 1 addition & 1 deletion tests/test_wheel.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ def test_base_relative_path(test_wheel_list, example_lock_spec):
assert "needs-one" in example_lock_spec.packages
assert "needs-one-opt" in example_lock_spec.packages
assert example_lock_spec.packages["needs-one-opt"].file_name.startswith(
"http://www.nowhere.org/dist/nEEds"
"http://www.nowhere.org/dist/needs"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder why it was written with nEEds in the first place, it should have been intentional?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably to test name canonicalization

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure why the original test was written with nEEds and why it passed. The filename should be canonicalized I gueess.

)


Expand Down