|
26 | 26 | from uuid import UUID
|
27 | 27 |
|
28 | 28 | from click import Context, Parameter
|
| 29 | +from click.core import ParameterSource |
29 | 30 | from click.shell_completion import CompletionItem
|
30 | 31 | from django.apps import apps
|
31 | 32 | from django.conf import settings
|
@@ -321,7 +322,12 @@ def __call__(
|
321 | 322 | return []
|
322 | 323 |
|
323 | 324 | excluded: t.List[t.Type[Model]] = []
|
324 |
| - if self.distinct and parameter.name: |
| 325 | + if ( |
| 326 | + self.distinct |
| 327 | + and parameter.name |
| 328 | + and context.get_parameter_source(parameter.name) |
| 329 | + is not ParameterSource.DEFAULT |
| 330 | + ): |
325 | 331 | excluded = context.params.get(parameter.name, []) or []
|
326 | 332 |
|
327 | 333 | return [
|
@@ -380,7 +386,12 @@ def handle(
|
380 | 386 | :return: A list of matching app labels or names. Labels already present for the
|
381 | 387 | parameter on the command line will be filtered out.
|
382 | 388 | """
|
383 |
| - present = [app.label for app in (ctx.params.get(param.name or "") or [])] |
| 389 | + present = [] |
| 390 | + if ( |
| 391 | + param.name |
| 392 | + and ctx.get_parameter_source(param.name) is not ParameterSource.DEFAULT |
| 393 | + ): |
| 394 | + present = [app.label for app in (ctx.params.get(param.name) or [])] |
384 | 395 | ret = [
|
385 | 396 | CompletionItem(app.label)
|
386 | 397 | for app in apps.get_app_configs()
|
@@ -503,29 +514,38 @@ def exists(pth: Path) -> bool:
|
503 | 514 | """
|
504 | 515 |
|
505 | 516 |
|
506 |
| -def these_strings(strings: t.List[str], allow_duplicates: bool = False): |
| 517 | +def these_strings( |
| 518 | + strings: t.Union[t.Callable[[], t.Sequence[str]], t.Sequence[str]], |
| 519 | + allow_duplicates: bool = False, |
| 520 | +): |
507 | 521 | """
|
508 | 522 | Get a completer that provides completion logic that matches the allowed strings.
|
509 | 523 |
|
510 |
| - :param strings: A list of allowed strings. |
| 524 | + :param strings: A sequence of allowed strings or a callable that generates a sequence of |
| 525 | + allowed strings. |
511 | 526 | :param allow_duplicates: Whether or not to allow duplicate values. Defaults to False.
|
512 | 527 | :return: A completer function.
|
513 | 528 | """
|
514 | 529 |
|
515 | 530 | def complete(ctx: Context, param: Parameter, incomplete: str):
|
516 | 531 | present = []
|
517 |
| - if not allow_duplicates: |
518 |
| - present = [value for value in (ctx.params.get(param.name or "") or [])] |
| 532 | + if ( |
| 533 | + not allow_duplicates |
| 534 | + and param.name |
| 535 | + and ctx.get_parameter_source(param.name) is not ParameterSource.DEFAULT |
| 536 | + ): |
| 537 | + present = [value for value in (ctx.params.get(param.name) or [])] |
519 | 538 | return [
|
520 | 539 | CompletionItem(item)
|
521 |
| - for item in strings |
| 540 | + for item in (strings() if callable(strings) else strings) |
522 | 541 | if item.startswith(incomplete) and item not in present
|
523 | 542 | ]
|
524 | 543 |
|
525 | 544 | return complete
|
526 | 545 |
|
527 | 546 |
|
528 |
| -databases = these_strings([alias for alias in settings.DATABASES.keys()]) |
| 547 | +# use a function that returns a generator because we should not access settings on import |
| 548 | +databases = these_strings(lambda: settings.DATABASES.keys()) |
529 | 549 | """
|
530 | 550 | A completer that provides completion logic for the Django database aliases
|
531 | 551 | configured in settings.DATABASES.
|
|
0 commit comments