Skip to content

Commit f39f170

Browse files
authored
Merge pull request #42 from taskbadger/sk/separeate-sdk-deps
Move CLI deps (typer, rich) to optional [cli] extra
2 parents 568bf98 + 145adc8 commit f39f170

6 files changed

Lines changed: 134 additions & 114 deletions

File tree

.pre-commit-config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
exclude: ^static/.*|assets/.*|/migrations/.*|\.min\.js$|\.min\.css$|\.css\.map$|\.min\.js$|\.js\.map$|\.svg$
22
default_language_version:
3-
python: python3.11
3+
python: python3.12
44
repos:
55
- repo: https://github.com/astral-sh/ruff-pre-commit
66
rev: v0.2.1

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ For full documentation go to https://docs.taskbadger.net/python/.
1616
pip install taskbadger
1717
```
1818

19+
To use the `taskbadger` command-line tool, install the `cli` extra:
20+
21+
```bash
22+
pip install 'taskbadger[cli]'
23+
```
24+
1925
### Client Usage
2026

2127
```python

pyproject.toml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ dependencies = [
2222
"httpx >=0.20.0",
2323
"attrs >=21.3.0",
2424
"python-dateutil >=2.8.0",
25-
"typer[all] <0.10.0",
2625
"tomlkit >=0.12.5",
2726
"importlib-metadata >=1.0; python_version < '3.8'",
2827
"typing-extensions >=4.7.1; python_version <= '3.9'",
@@ -42,6 +41,10 @@ include = [
4241
celery = [
4342
"celery>=4.0.0,<6.0.0",
4443
]
44+
cli = [
45+
"typer >=0.12",
46+
"rich >=13.0",
47+
]
4548

4649
[tool.uv]
4750
package = true
@@ -64,6 +67,7 @@ dev = [
6467
"pytest-celery",
6568
"redis",
6669
"openapi-python-client",
70+
"taskbadger[cli]",
6771
]
6872

6973
[project.scripts]

taskbadger/cli/utils.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import json
22
from enum import Enum
3+
from typing import Optional
34

45
import typer
56
from rich import print
@@ -28,9 +29,9 @@ def get_actions(action_def: tuple[str, str, str]) -> list[Action]:
2829
return []
2930

3031

31-
def merge_kv_json(metadata_kv: list[str], metadata_json: str) -> dict:
32+
def merge_kv_json(metadata_kv: Optional[list[str]], metadata_json: str) -> dict:
3233
metadata = {}
33-
for kv in metadata_kv:
34+
for kv in metadata_kv or []:
3435
k, v = kv.strip().split("=", 1)
3536
metadata[k] = v
3637

taskbadger/cli_main.py

Lines changed: 105 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -1,99 +1,107 @@
1+
import sys
12
from typing import Optional
23

3-
import typer
4-
from rich import print
5-
6-
from taskbadger import __version__
7-
from taskbadger.cli import create, get, list_tasks_command, run, update
8-
from taskbadger.config import get_config, write_config
9-
from taskbadger.sdk import _parse_token
10-
11-
app = typer.Typer(
12-
rich_markup_mode="rich",
13-
context_settings={"help_option_names": ["-h", "--help"]},
14-
)
15-
16-
17-
app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": False})(run)
18-
app.command(context_settings={"ignore_unknown_options": False})(get)
19-
app.command(context_settings={"ignore_unknown_options": False})(create)
20-
app.command(context_settings={"ignore_unknown_options": False})(update)
21-
app.command("list", context_settings={"ignore_unknown_options": False})(list_tasks_command)
22-
23-
24-
def version_callback(value: bool):
25-
if value:
26-
print(f"Task Badger CLI Version: {__version__}")
27-
raise typer.Exit()
28-
29-
30-
@app.command()
31-
def configure(ctx: typer.Context):
32-
"""Update CLI configuration."""
33-
config = ctx.meta["tb_config"]
34-
token = typer.prompt("API Key", default=config.token)
35-
parsed = _parse_token(token)
36-
if parsed:
37-
org_slug, project_slug, api_key = parsed
38-
print(f"Project key detected — organization: [green]{org_slug}[/green], project: [green]{project_slug}[/green]")
39-
config.organization_slug = org_slug
40-
config.project_slug = project_slug
41-
config.token = token
42-
else:
43-
config.organization_slug = typer.prompt("Organization slug", default=config.organization_slug)
44-
config.project_slug = typer.prompt("Project slug", default=config.project_slug)
45-
config.token = token
46-
path = write_config(config)
47-
print(f"Config written to [green]{path}[/green]")
48-
49-
50-
@app.command()
51-
def docs():
52-
"""Open Task Badger docs in a browser."""
53-
typer.launch("https://docs.taskbadger.net")
54-
55-
56-
@app.command()
57-
def info(ctx: typer.Context):
58-
"""Show CLI configuration."""
59-
config = ctx.meta["tb_config"]
60-
print(str(config))
61-
62-
63-
@app.callback()
64-
def main(
65-
ctx: typer.Context,
66-
org: Optional[str] = typer.Option(
67-
None,
68-
"--org",
69-
"-o",
70-
metavar="TASKBADGER_ORG",
71-
show_default=False,
72-
help="Organization Slug. This will override values from the config file and environment variables.",
73-
),
74-
project: Optional[str] = typer.Option(
75-
None,
76-
"--project",
77-
"-p",
78-
show_envvar=False,
79-
metavar="TASKBADGER_PROJECT",
80-
show_default=False,
81-
help="Project Slug. This will override values from the config file and environment variables.",
82-
),
83-
version: Optional[bool] = typer.Option( # noqa
84-
None,
85-
"--version",
86-
callback=version_callback,
87-
is_eager=True,
88-
help="Show CLI Version",
89-
),
90-
):
91-
"""
92-
Task Badger CLI
93-
"""
94-
config = get_config(org=org, project=project)
95-
ctx.meta["tb_config"] = config
96-
97-
98-
if __name__ == "__main__":
99-
app()
4+
try:
5+
import typer
6+
from rich import print
7+
except ImportError as exc:
8+
_missing = exc.name or "typer"
9+
10+
def app() -> None:
11+
sys.stderr.write(
12+
f"The Task Badger CLI requires the '{_missing}' package, which is not installed.\n"
13+
"Install the CLI extras with:\n\n"
14+
" pip install 'taskbadger[cli]'\n"
15+
)
16+
sys.exit(1)
17+
else:
18+
from taskbadger import __version__
19+
from taskbadger.cli import create, get, list_tasks_command, run, update
20+
from taskbadger.config import get_config, write_config
21+
from taskbadger.sdk import _parse_token
22+
23+
app = typer.Typer(
24+
rich_markup_mode="rich",
25+
context_settings={"help_option_names": ["-h", "--help"]},
26+
)
27+
28+
app.command(context_settings={"allow_extra_args": True, "ignore_unknown_options": False})(run)
29+
app.command(context_settings={"ignore_unknown_options": False})(get)
30+
app.command(context_settings={"ignore_unknown_options": False})(create)
31+
app.command(context_settings={"ignore_unknown_options": False})(update)
32+
app.command("list", context_settings={"ignore_unknown_options": False})(list_tasks_command)
33+
34+
def version_callback(value: bool):
35+
if value:
36+
print(f"Task Badger CLI Version: {__version__}")
37+
raise typer.Exit()
38+
39+
@app.command()
40+
def configure(ctx: typer.Context):
41+
"""Update CLI configuration."""
42+
config = ctx.meta["tb_config"]
43+
token = typer.prompt("API Key", default=config.token)
44+
parsed = _parse_token(token)
45+
if parsed:
46+
org_slug, project_slug, api_key = parsed
47+
print(
48+
f"Project key detected — organization: [green]{org_slug}[/green], "
49+
f"project: [green]{project_slug}[/green]"
50+
)
51+
config.organization_slug = org_slug
52+
config.project_slug = project_slug
53+
config.token = token
54+
else:
55+
config.organization_slug = typer.prompt("Organization slug", default=config.organization_slug)
56+
config.project_slug = typer.prompt("Project slug", default=config.project_slug)
57+
config.token = token
58+
path = write_config(config)
59+
print(f"Config written to [green]{path}[/green]")
60+
61+
@app.command()
62+
def docs():
63+
"""Open Task Badger docs in a browser."""
64+
typer.launch("https://docs.taskbadger.net")
65+
66+
@app.command()
67+
def info(ctx: typer.Context):
68+
"""Show CLI configuration."""
69+
config = ctx.meta["tb_config"]
70+
print(str(config))
71+
72+
@app.callback()
73+
def main(
74+
ctx: typer.Context,
75+
org: Optional[str] = typer.Option(
76+
None,
77+
"--org",
78+
"-o",
79+
metavar="TASKBADGER_ORG",
80+
show_default=False,
81+
help="Organization Slug. This will override values from the config file and environment variables.",
82+
),
83+
project: Optional[str] = typer.Option(
84+
None,
85+
"--project",
86+
"-p",
87+
show_envvar=False,
88+
metavar="TASKBADGER_PROJECT",
89+
show_default=False,
90+
help="Project Slug. This will override values from the config file and environment variables.",
91+
),
92+
version: Optional[bool] = typer.Option( # noqa
93+
None,
94+
"--version",
95+
callback=version_callback,
96+
is_eager=True,
97+
help="Show CLI Version",
98+
),
99+
):
100+
"""
101+
Task Badger CLI
102+
"""
103+
config = get_config(org=org, project=project)
104+
ctx.meta["tb_config"] = config
105+
106+
if __name__ == "__main__":
107+
app()

uv.lock

Lines changed: 14 additions & 13 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)