GNXSOFT.COM
This commit is contained in:
198
gnx-react/venv/lib/python3.12/site-packages/celery/utils/text.py
Normal file
198
gnx-react/venv/lib/python3.12/site-packages/celery/utils/text.py
Normal file
@@ -0,0 +1,198 @@
|
||||
"""Text formatting utilities."""
|
||||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
import re
|
||||
from functools import partial
|
||||
from pprint import pformat
|
||||
from re import Match
|
||||
from textwrap import fill
|
||||
from typing import Any, Callable, Pattern
|
||||
|
||||
__all__ = (
|
||||
'abbr', 'abbrtask', 'dedent', 'dedent_initial',
|
||||
'ensure_newlines', 'ensure_sep',
|
||||
'fill_paragraphs', 'indent', 'join',
|
||||
'pluralize', 'pretty', 'str_to_list', 'simple_format', 'truncate',
|
||||
)
|
||||
|
||||
UNKNOWN_SIMPLE_FORMAT_KEY = """
|
||||
Unknown format %{0} in string {1!r}.
|
||||
Possible causes: Did you forget to escape the expand sign (use '%%{0!r}'),
|
||||
or did you escape and the value was expanded twice? (%%N -> %N -> %hostname)?
|
||||
""".strip()
|
||||
|
||||
RE_FORMAT = re.compile(r'%(\w)')
|
||||
|
||||
|
||||
def str_to_list(s: str) -> list[str]:
|
||||
"""Convert string to list."""
|
||||
if isinstance(s, str):
|
||||
return s.split(',')
|
||||
return s
|
||||
|
||||
|
||||
def dedent_initial(s: str, n: int = 4) -> str:
|
||||
"""Remove indentation from first line of text."""
|
||||
return s[n:] if s[:n] == ' ' * n else s
|
||||
|
||||
|
||||
def dedent(s: str, sep: str = '\n') -> str:
|
||||
"""Remove indentation."""
|
||||
return sep.join(dedent_initial(l) for l in s.splitlines())
|
||||
|
||||
|
||||
def fill_paragraphs(s: str, width: int, sep: str = '\n') -> str:
|
||||
"""Fill paragraphs with newlines (or custom separator)."""
|
||||
return sep.join(fill(p, width) for p in s.split(sep))
|
||||
|
||||
|
||||
def join(l: list[str], sep: str = '\n') -> str:
|
||||
"""Concatenate list of strings."""
|
||||
return sep.join(v for v in l if v)
|
||||
|
||||
|
||||
def ensure_sep(sep: str, s: str, n: int = 2) -> str:
|
||||
"""Ensure text s ends in separator sep'."""
|
||||
return s + sep * (n - s.count(sep))
|
||||
|
||||
|
||||
ensure_newlines = partial(ensure_sep, '\n')
|
||||
|
||||
|
||||
def abbr(S: str, max: int, ellipsis: str | bool = '...') -> str:
|
||||
"""Abbreviate word."""
|
||||
if S is None:
|
||||
return '???'
|
||||
if len(S) > max:
|
||||
return isinstance(ellipsis, str) and (
|
||||
S[: max - len(ellipsis)] + ellipsis) or S[: max]
|
||||
return S
|
||||
|
||||
|
||||
def abbrtask(S: str, max: int) -> str:
|
||||
"""Abbreviate task name."""
|
||||
if S is None:
|
||||
return '???'
|
||||
if len(S) > max:
|
||||
module, _, cls = S.rpartition('.')
|
||||
module = abbr(module, max - len(cls) - 3, False)
|
||||
return module + '[.]' + cls
|
||||
return S
|
||||
|
||||
|
||||
def indent(t: str, indent: int = 0, sep: str = '\n') -> str:
|
||||
"""Indent text."""
|
||||
return sep.join(' ' * indent + p for p in t.split(sep))
|
||||
|
||||
|
||||
def truncate(s: str, maxlen: int = 128, suffix: str = '...') -> str:
|
||||
"""Truncate text to a maximum number of characters."""
|
||||
if maxlen and len(s) >= maxlen:
|
||||
return s[:maxlen].rsplit(' ', 1)[0] + suffix
|
||||
return s
|
||||
|
||||
|
||||
def pluralize(n: float, text: str, suffix: str = 's') -> str:
|
||||
"""Pluralize term when n is greater than one."""
|
||||
if n != 1:
|
||||
return text + suffix
|
||||
return text
|
||||
|
||||
|
||||
def pretty(value: str, width: int = 80, nl_width: int = 80, sep: str = '\n', **
|
||||
kw: Any) -> str:
|
||||
"""Format value for printing to console."""
|
||||
if isinstance(value, dict):
|
||||
return f'{sep} {pformat(value, 4, nl_width)[1:]}'
|
||||
elif isinstance(value, tuple):
|
||||
return '{}{}{}'.format(
|
||||
sep, ' ' * 4, pformat(value, width=nl_width, **kw),
|
||||
)
|
||||
else:
|
||||
return pformat(value, width=width, **kw)
|
||||
|
||||
|
||||
def match_case(s: str, other: str) -> str:
|
||||
return s.upper() if other.isupper() else s.lower()
|
||||
|
||||
|
||||
def simple_format(
|
||||
s: str, keys: dict[str, str | Callable],
|
||||
pattern: Pattern[str] = RE_FORMAT, expand: str = r'\1') -> str:
|
||||
"""Format string, expanding abbreviations in keys'."""
|
||||
if s:
|
||||
keys.setdefault('%', '%')
|
||||
|
||||
def resolve(match: Match) -> str | Any:
|
||||
key = match.expand(expand)
|
||||
try:
|
||||
resolver = keys[key]
|
||||
except KeyError:
|
||||
raise ValueError(UNKNOWN_SIMPLE_FORMAT_KEY.format(key, s))
|
||||
if callable(resolver):
|
||||
return resolver()
|
||||
return resolver
|
||||
|
||||
return pattern.sub(resolve, s)
|
||||
return s
|
||||
|
||||
|
||||
def remove_repeating_from_task(task_name: str, s: str) -> str:
|
||||
"""Given task name, remove repeating module names.
|
||||
|
||||
Example:
|
||||
>>> remove_repeating_from_task(
|
||||
... 'tasks.add',
|
||||
... 'tasks.add(2, 2), tasks.mul(3), tasks.div(4)')
|
||||
'tasks.add(2, 2), mul(3), div(4)'
|
||||
"""
|
||||
# This is used by e.g. repr(chain), to remove repeating module names.
|
||||
# - extract the module part of the task name
|
||||
module = str(task_name).rpartition('.')[0] + '.'
|
||||
return remove_repeating(module, s)
|
||||
|
||||
|
||||
def remove_repeating(substr: str, s: str) -> str:
|
||||
"""Remove repeating module names from string.
|
||||
|
||||
Arguments:
|
||||
task_name (str): Task name (full path including module),
|
||||
to use as the basis for removing module names.
|
||||
s (str): The string we want to work on.
|
||||
|
||||
Example:
|
||||
|
||||
>>> _shorten_names(
|
||||
... 'x.tasks.add',
|
||||
... 'x.tasks.add(2, 2) | x.tasks.add(4) | x.tasks.mul(8)',
|
||||
... )
|
||||
'x.tasks.add(2, 2) | add(4) | mul(8)'
|
||||
"""
|
||||
# find the first occurrence of substr in the string.
|
||||
index = s.find(substr)
|
||||
if index >= 0:
|
||||
return ''.join([
|
||||
# leave the first occurrence of substr untouched.
|
||||
s[:index + len(substr)],
|
||||
# strip seen substr from the rest of the string.
|
||||
s[index + len(substr):].replace(substr, ''),
|
||||
])
|
||||
return s
|
||||
|
||||
|
||||
StringIO = io.StringIO
|
||||
_SIO_write = StringIO.write
|
||||
_SIO_init = StringIO.__init__
|
||||
|
||||
|
||||
class WhateverIO(StringIO):
|
||||
"""StringIO that takes bytes or str."""
|
||||
|
||||
def __init__(
|
||||
self, v: bytes | str | None = None, *a: Any, **kw: Any) -> None:
|
||||
_SIO_init(self, v.decode() if isinstance(v, bytes) else v, *a, **kw)
|
||||
|
||||
def write(self, data: bytes | str) -> int:
|
||||
return _SIO_write(self, data.decode()
|
||||
if isinstance(data, bytes) else data)
|
||||
Reference in New Issue
Block a user