Skip to content

Commit

Permalink
more strictly enforce 88 line length limit
Browse files Browse the repository at this point in the history
  • Loading branch information
bckohan committed Feb 7, 2025
1 parent abad5d8 commit f6a1e13
Show file tree
Hide file tree
Showing 15 changed files with 388 additions and 300 deletions.
32 changes: 20 additions & 12 deletions django_typer/completers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,20 @@
This package provides some completer functions and classes that work with common Django_
types:
- **models**: Complete model object field strings using :class:`~django_typer.completers.model.ModelObjectCompleter`.
- **django apps**: Complete app labels or names using :func:`~django_typer.completers.apps.app_labels`.
- **commands**: Complete Django command names using :func:`~django_typer.completers.cmd.commands`.
- **databases**: Complete Django database names using :func:`~django_typer.completers.db.databases`.
- **import paths**: Complete Django database names using :func:`~django_typer.completers.path.import_paths`.
- **paths**: Complete Django database names using :func:`~django_typer.completers.path.paths`.
- **directories**: Complete Django database names using :func:`~django_typer.completers.path.directories`.
- **models**: Complete model object field strings using
:class:`~django_typer.completers.model.ModelObjectCompleter`.
- **django apps**: Complete app labels or names using
:func:`~django_typer.completers.apps.app_labels`.
- **commands**: Complete Django command names using
:func:`~django_typer.completers.cmd.commands`.
- **databases**: Complete Django database names using
:func:`~django_typer.completers.db.databases`.
- **import paths**: Complete Django database names using
:func:`~django_typer.completers.path.import_paths`.
- **paths**: Complete Django database names using
:func:`~django_typer.completers.path.paths`.
- **directories**: Complete Django database names using
:func:`~django_typer.completers.path.directories`.
"""

import typing as t
Expand All @@ -35,9 +42,10 @@ def these_strings(
"""
Get a completer that provides completion logic that matches the allowed strings.
:param strings: A sequence of allowed strings or a callable that generates a sequence of
allowed strings.
:param allow_duplicates: Whether or not to allow duplicate values. Defaults to False.
:param strings: A sequence of allowed strings or a callable that generates a
sequence of allowed strings.
:param allow_duplicates: Whether or not to allow duplicate values. Defaults to
False.
:return: A completer function.
"""

Expand Down Expand Up @@ -84,8 +92,8 @@ def chain(
:param completers: The completers to use
:param first_match: If true, return only the matches from the first completer that
finds completions. Default: False
:param allow_duplicates: If False (default) remove completions from previously provided
values.
:param allow_duplicates: If False (default) remove completions from previously
provided values.
"""

def complete(ctx: Context, param: Parameter, incomplete: str):
Expand Down
3 changes: 2 additions & 1 deletion django_typer/completers/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@

from . import these_strings

# use a function that returns a generator because we should not access settings on import
# use a function that returns a generator because we should not access settings on
# import
databases = partial(these_strings, lambda: settings.DATABASES.keys())
"""
A completer that completes Django database aliases configured in settings.DATABASES.
Expand Down
66 changes: 36 additions & 30 deletions django_typer/completers/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,14 @@ class ModelObjectCompleter:
.. note::
The queries used by this completer will make use of column indexes. Completions should be
fast even for large data.
The queries used by this completer will make use of column indexes. Completions
should be fast even for large data.
The completer query logic is pluggable, but the defaults cover most use cases. The
limit field is important. It defaults to 50 meaning if more than 50 potential completions
are found only the first 50 will be returned and there will be no indication to the user
that there are more. This is to prevent the shell from becoming unresponsive when offering
completion for large tables.
limit field is important. It defaults to 50 meaning if more than 50 potential
completions are found only the first 50 will be returned and there will be no
indication to the user that there are more. This is to prevent the shell from
becoming unresponsive when offering completion for large tables.
To use this completer, pass an instance of this class to the `shell_complete`
argument of a typer.Option or typer.Argument:
Expand Down Expand Up @@ -221,7 +221,8 @@ def text_query(
"""
The default completion query builder for text-based fields. This method will
return a Q object that will match any value that starts with the incomplete
string. Case sensitivity is determined by the case_insensitive constructor parameter.
string. Case sensitivity is determined by the case_insensitive constructor
parameter.
:param context: The click context.
:param parameter: The click parameter.
Expand Down Expand Up @@ -282,7 +283,8 @@ def uuid_query(

def _get_date_bounds(self, incomplete: str) -> t.Tuple[date, date]:
"""
Turn an incomplete YYYY-MM-DD date string into upper and lower bound date objects.
Turn an incomplete YYYY-MM-DD date string into upper and lower bound date
objects.
:param incomplete: The incomplete time string.
:return: A 2-tuple of (lower, upper) date object boundaries.
Expand Down Expand Up @@ -372,9 +374,9 @@ def date_query(
self, context: Context, parameter: Parameter, incomplete: str
) -> models.Q:
"""
Default completion query builder for date fields. This method will return a Q object that
will match any value that starts with the incomplete date string. All dates must be in
ISO8601 format (YYYY-MM-DD).
Default completion query builder for date fields. This method will return a Q
object that will match any value that starts with the incomplete date string.
All dates must be in ISO8601 format (YYYY-MM-DD).
:param context: The click context.
:param parameter: The click parameter.
Expand All @@ -392,9 +394,9 @@ def time_query(
self, context: Context, parameter: Parameter, incomplete: str
) -> models.Q:
"""
Default completion query builder for time fields. This method will return a Q object that
will match any value that starts with the incomplete time string. All times must be in
ISO 8601 format (HH:MM:SS.ssssss).
Default completion query builder for time fields. This method will return a Q
object that will match any value that starts with the incomplete time string.
All times must be in ISO 8601 format (HH:MM:SS.ssssss).
:param context: The click context.
:param parameter: The click parameter.
Expand All @@ -412,16 +414,17 @@ def datetime_query(
self, context: Context, parameter: Parameter, incomplete: str
) -> models.Q:
"""
Default completion query builder for datetime fields. This method will return a Q object that
will match any value that starts with the incomplete datetime string. All dates must be in
ISO8601 format (YYYY-MM-DDTHH:MM:SS.ssssss±HH:MM).
Default completion query builder for datetime fields. This method will return a
Q object that will match any value that starts with the incomplete datetime
string. All dates must be in ISO8601 format (YYYY-MM-DDTHH:MM:SS.ssssss±HH:MM).
:param context: The click context.
:param parameter: The click parameter.
:param incomplete: The incomplete string.
:return: A Q object to use for filtering the queryset.
:raises ValueError: If the incomplete string is not a valid partial datetime.
:raises AssertionError: If the incomplete string is not a valid partial datetime.
:raises AssertionError: If the incomplete string is not a valid partial
datetime.
"""
import re
from datetime import datetime
Expand All @@ -440,9 +443,10 @@ def get_tz_part(dt_str: str) -> str:
if len(parts) > 1:
time_parts = re.split(r"[+-]", parts[1])
time_lower, time_upper = self._get_time_bounds(time_parts[0])
# we punt on the timezones - if the user supplies a partial timezone different than
# the default django timezone, its just too complicated to be worth trying to complete,
# we ensure it aligns as a prefix to the configured default timezone instead
# we punt on the timezones - if the user supplies a partial timezone
# different than the default django timezone, its just too complicated to be
# worth trying to complete, we ensure it aligns as a prefix to the
# configured default timezone instead
if len(time_parts) > 1 and parts[1]:
tz_part = get_tz_part(parts[1])
lower_bound = datetime.combine(lower_bound, time_lower)
Expand All @@ -463,18 +467,19 @@ def duration_query(
self, context: Context, parameter: Parameter, incomplete: str
) -> models.Q:
"""
Default completion query builder for duration fields. This method will return a Q object
that will match any value that is greater than the incomplete duration string (or less if
negative). Duration strings are formatted in a subset of the ISO8601 standard. Only day,
hours, minutes and fractional seconds are supported. Year, week and month specifiers are
not.
Default completion query builder for duration fields. This method will return a
Q object that will match any value that is greater than the incomplete duration
string (or less if negative). Duration strings are formatted in a subset of the
ISO8601 standard. Only day, hours, minutes and fractional seconds are supported.
Year, week and month specifiers are not.
:param context: The click context.
:param parameter: The click parameter.
:param incomplete: The incomplete string.
:return: A Q object to use for filtering the queryset.
:raises ValueError: If the incomplete string is not a valid partial duration.
:raises AssertionError: If the incomplete string is not a valid partial duration.
:raises AssertionError: If the incomplete string is not a valid partial
duration.
"""
from django_typer.utils import parse_iso_duration

Expand Down Expand Up @@ -526,8 +531,8 @@ def duration_query(
# or (exclusively) we may be missing time components
if ambiguity is None:
# handle no ambiguity first
# there's no way to be here and have any ambiguity or non-ambiguous microseconds
# ex: PT PT1. PT1M PT1H PT1H1M
# there's no way to be here and have any ambiguity or non-ambiguous
# microseconds ex: PT PT1. PT1M PT1H PT1H1M
if incomplete.endswith("M"):
horizon = timedelta(minutes=1)
elif incomplete.endswith("H"):
Expand Down Expand Up @@ -749,7 +754,8 @@ def __call__(
if str_value:
completions.append(
CompletionItem(
# use the incomplete string prefix incase this was a case insensitive match
# use the incomplete string prefix incase this was a case
# insensitive match
value=incomplete + str_value[len(incomplete) + self._offset :],
help=values[1] if len(values) > 1 else None,
)
Expand Down
17 changes: 10 additions & 7 deletions django_typer/completers/path.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,14 +50,14 @@ def paths(
ctx: Context, param: Parameter, incomplete: str, dir_only: t.Optional[bool] = None
) -> t.List[CompletionItem]:
"""
A completer that completes a path. Relative incomplete paths are interpreted relative to
the current working directory.
A completer that completes a path. Relative incomplete paths are interpreted
relative to the current working directory.
:param ctx: The click context.
:param param: The click parameter.
:param incomplete: The incomplete string.
:param dir_only: Restrict completions to paths to directories only, otherwise complete
directories or files.
:param dir_only: Restrict completions to paths to directories only, otherwise
complete directories or files.
:return: A list of available matching directories
"""

Expand Down Expand Up @@ -87,11 +87,14 @@ def exists(pth: Path) -> bool:
continue
if child.startswith(partial_dir):
to_complete = incomplete[0 : (-len(partial_dir) or None)]
sep = (
""
if not to_complete or to_complete.endswith(separator)
else separator
)
completions.append(
CompletionItem(
f"{to_complete}"
f"{'' if not to_complete or to_complete.endswith(separator) else separator}"
f"{child}",
f"{to_complete}{sep}{child}",
type="dir" if (incomplete_path / child).is_dir() else "file",
)
)
Expand Down
Loading

0 comments on commit f6a1e13

Please sign in to comment.