Skip to content

Commit

Permalink
fix: use standard collections as type annotations (#171)
Browse files Browse the repository at this point in the history
* fix: use standard collections as type annotations

* fix: call jsonschema.validate w/o format_checker

* change: add 'from __future__ import annotations'

* fix: correct type hint

* change: switch to use pytest instead of unittest

* fix: move imports needed for type checks into 'if typing.TYPE_CHECKING' block

* change: add/move configurations from options in tox.ini to pyproject.toml

* fix: line break fix

* fix: remove the import unused

* fix: suppress pylint error, B017
  • Loading branch information
ssato authored Apr 20, 2024
1 parent 5f2d952 commit 015251d
Show file tree
Hide file tree
Showing 71 changed files with 668 additions and 579 deletions.
9 changes: 9 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,15 @@ testpaths = [
]
addopts = "--cov=src -vv -rxXs --cov --cov-report xml"

[tool.pylint."MESSAGES CONTROL"]
disable = [
"import-error",
"invalid-name",
"locally-disabled",
"too-many-ancestors",
"too-many-return-statements",
]

# .. seealso:: https://docs.astral.sh/ruff/settings/#top-level
[tool.ruff]
exclude = [
Expand Down
4 changes: 1 addition & 3 deletions src/anyconfig/api/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,6 @@
"""
from __future__ import annotations

import typing

from .datatypes import MaybeDataT
from ._dump import (
dump, dumps
Expand Down Expand Up @@ -123,7 +121,7 @@
__version__ = "0.14.0"


def version() -> typing.List[str]:
def version() -> list[str]:
"""Version info.
:return: A list of version info, [major, minor, release[, e.g. [0, 8, 2]
Expand Down
17 changes: 10 additions & 7 deletions src/anyconfig/api/_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@
from .utils import are_same_file_types

if typing.TYPE_CHECKING:
import collections.abc

from ..common import (
InDataT, InDataExT
)


MappingT = typing.Dict[str, typing.Any]
MappingT = dict[str, typing.Any]
MaybeParserOrIdOrTypeT = typing.Optional[typing.Union[str, ParserT]]


Expand Down Expand Up @@ -62,8 +64,9 @@ def try_to_load_schema(**options) -> typing.Optional[InDataT]:


def _single_load(
ioi: ioinfo.IOInfo, *, ac_parser: MaybeParserOrIdOrTypeT = None,
ac_template: bool = False, ac_context: typing.Optional[MappingT] = None,
ioi: ioinfo.IOInfo, *,
ac_parser: MaybeParserOrIdOrTypeT = None, ac_template: bool = False,
ac_context: typing.Optional[MappingT] = None,
**options
) -> InDataExT:
"""Load data from a given ``ioi``.
Expand Down Expand Up @@ -168,7 +171,7 @@ def single_load(

def multi_load(
inputs: typing.Union[
typing.Iterable[ioinfo.PathOrIOInfoT], ioinfo.PathOrIOInfoT
collections.abc.Iterable[ioinfo.PathOrIOInfoT], ioinfo.PathOrIOInfoT
], ac_parser: MaybeParserOrIdOrTypeT = None,
*,
ac_template: bool = False, ac_context: typing.Optional[MappingT] = None,
Expand Down Expand Up @@ -275,10 +278,10 @@ def multi_load(

def load(
path_specs: typing.Union[
typing.Iterable[ioinfo.PathOrIOInfoT], ioinfo.PathOrIOInfoT
collections.abc.Iterable[ioinfo.PathOrIOInfoT], ioinfo.PathOrIOInfoT
],
ac_parser: typing.Optional[str] = None, *,
ac_dict: typing.Optional[typing.Callable] = None,
ac_dict: typing.Optional[collections.abc.Callable] = None,
ac_template: bool = False, ac_context: typing.Optional[MappingT] = None,
**options
) -> InDataExT:
Expand Down Expand Up @@ -328,7 +331,7 @@ def load(

def loads(
content: str, ac_parser: MaybeParserOrIdOrTypeT = None, *,
ac_dict: typing.Optional[typing.Callable] = None,
ac_dict: typing.Optional[collections.abc.Callable] = None,
ac_template: typing.Union[str, bool] = False,
ac_context: typing.Optional[MappingT] = None,
**options
Expand Down
2 changes: 1 addition & 1 deletion src/anyconfig/api/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from .. import ioinfo


def are_same_file_types(objs: typing.List[ioinfo.IOInfo]) -> bool:
def are_same_file_types(objs: list[ioinfo.IOInfo]) -> bool:
"""Test if given objects have same types (extensions)."""
if not objs:
return False
Expand Down
8 changes: 5 additions & 3 deletions src/anyconfig/backend/base/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#
# Copyright (C) 2021 - 2024 Satoru SATOH <satoru.satoh @ gmail.com>
# Copyright (C) 2021 - 2024 Satoru SATOH <satoru.satoh gmail.com>
# SPDX-License-Identifier: MIT
#
"""Backend basic classes, functions and constants."""
from __future__ import annotations

import typing

from .compat import BinaryFilesMixin
Expand All @@ -27,8 +29,8 @@


ParserT = typing.TypeVar("ParserT", bound=Parser)
ParsersT = typing.List[ParserT]
ParserClssT = typing.List[typing.Type[ParserT]]
ParsersT = list[ParserT]
ParserClssT = list[type[ParserT]]


__all__ = [
Expand Down
2 changes: 1 addition & 1 deletion src/anyconfig/backend/base/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
class BinaryFilesMixin:
"""Mixin class to open configuration files as a binary data."""

_open_flags: typing.Tuple[str, str] = ("rb", "wb")
_open_flags: tuple[str, str] = ("rb", "wb")

@classmethod
def ropen(cls, filepath: PathOrStrT, **options) -> typing.IO:
Expand Down
7 changes: 5 additions & 2 deletions src/anyconfig/backend/base/datatypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
# SPDX-License-Identifier: MIT
#
"""Utility functions in anyconfig.backend.base."""
from __future__ import annotations

import collections.abc
import pathlib
import typing

Expand All @@ -19,7 +22,7 @@
IoiT = IOInfo
MaybeFilePathT = typing.Optional[PathOrIOInfoT]

GenContainerT = typing.Callable[..., InDataT]
OptionsT = typing.Dict[str, typing.Any]
GenContainerT = collections.abc.Callable[..., InDataT]
OptionsT = dict[str, typing.Any]

PathOrStrT = typing.Union[str, pathlib.Path]
2 changes: 1 addition & 1 deletion src/anyconfig/backend/base/dumpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class DumperMixin:
- _open_write_mode: Backend option to specify write mode passed to open()
"""

_dump_opts: typing.Tuple[str, ...] = ()
_dump_opts: tuple[str, ...] = ()
_open_write_mode: typing.ClassVar[str] = "w"

def wopen(self, filepath: PathOrStrT, **options) -> typing.IO:
Expand Down
6 changes: 3 additions & 3 deletions src/anyconfig/backend/base/loaders.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,10 @@ class LoaderMixin:
- _open_read_mode: Backend option to specify read mode passed to open()
"""

_load_opts: typing.Tuple[str, ...] = ()
_load_opts: tuple[str, ...] = ()
_ordered: typing.ClassVar[bool] = False
_allow_primitives: typing.ClassVar[bool] = False
_dict_opts: typing.Tuple[str, ...] = ()
_dict_opts: tuple[str, ...] = ()
_open_read_mode: typing.ClassVar[str] = "r"

@classmethod
Expand All @@ -66,7 +66,7 @@ def allow_primitives(cls) -> bool:
return cls._allow_primitives

@classmethod
def dict_options(cls) -> typing.Tuple[str, ...]:
def dict_options(cls) -> tuple[str, ...]:
"""Get the list of dict factory options."""
return cls._dict_opts

Expand Down
5 changes: 3 additions & 2 deletions src/anyconfig/backend/base/parsers.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"""
from __future__ import annotations

import collections.abc
import typing

from ...models import processor
Expand Down Expand Up @@ -68,8 +69,8 @@ class StreamParser(Parser, FromStreamLoaderMixin, ToStreamDumperMixin):
"""


LoadFnT = typing.Callable[..., InDataExT]
DumpFnT = typing.Callable[..., str]
LoadFnT = collections.abc.Callable[..., InDataExT]
DumpFnT = collections.abc.Callable[..., str]


def load_with_fn(
Expand Down
9 changes: 6 additions & 3 deletions src/anyconfig/backend/base/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import pathlib
import typing

if typing.TYPE_CHECKING:
import collections.abc


def not_implemented(
*_args, **_options
Expand All @@ -26,8 +29,8 @@ def ensure_outdir_exists(filepath: typing.Union[str, pathlib.Path]) -> None:


def to_method(
func: typing.Callable[..., typing.Any]
) -> typing.Callable[..., typing.Any]:
func: collections.abc.Callable[..., typing.Any]
) -> collections.abc.Callable[..., typing.Any]:
"""Lift :func:`func` to a method.
It will be called with the first argument 'self' ignored.
Expand All @@ -37,7 +40,7 @@ def to_method(
@functools.wraps(func)
def wrapper(
*args, **kwargs
) -> typing.Callable[..., typing.Any]:
) -> collections.abc.Callable[..., typing.Any]:
"""Original function decorated."""
return func(*args[1:], **kwargs)

Expand Down
36 changes: 20 additions & 16 deletions src/anyconfig/backend/ini/configparser.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
from ... import parser, utils
from .. import base

if typing.TYPE_CHECKING:
import collections.abc


_SEP = ","
try:
Expand All @@ -49,7 +52,7 @@
DEFAULTSECT: str = "DEFAULT" # type: ignore[no-redef]


_QUOTED_RE: typing.Pattern = re.compile(
_QUOTED_RE: re.Pattern = re.compile(
r"^("
r'".*"'
r"|"
Expand All @@ -59,7 +62,7 @@


def parse(
val_s: str, sep: str = _SEP, quoted_re: typing.Pattern = _QUOTED_RE
val_s: str, sep: str = _SEP, quoted_re: re.Pattern = _QUOTED_RE
) -> typing.Any:
"""Parse expression.
Expand Down Expand Up @@ -91,9 +94,10 @@ def _to_s(val: typing.Any, sep: str = ", ") -> str:
return str(val)


def parsed_items(items: typing.Iterable[typing.Tuple[str, typing.Any]],
sep: str = _SEP, **options
) -> typing.Iterator[typing.Tuple[str, typing.Any]]:
def parsed_items(
items: collections.abc.Iterable[tuple[str, typing.Any]],
sep: str = _SEP, **options
) -> collections.abc.Iterator[tuple[str, typing.Any]]:
"""Parse an iterable of items.
:param items: List of pairs, [(key, value)], or generator yields pairs
Expand All @@ -105,9 +109,9 @@ def parsed_items(items: typing.Iterable[typing.Tuple[str, typing.Any]],
yield (key, __parse(val, sep)) # type: ignore[operator]


def _make_parser(**kwargs
) -> typing.Tuple[typing.Dict[str, typing.Any],
configparser.ConfigParser]:
def _make_parser(
**kwargs
) -> tuple[dict[str, typing.Any], configparser.ConfigParser]:
"""Make an instance of configparser.ConfigParser."""
# Optional arguments for configparser.ConfigParser{,readfp}
kwargs_0 = utils.filter_options(
Expand All @@ -128,8 +132,8 @@ def _make_parser(**kwargs


def _load(
stream: typing.IO, container: base.GenContainerT, sep: str = _SEP,
dkey: str = DEFAULTSECT, **kwargs
stream: typing.IO, container: base.GenContainerT,
sep: str = _SEP, dkey: str = DEFAULTSECT, **kwargs
) -> base.InDataT:
"""Load data from ``stream`` of which file should be in INI format.
Expand Down Expand Up @@ -157,8 +161,8 @@ def _load(


def _dumps_itr(
cnf: typing.Dict[str, typing.Any], dkey: str = DEFAULTSECT
) -> typing.Iterator[str]:
cnf: dict[str, typing.Any], dkey: str = DEFAULTSECT
) -> collections.abc.Iterator[str]:
"""Dump data iterably.
:param cnf: Configuration data to dump
Expand All @@ -175,7 +179,7 @@ def _dumps_itr(
yield "" # it will be a separator between each sections.


def _dumps(cnf: typing.Dict[str, typing.Any], **_kwargs) -> str:
def _dumps(cnf: dict[str, typing.Any], **_kwargs) -> str:
"""Dump data as a str.
:param cnf: Configuration data to dump
Expand All @@ -193,12 +197,12 @@ class Parser(base.Parser, base.FromStreamLoaderMixin,

_cid: typing.ClassVar[str] = "ini.configparser"
_type: typing.ClassVar[str] = "ini"
_extensions: typing.Tuple[str, ...] = ("ini", )
_load_opts: typing.Tuple[str, ...] = (
_extensions: tuple[str, ...] = ("ini", )
_load_opts: tuple[str, ...] = (
"defaults", "dict_type", "allow_no_value", "filename",
"ac_parse_value", "strict"
)
_dict_opts: typing.Tuple[str, ...] = ("dict_type", )
_dict_opts: tuple[str, ...] = ("dict_type", )

dump_to_string = base.to_method(_dumps)
load_from_stream = base.to_method(_load)
12 changes: 5 additions & 7 deletions src/anyconfig/backend/json/common.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
#
# Copyright (C) 2018 - 2024 Satoru SATOH <satoru.satoh@gmail.com>
# Copyright (C) 2018 - 2024 Satoru SATOH <satoru.satoh gmail.com>
# SPDX-License-Identifier: MIT
#
"""Globals, functions common in some JSON backend modules.
Expand All @@ -15,15 +15,15 @@
from .. import base


JSON_LOAD_OPTS: typing.Tuple[str, ...] = (
JSON_LOAD_OPTS: tuple[str, ...] = (
"cls", "object_hook", "parse_float", "parse_int",
"parse_constant", "object_pairs_hook"
)
JSON_DUMP_OPTS: typing.Tuple[str, ...] = (
JSON_DUMP_OPTS: tuple[str, ...] = (
"skipkeys", "ensure_ascii", "check_circular", "allow_nan",
"cls", "indent", "separators", "default", "sort_keys"
)
JSON_DICT_OPTS: typing.Tuple[str, ...] = (
JSON_DICT_OPTS: tuple[str, ...] = (
"object_pairs_hook", "object_hook"
)

Expand All @@ -33,13 +33,11 @@ class Parser(base.StringStreamFnParser):

_cid: typing.ClassVar[str] = "json.stdlib"
_type: typing.ClassVar[str] = "json"
_extensions: typing.Tuple[str, ...] = ("json", "jsn", "js")
_extensions: tuple[str, ...] = ("json", "jsn", "js")
_ordered: typing.ClassVar[bool] = True
_allow_primitives: typing.ClassVar[bool] = True

# .. note:: These may be overwritten.
_load_opts = JSON_LOAD_OPTS
_dump_opts = JSON_DUMP_OPTS
_dict_opts = JSON_DICT_OPTS

# vim:sw=4:ts=4:et:
6 changes: 3 additions & 3 deletions src/anyconfig/backend/pickle/stdlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,16 +35,16 @@
from .. import base


LOAD_OPTS: typing.Tuple[str, ...] = ("fix_imports", "encoding", "errors")
DUMP_OPTS: typing.Tuple[str, ...] = ("protocol", "fix_imports")
LOAD_OPTS: tuple[str, ...] = ("fix_imports", "encoding", "errors")
DUMP_OPTS: tuple[str, ...] = ("protocol", "fix_imports")


class Parser(base.StringStreamFnParser):
"""Parser for Pickle files."""

_cid: typing.ClassVar[str] = "pickle.stdlib"
_type: typing.ClassVar[str] = "pickle"
_extensions: typing.Tuple[str, ...] = ("pkl", "pickle")
_extensions: tuple[str, ...] = ("pkl", "pickle")
_open_read_mode: typing.ClassVar[str] = "rb"
_open_write_mode: typing.ClassVar[str] = "wb"

Expand Down
Loading

0 comments on commit 015251d

Please sign in to comment.