Skip to content

Commit 141a67a

Browse files
authored
feat: provide global option -j/--workers (#190) (#204)
* feat #190: provide global option -j/--workers Signed-off-by: sushant-suse <[email protected]> * fix #190: addressed Tom's comments Signed-off-by: sushant-suse <[email protected]> * feat: added fragment file for issue #189 and #190 Signed-off-by: sushant-suse <[email protected]> --------- Signed-off-by: sushant-suse <[email protected]>
1 parent 5532191 commit 141a67a

6 files changed

Lines changed: 46 additions & 5 deletions

File tree

changelog.d/189.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Introduce the ``max_workers`` configuration key in the application config. This allows users to define concurrency limits using integers or hardware-aware keywords such as ``all``, ``half``, or ``all2``.

changelog.d/190.feature.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add a global CLI option ``-j``/``--workers`` to manage concurrency. This option overrides the configuration file and supports both explicit integer values and dynamic keywords (``all``, ``half``, ``all2``).

src/docbuild/cli/cmd_cli.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ def handle_validation_error(
9696
)
9797
@click.option("-v", "--verbose", count=True, help="Increase verbosity")
9898
@click.option("--dry-run", is_flag=True, help="Run without making changes")
99+
@click.option(
100+
"-j",
101+
"--workers",
102+
"max_workers",
103+
default="half",
104+
show_default=True,
105+
help="Maximum number of concurrent workers (integer, 'all', or 'all2').",
106+
)
99107
@click.option(
100108
"--debug/--no-debug",
101109
default=False,
@@ -137,6 +145,7 @@ def cli(
137145
debug: bool,
138146
app_config: Path,
139147
env_config: Path,
148+
max_workers: str | None,
140149
**kwargs: dict,
141150
) -> None:
142151
"""Acts as a main entry point for CLI tool.
@@ -177,6 +186,9 @@ def cli(
177186

178187
raw_appconfig = cast(dict[str, Any], raw_appconfig)
179188

189+
if max_workers is not None:
190+
raw_appconfig["max_workers"] = max_workers
191+
180192
try:
181193
context.appconfig = AppConfig.from_dict(raw_appconfig)
182194
except (ValueError, ValidationError) as e:

src/docbuild/cli/context.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
from dataclasses import dataclass
44
from pathlib import Path
5-
from typing import Any
65

6+
from ..models.config.app import AppConfig
77
from ..models.config.env import EnvConfig
88
from ..models.doctype import Doctype
99

@@ -24,7 +24,7 @@ class DocBuildContext:
2424
appconfig_from_defaults: bool = False
2525
"""If set, the app's config was loaded from defaults"""
2626

27-
appconfig: dict[str, Any] | None = None
27+
appconfig: AppConfig | None = None
2828
"""The accumulated content of all app config files"""
2929

3030
envconfigfiles: tuple[str | Path, ...] | None = None

src/docbuild/models/config/app.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -190,14 +190,14 @@ class AppConfig(BaseModel):
190190
)
191191

192192
# Added max_workers with support for ints and descriptive strings
193-
max_workers: int | str = Field(
194-
default="half",
193+
max_workers: int = Field(
194+
default="half", # type: ignore
195195
description="Max concurrent workers. Supports integers or 'all', 'all2'/'half'.",
196196
)
197197

198198
model_config = ConfigDict(extra="allow")
199199

200-
@field_validator("max_workers")
200+
@field_validator("max_workers", mode="before")
201201
@classmethod
202202
def _resolve_worker_count(cls, v: int | str) -> int:
203203
"""Resolve keywords 'all', 'half', 'all2' into concrete integers."""

tests/cli/test_worker_option.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from click.testing import CliRunner
2+
3+
from docbuild.cli.cmd_cli import cli
4+
5+
6+
def test_workers_option_integration():
7+
runner = CliRunner()
8+
9+
# We use a command that exists but we don't care if it fails
10+
# due to the directory permissions seen above.
11+
# We are testing the CLI parsing logic here.
12+
result = runner.invoke(cli, ["-j", "1", "config", "show"])
13+
14+
# If '-j' was invalid, exit code would be 2 (Click usage error)
15+
# Since it's valid, it should proceed to validation logic (exit code 1 or 0)
16+
assert result.exit_code != 2
17+
assert "no such option: -j" not in result.output
18+
19+
def test_workers_option_invalid_value():
20+
runner = CliRunner()
21+
22+
# Test an invalid string that should trigger our Pydantic ValueError
23+
result = runner.invoke(cli, ["-j", "not-a-number", "config", "show"])
24+
25+
# This should trigger our 'handle_validation_error' logic
26+
assert result.exit_code == 1
27+
assert "Invalid max_workers value" in result.output

0 commit comments

Comments
 (0)