diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 5ebde9e..0e1f36c 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,7 +11,7 @@ jobs: timeout-minutes: 4 strategy: matrix: - python-version: ['pypy3', '3.9', '3.10', '3.11', '3.12'] # Maybe soon?, '3.13'] + python-version: ['pypy3.9', 'pypy3.10', '3.9', '3.10', '3.11', '3.12'] # Maybe soon?, '3.13'] steps: - uses: actions/checkout@v4 diff --git a/python_utils/__init__.py b/python_utils/__init__.py index 9a6c629..7c4242c 100644 --- a/python_utils/__init__.py +++ b/python_utils/__init__.py @@ -83,44 +83,44 @@ ) __all__ = [ + 'CastedDict', + 'LazyCastedDict', + 'Logged', + 'LoggerBase', + 'UniqueList', + 'abatcher', + 'acount', 'aio', - 'generators', + 'aio_generator_timeout_detector', + 'aio_generator_timeout_detector_decorator', + 'aio_timeout_generator', + 'batcher', + 'camel_to_underscore', 'converters', 'decorators', + 'delta_to_seconds', + 'delta_to_seconds_or_none', + 'format_time', 'formatters', + 'generators', + 'get_terminal_size', 'import_', + 'import_global', + 'listify', 'logger', - 'terminal', - 'time', - 'types', - 'to_int', - 'to_float', - 'to_unicode', - 'to_str', - 'scale_1024', + 'raise_exception', 'remap', + 'reraise', + 'scale_1024', 'set_attributes', - 'listify', - 'camel_to_underscore', - 'timesince', - 'import_global', - 'get_terminal_size', + 'terminal', + 'time', 'timedelta_to_seconds', - 'format_time', 'timeout_generator', - 'acount', - 'abatcher', - 'batcher', - 'aio_timeout_generator', - 'aio_generator_timeout_detector_decorator', - 'aio_generator_timeout_detector', - 'delta_to_seconds', - 'delta_to_seconds_or_none', - 'reraise', - 'raise_exception', - 'Logged', - 'LoggerBase', - 'CastedDict', - 'LazyCastedDict', - 'UniqueList', + 'timesince', + 'to_float', + 'to_int', + 'to_str', + 'to_unicode', + 'types', ] diff --git a/python_utils/formatters.py b/python_utils/formatters.py index 4e634e4..44ec873 100644 --- a/python_utils/formatters.py +++ b/python_utils/formatters.py @@ -161,11 +161,11 @@ def timesince( output: types.List[str] = [] for period, singular, plural in periods: - if int(period): - if int(period) == 1: - output.append('%d %s' % (period, singular)) - else: - output.append('%d %s' % (period, plural)) + int_period = int(period) + if int_period == 1: + output.append(f'{int_period} {singular}') + elif int_period: + output.append(f'{int_period} {plural}') if output: return f'{" and ".join(output[:2])} ago' diff --git a/python_utils/logger.py b/python_utils/logger.py index bd988c5..ff20279 100644 --- a/python_utils/logger.py +++ b/python_utils/logger.py @@ -331,7 +331,7 @@ def __get_name(cls, *name_parts: str) -> str: LoggerBase._LoggerBase__get_name(*name_parts), # type: ignore[attr-defined] # pyright: ignore[reportUnknownMemberType, reportUnknownVariableType, reportAttributeAccessIssue] ) - def __new__(cls, *args: types.Any, **kwargs: types.Any) -> 'Logged': + def __new__(cls, *args: types.Any, **kwargs: types.Any) -> types.Self: """ Create a new instance of the class and initialize the logger. diff --git a/python_utils/types.py b/python_utils/types.py index 90bcd2a..ab89c43 100644 --- a/python_utils/types.py +++ b/python_utils/types.py @@ -54,128 +54,128 @@ ] __all__ = [ - 'OptionalScope', - 'Number', - 'DecimalNumber', - 'delta_type', - 'timestamp_type', + 'IO', + 'TYPE_CHECKING', + # ABCs (from collections.abc). + 'AbstractSet', # The types from the typing module. # Super-special typing primitives. 'Annotated', 'Any', + # One-off things. + 'AnyStr', + 'AsyncContextManager', + 'AsyncGenerator', + 'AsyncGeneratorType', + 'AsyncIterable', + 'AsyncIterator', + 'Awaitable', + # Other concrete types. + 'BinaryIO', + 'BuiltinFunctionType', + 'BuiltinMethodType', + 'ByteString', 'Callable', + # Concrete collection types. + 'ChainMap', + 'ClassMethodDescriptorType', 'ClassVar', + 'CodeType', + 'Collection', 'Concatenate', + 'Container', + 'ContextManager', + 'Coroutine', + 'CoroutineType', + 'Counter', + 'DecimalNumber', + 'DefaultDict', + 'Deque', + 'Dict', + 'DynamicClassAttribute', 'Final', 'ForwardRef', + 'FrameType', + 'FrozenSet', + # Types from the `types` module. + 'FunctionType', + 'Generator', + 'GeneratorType', 'Generic', - 'Literal', - 'SupportsIndex', - 'Optional', - 'ParamSpec', - 'ParamSpecArgs', - 'ParamSpecKwargs', - 'Protocol', - 'Tuple', - 'Type', - 'TypeVar', - 'Union', - # ABCs (from collections.abc). - 'AbstractSet', - 'ByteString', - 'Container', - 'ContextManager', + 'GetSetDescriptorType', 'Hashable', 'ItemsView', 'Iterable', 'Iterator', 'KeysView', + 'LambdaType', + 'List', + 'Literal', 'Mapping', + 'MappingProxyType', 'MappingView', + 'Match', + 'MemberDescriptorType', + 'MethodDescriptorType', + 'MethodType', + 'MethodWrapperType', + 'ModuleType', 'MutableMapping', 'MutableSequence', 'MutableSet', - 'Sequence', - 'Sized', - 'ValuesView', - 'Awaitable', - 'AsyncIterator', - 'AsyncIterable', - 'Coroutine', - 'Collection', - 'AsyncGenerator', - 'AsyncContextManager', + 'NamedTuple', # Not really a type. + 'NewType', + 'NoReturn', + 'Number', + 'Optional', + 'OptionalScope', + 'OrderedDict', + 'ParamSpec', + 'ParamSpecArgs', + 'ParamSpecKwargs', + 'Pattern', + 'Protocol', # Structural checks, a.k.a. protocols. 'Reversible', + 'Sequence', + 'Set', + 'SimpleNamespace', + 'Sized', 'SupportsAbs', 'SupportsBytes', 'SupportsComplex', 'SupportsFloat', 'SupportsIndex', + 'SupportsIndex', 'SupportsInt', 'SupportsRound', - # Concrete collection types. - 'ChainMap', - 'Counter', - 'Deque', - 'Dict', - 'DefaultDict', - 'List', - 'OrderedDict', - 'Set', - 'FrozenSet', - 'NamedTuple', # Not really a type. - 'TypedDict', # Not really a type. - 'Generator', - # Other concrete types. - 'BinaryIO', - 'IO', - 'Match', - 'Pattern', + 'Text', 'TextIO', - # One-off things. - 'AnyStr', + 'TracebackType', + 'TracebackType', + 'Tuple', + 'Type', + 'TypeAlias', + 'TypeGuard', + 'TypeVar', + 'TypedDict', # Not really a type. + 'Union', + 'ValuesView', + 'WrapperDescriptorType', 'cast', + 'coroutine', + 'delta_type', 'final', 'get_args', 'get_origin', 'get_type_hints', 'is_typeddict', - 'NewType', + 'new_class', 'no_type_check', 'no_type_check_decorator', - 'NoReturn', 'overload', - 'runtime_checkable', - 'Text', - 'TYPE_CHECKING', - 'TypeAlias', - 'TypeGuard', - 'TracebackType', - # Types from the `types` module. - 'FunctionType', - 'LambdaType', - 'CodeType', - 'MappingProxyType', - 'SimpleNamespace', - 'GeneratorType', - 'CoroutineType', - 'AsyncGeneratorType', - 'MethodType', - 'BuiltinFunctionType', - 'BuiltinMethodType', - 'WrapperDescriptorType', - 'MethodWrapperType', - 'MethodDescriptorType', - 'ClassMethodDescriptorType', - 'ModuleType', - 'TracebackType', - 'FrameType', - 'GetSetDescriptorType', - 'MemberDescriptorType', - 'new_class', - 'resolve_bases', 'prepare_class', - 'DynamicClassAttribute', - 'coroutine', + 'resolve_bases', + 'runtime_checkable', + 'timestamp_type', ] diff --git a/ruff.toml b/ruff.toml index 1ce08a4..294cb3c 100644 --- a/ruff.toml +++ b/ruff.toml @@ -6,10 +6,15 @@ target-version = 'py39' exclude = [ '.venv', '.tox', + # Ignore local test files/directories/old-stuff 'test.py', + '*_old.py', ] -lint.ignore = [ +line-length = 79 + +[lint] +ignore = [ 'A001', # Variable {name} is shadowing a Python builtin 'A002', # Argument {name} is shadowing a Python builtin 'A003', # Class attribute {name} is shadowing a Python builtin @@ -27,13 +32,14 @@ lint.ignore = [ 'RET506', # Unnecessary `else` after `raise` statement 'Q001', # Remove bad quotes 'Q002', # Remove bad quotes + 'FA100', # Missing `from __future__ import annotations`, but uses `typing.Optional` 'COM812', # Missing trailing comma in a list 'ISC001', # String concatenation with implicit str conversion 'SIM108', # Ternary operators are not always more readable - 'RUF100', # Unused `noqa` directive. These vary per Python version so this warning is often incorrect. + 'RUF100', # Unused noqa directives. Due to multiple Python versions, we need to keep them ] -line-length = 79 -lint.select = [ + +select = [ 'A', # flake8-builtins 'ASYNC', # flake8 async checker 'B', # flake8-bugbear @@ -105,3 +111,4 @@ max-line-length = 79 [lint.flake8-pytest-style] mark-parentheses = true +