Skip to content
Draft
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
28 changes: 12 additions & 16 deletions docs/source/en/package_reference/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ $ hf collections delete-item [OPTIONS] COLLECTION_SLUG ITEM_OBJECT_ID

### `hf collections info`

Get info about a collection on the Hub. Output is in JSON format.
Get info about a collection on the Hub.

**Usage**:

Expand All @@ -820,6 +820,7 @@ $ hf collections info [OPTIONS] COLLECTION_SLUG

**Options**:

* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--token TEXT`: A User Access Token generated from https://huggingface.co/settings/tokens.
* `--help`: Show this message and exit.

Expand Down Expand Up @@ -847,8 +848,7 @@ $ hf collections list [OPTIONS]
* `--item TEXT`: Filter collections containing a specific item (e.g., "models/gpt2", "datasets/squad", "papers/2311.12983").
* `--sort [lastModified|trending|upvotes]`: Sort results by last modified, trending, or upvotes.
* `--limit INTEGER`: Limit the number of results. [default: 10]
* `--format [table|json]`: Output format (table or json). [default: table]
* `-q, --quiet`: Print only IDs (one per line).
* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--token TEXT`: A User Access Token generated from https://huggingface.co/settings/tokens.
* `--help`: Show this message and exit.

Expand Down Expand Up @@ -1284,8 +1284,7 @@ $ hf discussions list [OPTIONS] REPO_ID
* `--author TEXT`: Filter by author or organization.
* `--limit INTEGER`: Limit the number of results. [default: 30]
* `--type, --repo-type [model|dataset|space]`: The type of repository (model, dataset, or space). [default: model]
* `--format [table|json]`: Output format (table or json). [default: table]
* `-q, --quiet`: Print only IDs (one per line).
* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--token TEXT`: A User Access Token generated from https://huggingface.co/settings/tokens.
* `--help`: Show this message and exit.

Expand Down Expand Up @@ -1643,8 +1642,7 @@ $ hf endpoints list [OPTIONS]
**Options**:

* `--namespace TEXT`: The namespace associated with the Inference Endpoint. Defaults to the current user's namespace.
* `--format [table|json]`: Output format (table or json). [default: table]
* `-q, --quiet`: Print only IDs (one per line).
* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--token TEXT`: A User Access Token generated from https://huggingface.co/settings/tokens.
* `--help`: Show this message and exit.

Expand Down Expand Up @@ -1906,8 +1904,7 @@ $ hf extensions list [OPTIONS]

**Options**:

* `--format [table|json]`: Output format (table or json). [default: table]
* `-q, --quiet`: Print only IDs (one per line).
* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--help`: Show this message and exit.

Examples
Expand Down Expand Up @@ -1956,8 +1953,7 @@ $ hf extensions search [OPTIONS]

**Options**:

* `--format [table|json]`: Output format (table or json). [default: table]
* `-q, --quiet`: Print only IDs (one per line).
* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--help`: Show this message and exit.

Examples
Expand Down Expand Up @@ -3640,7 +3636,7 @@ $ hf webhooks [OPTIONS] COMMAND [ARGS]...
* `delete`: Delete a webhook permanently.
* `disable`: Disable an active webhook.
* `enable`: Enable a disabled webhook.
* `info`: Show full details for a single webhook as...
* `info`: Show full details for a single webhook.
* `list`: List all webhooks for the current user. [alias: ls]
* `update`: Update an existing webhook.

Expand Down Expand Up @@ -3761,7 +3757,7 @@ Learn more

### `hf webhooks info`

Show full details for a single webhook as JSON.
Show full details for a single webhook.

**Usage**:

Expand All @@ -3775,6 +3771,7 @@ $ hf webhooks info [OPTIONS] WEBHOOK_ID

**Options**:

* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--token TEXT`: A User Access Token generated from https://huggingface.co/settings/tokens.
* `--help`: Show this message and exit.

Expand All @@ -3798,15 +3795,14 @@ $ hf webhooks list [OPTIONS]

**Options**:

* `--format [table|json]`: Output format (table or json). [default: table]
* `-q, --quiet`: Print only IDs (one per line).
* `--format [agent|auto|human|json|quiet]`: Output format. [default: auto]
* `--token TEXT`: A User Access Token generated from https://huggingface.co/settings/tokens.
* `--help`: Show this message and exit.

Examples
$ hf webhooks ls
$ hf webhooks ls --format json
$ hf webhooks ls -q
$ hf webhooks ls --format quiet

Learn more
Use `hf <command> --help` for more information about a command.
Expand Down
35 changes: 16 additions & 19 deletions src/huggingface_hub/cli/collections.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,24 +34,21 @@
"""

import enum
import json
from typing import Annotated, get_args

import typer

from huggingface_hub.hf_api import CollectionItemType_T, CollectionSort_T

from ._cli_utils import (
FormatOpt,
FormatWithAutoOpt,
LimitOpt,
OutputFormat,
QuietOpt,
TokenOpt,
api_object_to_dict,
get_hf_api,
print_list_output,
typer_factory,
)
from ._output import OutputFormatWithAuto, out


# Build enums dynamically from Literal types to avoid duplication
Expand Down Expand Up @@ -89,8 +86,7 @@ def collections_ls(
typer.Option(help="Sort results by last modified, trending, or upvotes."),
] = None,
limit: LimitOpt = 10,
format: FormatOpt = OutputFormat.table,
quiet: QuietOpt = False,
format: FormatWithAutoOpt = OutputFormatWithAuto.auto,
token: TokenOpt = None,
) -> None:
"""List collections on the Hub."""
Expand All @@ -105,7 +101,7 @@ def collections_ls(
limit=limit,
)
]
print_list_output(results, format=format, quiet=quiet)
out.table(results)


@collections_cli.command(
Expand All @@ -116,12 +112,13 @@ def collections_ls(
)
def collections_info(
collection_slug: Annotated[str, typer.Argument(help="The collection slug (e.g., 'username/collection-slug').")],
format: FormatWithAutoOpt = OutputFormatWithAuto.auto,
token: TokenOpt = None,
) -> None:
"""Get info about a collection on the Hub. Output is in JSON format."""
"""Get info about a collection on the Hub."""
api = get_hf_api(token=token)
collection = api.get_collection(collection_slug)
print(json.dumps(api_object_to_dict(collection), indent=2))
out.dict(collection)


@collections_cli.command(
Expand Down Expand Up @@ -161,8 +158,8 @@ def collections_create(
private=private,
exists_ok=exists_ok,
)
print(f"Collection created: {collection.url}")
print(json.dumps(api_object_to_dict(collection), indent=2))
out.result("Collection created", url=collection.url)
out.dict(collection)


@collections_cli.command(
Expand Down Expand Up @@ -207,8 +204,8 @@ def collections_update(
private=private,
theme=theme,
)
print(f"Collection updated: {collection.url}")
print(json.dumps(api_object_to_dict(collection), indent=2))
out.result("Collection updated", url=collection.url)
out.dict(collection)


@collections_cli.command(
Expand All @@ -229,7 +226,7 @@ def collections_delete(
"""Delete a collection from the Hub."""
api = get_hf_api(token=token)
api.delete_collection(collection_slug, missing_ok=missing_ok)
print(f"Collection deleted: {collection_slug}")
out.result("Collection deleted", slug=collection_slug)


@collections_cli.command(
Expand Down Expand Up @@ -268,8 +265,8 @@ def collections_add_item(
note=note,
exists_ok=exists_ok,
)
print(f"Item added to collection: {collection_slug}")
print(json.dumps(api_object_to_dict(collection), indent=2))
out.result("Item added to collection", slug=collection_slug)
out.dict(collection)


@collections_cli.command(
Expand Down Expand Up @@ -303,7 +300,7 @@ def collections_update_item(
note=note,
position=position,
)
print(f"Item updated in collection: {collection_slug}")
out.result("Item updated in collection", slug=collection_slug)


@collections_cli.command("delete-item")
Expand All @@ -328,4 +325,4 @@ def collections_delete_item(
item_object_id=item_object_id,
missing_ok=missing_ok,
)
print(f"Item deleted from collection: {collection_slug}")
out.result("Item deleted from collection", slug=collection_slug)
45 changes: 14 additions & 31 deletions src/huggingface_hub/cli/discussions.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,17 @@

from ._cli_utils import (
AuthorOpt,
FormatOpt,
FormatWithAutoOpt,
LimitOpt,
OutputFormat,
QuietOpt,
RepoIdArg,
RepoType,
RepoTypeOpt,
TokenOpt,
_format_cell,
api_object_to_dict,
get_hf_api,
print_list_output,
typer_factory,
)
from ._output import OutputFormatWithAuto, out


class DiscussionStatus(str, enum.Enum):
Expand Down Expand Up @@ -181,8 +178,7 @@ def discussion_list(
author: AuthorOpt = None,
limit: LimitOpt = 30,
repo_type: RepoTypeOpt = RepoType.model,
format: FormatOpt = OutputFormat.table,
quiet: QuietOpt = False,
format: FormatWithAutoOpt = OutputFormatWithAuto.auto,
token: TokenOpt = None,
) -> None:
"""List discussions and pull requests on a repo."""
Expand Down Expand Up @@ -217,21 +213,10 @@ def discussion_list(
break

items = [api_object_to_dict(d) for d in discussions]

print_list_output(
out.table(
items,
format=format,
quiet=quiet,
id_key="num",
headers=["num", "title", "is_pull_request", "status", "author", "created_at"],
row_fn=lambda item: [
f"#{item['num']}",
_format_cell(item.get("title", ""), max_len=50),
"PR" if item.get("is_pull_request") else "",
_format_status(str(item.get("status", ""))),
str(item.get("author", "")),
_format_cell(item.get("created_at", "")),
],
id_key="num",
alignments={"num": "right"},
)

Expand Down Expand Up @@ -360,10 +345,8 @@ def discussion_create(
pull_request=pull_request,
)
kind = "pull request" if pull_request else "discussion"
print(f"Created {kind} {ANSI.bold(f'#{discussion.num}')} on {ANSI.bold(repo_id)}")
if pull_request:
print(f"Push changes to: {ANSI.bold(f'refs/pr/{discussion.num}')}")
print(f"View on Hub: {ANSI.blue(discussion.url)}")
ref = f"refs/pr/{discussion.num}" if pull_request else None
out.result(f"Created {kind} #{discussion.num} on {repo_id}", num=discussion.num, url=discussion.url, ref=ref)


@discussions_cli.command(
Expand Down Expand Up @@ -404,7 +387,7 @@ def discussion_comment(
comment=comment,
repo_type=repo_type.value,
)
print(f"Commented on #{num} in {ANSI.bold(repo_id)}")
out.result(f"Commented on #{num} on {repo_id}", num=num, repo=repo_id)


@discussions_cli.command(
Expand Down Expand Up @@ -449,7 +432,7 @@ def discussion_close(
comment=comment,
repo_type=repo_type.value,
)
print(f"Closed #{num} in {ANSI.bold(repo_id)}")
out.result(f"Closed #{num} on {repo_id}", num=num, repo=repo_id)


@discussions_cli.command(
Expand Down Expand Up @@ -494,7 +477,7 @@ def discussion_reopen(
comment=comment,
repo_type=repo_type.value,
)
print(f"Reopened #{num} in {ANSI.bold(repo_id)}")
out.result(f"Reopened #{num} on {repo_id}", num=num, repo=repo_id)


@discussions_cli.command(
Expand Down Expand Up @@ -523,7 +506,7 @@ def discussion_rename(
new_title=new_title,
repo_type=repo_type.value,
)
print(f"Renamed #{num} to {ANSI.bold(new_title)} in {ANSI.bold(repo_id)}")
out.result(f"Renamed #{num} on {repo_id}", num=num, repo=repo_id, title=new_title)


@discussions_cli.command(
Expand Down Expand Up @@ -567,7 +550,7 @@ def discussion_merge(
comment=comment,
repo_type=repo_type.value,
)
print(f"Merged #{num} in {ANSI.bold(repo_id)}")
out.result(f"Merged #{num} on {repo_id}", num=num, repo=repo_id)


@discussions_cli.command(
Expand All @@ -590,6 +573,6 @@ def discussion_diff(
repo_type=repo_type.value,
)
if details.diff:
print(details.diff)
out.text(details.diff)
else:
print("No diff available.")
out.text("No diff available.")
11 changes: 6 additions & 5 deletions src/huggingface_hub/cli/extensions.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@
from huggingface_hub.errors import CLIError, CLIExtensionInstallError
from huggingface_hub.utils import StatusLine, get_session, logging

from ._cli_utils import FormatOpt, OutputFormat, QuietOpt, print_list_output, typer_factory
from ._cli_utils import FormatWithAutoOpt, typer_factory
from ._output import OutputFormatWithAuto, out


DEFAULT_EXTENSION_OWNER = "huggingface"
Expand Down Expand Up @@ -159,7 +160,7 @@ def extension_exec(


@extensions_cli.command("list | ls", examples=["hf extensions list"])
def extension_list(format: FormatOpt = OutputFormat.table, quiet: QuietOpt = False) -> None:
def extension_list(format: FormatWithAutoOpt = OutputFormatWithAuto.auto) -> None:
"""List installed extension commands."""
rows = [
{
Expand All @@ -171,11 +172,11 @@ def extension_list(format: FormatOpt = OutputFormat.table, quiet: QuietOpt = Fal
}
for manifest in _list_installed_extensions()
]
print_list_output(rows, format=format, quiet=quiet, id_key="command")
out.table(rows, id_key="command")


@extensions_cli.command("search", examples=["hf extensions search"])
def extension_search(format: FormatOpt = OutputFormat.table, quiet: QuietOpt = False) -> None:
def extension_search(format: FormatWithAutoOpt = OutputFormatWithAuto.auto) -> None:
"""Search extensions available on GitHub (tagged with 'hf-extension' topic)."""
response = get_session().get(
"https://api.github.com/search/repositories",
Expand All @@ -202,7 +203,7 @@ def extension_search(format: FormatOpt = OutputFormat.table, quiet: QuietOpt = F
}
)

print_list_output(rows, format=format, quiet=quiet, id_key="repo", alignments={"stars": "right"})
out.table(rows, id_key="repo", alignments={"stars": "right"})


@extensions_cli.command("remove | rm", examples=["hf extensions remove claude"])
Expand Down
Loading
Loading