|
1 | 1 | import asyncio |
2 | 2 | import logging |
3 | 3 | from functools import partial, wraps |
| 4 | +from typing import Any, Callable |
| 5 | +from types import SimpleNamespace |
4 | 6 |
|
5 | 7 | import click |
6 | 8 | import httpx |
| 9 | +from click.core import Parameter, ParameterSource |
7 | 10 | from packaging.version import parse |
8 | 11 |
|
9 | 12 | from .config import Session |
@@ -204,25 +207,113 @@ def callback(ctx: click.Context, param, value): |
204 | 207 | return option |
205 | 208 |
|
206 | 209 |
|
207 | | -def bunch_size_option(func=None, **kwargs): |
| 210 | +def page_size_option( |
| 211 | + func: Callable[..., Any] | None = None, **kwargs: Any |
| 212 | +) -> Callable[..., Any]: |
| 213 | + """Create a Click option for page size with a legacy alias. |
| 214 | +
|
| 215 | + Adds a primary ``--page-size`` option and accepts the legacy |
| 216 | + ``--bunch-size`` during a transition period. The value is validated to |
| 217 | + be within ``[10, 1000]``. If both flags are supplied, ``--page-size`` |
| 218 | + takes precedence. The value is stored under both keys (``page_size``, |
| 219 | + ``bunch_size``) to keep older commands compatible. |
| 220 | + """ |
| 221 | + # Primary option defaults |
208 | 222 | kwargs.setdefault("type", click.IntRange(10, 1000)) |
209 | 223 | kwargs.setdefault("default", 1000) |
210 | 224 | kwargs.setdefault("show_default", True) |
| 225 | + kwargs.setdefault("metavar", "[10-1000]") |
211 | 226 | kwargs.setdefault( |
212 | | - "help", ("How many library items should be requested per request. A " |
213 | | - "lower size results in more requests to get the full library. " |
214 | | - "A higher size can result in a TimeOutError on low internet " |
215 | | - "connections.") |
| 227 | + "help", |
| 228 | + ( |
| 229 | + "Number of items to request per API call (10–1000). Larger values " |
| 230 | + "reduce the number of requests but may cause timeouts or higher " |
| 231 | + "memory usage on slow connections. Tip: Use smaller values if you " |
| 232 | + "experience 408 timeouts or 429 rate limits." |
| 233 | + ), |
216 | 234 | ) |
217 | | - kwargs.setdefault("callback", add_param_to_session) |
218 | | - kwargs.setdefault("expose_value", False) |
219 | 235 |
|
220 | | - option = click.option("--bunch-size", **kwargs) |
| 236 | + def _page_size_callback( |
| 237 | + ctx: click.Context, param: Parameter, value: int | None |
| 238 | + ) -> None: |
| 239 | + """Callback for ``--page-size``. |
| 240 | +
|
| 241 | + If the value came from the command line, always write it. |
| 242 | + If it's the default, only write it when the session does not already |
| 243 | + contain values (e.g., set by legacy ``--bunch-size``). |
| 244 | + """ |
| 245 | + if value is None: |
| 246 | + return |
| 247 | + |
| 248 | + source = ctx.get_parameter_source("page_size") |
| 249 | + session = ctx.ensure_object(Session) # your app's Session |
| 250 | + |
| 251 | + if source == ParameterSource.COMMANDLINE: |
| 252 | + # Explicit --page-size: always set/override. |
| 253 | + add_param_to_session(ctx, SimpleNamespace(name="page_size"), value) |
| 254 | + add_param_to_session(ctx, SimpleNamespace(name="bunch_size"), value) |
| 255 | + return |
| 256 | + |
| 257 | + # Default value path: do not overwrite if legacy already populated. |
| 258 | + if "page_size" in session.params or "bunch_size" in session.params: |
| 259 | + # Skip to avoid clobbering a legacy value (or any pre-set value). |
| 260 | + return |
| 261 | + |
| 262 | + # Neither key set yet → apply default to both keys. |
| 263 | + add_param_to_session(ctx, SimpleNamespace(name="page_size"), value) |
| 264 | + add_param_to_session(ctx, SimpleNamespace(name="bunch_size"), value) |
| 265 | + |
| 266 | + kwargs["callback"] = _page_size_callback |
| 267 | + kwargs["expose_value"] = False |
| 268 | + |
| 269 | + page_size = click.option("--page-size", **kwargs) |
| 270 | + |
| 271 | + def _legacy_bunch_size_callback( |
| 272 | + ctx: click.Context, param: Parameter, value: int | None |
| 273 | + ) -> None: |
| 274 | + """Handle ``--bunch-size`` as a deprecated alias. |
| 275 | +
|
| 276 | + If ``--page-size`` was explicitly provided, ignore legacy and note it. |
| 277 | + Otherwise, store the legacy value under both keys and warn. |
| 278 | + """ |
| 279 | + if value is None: |
| 280 | + return |
| 281 | + |
| 282 | + if ctx.get_parameter_source("page_size") == ParameterSource.COMMANDLINE: |
| 283 | + click.echo( |
| 284 | + "Note: --bunch-size is deprecated and ignored because --page-size was provided.", |
| 285 | + err=True, |
| 286 | + ) |
| 287 | + return |
| 288 | + |
| 289 | + click.echo( |
| 290 | + "Warning: --bunch-size is deprecated. Please use --page-size.", |
| 291 | + err=True, |
| 292 | + ) |
| 293 | + add_param_to_session(ctx, SimpleNamespace(name="page_size"), value) |
| 294 | + add_param_to_session(ctx, SimpleNamespace(name="bunch_size"), value) |
| 295 | + |
| 296 | + legacy = click.option( |
| 297 | + "--bunch-size", |
| 298 | + type=click.IntRange(10, 1000), |
| 299 | + default=None, # only active when explicitly provided |
| 300 | + hidden=True, # keep it out of --help |
| 301 | + callback=_legacy_bunch_size_callback, |
| 302 | + expose_value=False, |
| 303 | + ) |
| 304 | + |
| 305 | + def decorator(f: Callable[..., Any]) -> Callable[..., Any]: |
| 306 | + # Order doesn't matter now; guards in callbacks prevent overwrites. |
| 307 | + return page_size(legacy(f)) |
221 | 308 |
|
222 | 309 | if callable(func): |
223 | | - return option(func) |
| 310 | + return decorator(func) |
224 | 311 |
|
225 | | - return option |
| 312 | + return decorator |
| 313 | + |
| 314 | + |
| 315 | +# Backward-compat alias for old imports |
| 316 | +bunch_size_option = page_size_option |
226 | 317 |
|
227 | 318 |
|
228 | 319 | def start_date_option(func=None, **kwargs): |
|
0 commit comments