From e6345d60a7926bd413d3d7238ba06f7c81a7faf9 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 24 Jul 2021 17:10:32 +0100 Subject: Replace all Typeguard with cast, revert update to typing-extensions==3.10.0 --- git/config.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'git/config.py') diff --git a/git/config.py b/git/config.py index 345cb40e..b25707b2 100644 --- a/git/config.py +++ b/git/config.py @@ -34,7 +34,7 @@ import configparser as cp from typing import (Any, Callable, IO, List, Dict, Sequence, TYPE_CHECKING, Tuple, Union, cast, overload) -from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never, is_config_level +from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never if TYPE_CHECKING: from git.repo.base import Repo @@ -309,9 +309,9 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # else: if config_level is None: if read_only: - self._file_or_files = [get_config_path(f) + self._file_or_files = [get_config_path(cast(Lit_config_levels, f)) for f in CONFIG_LEVELS - if is_config_level(f) and f != 'repository'] + if f != 'repository'] else: raise ValueError("No configuration level or configuration files specified") else: -- cgit v1.2.1 From d812818cb20c39e0bb5609186214ea4bcc18c047 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 24 Jul 2021 22:05:06 +0100 Subject: Rmv with_metaclass shim, make section constraint generic wrt its configparser type --- git/config.py | 55 ++++++++++++++++++++++++------------------------------- 1 file changed, 24 insertions(+), 31 deletions(-) (limited to 'git/config.py') diff --git a/git/config.py b/git/config.py index b25707b2..76200f31 100644 --- a/git/config.py +++ b/git/config.py @@ -14,12 +14,10 @@ import logging import os import re import fnmatch -from collections import OrderedDict from git.compat import ( defenc, force_text, - with_metaclass, is_win, ) @@ -31,15 +29,16 @@ import configparser as cp # typing------------------------------------------------------- -from typing import (Any, Callable, IO, List, Dict, Sequence, - TYPE_CHECKING, Tuple, Union, cast, overload) +from typing import (Any, Callable, Generic, IO, List, Dict, Sequence, + TYPE_CHECKING, Tuple, TypeVar, Union, cast, overload) -from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never +from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never, _T if TYPE_CHECKING: from git.repo.base import Repo from io import BytesIO +T_ConfigParser = TypeVar('T_ConfigParser', bound='GitConfigParser') # ------------------------------------------------------------- __all__ = ('GitConfigParser', 'SectionConstraint') @@ -61,7 +60,6 @@ CONDITIONAL_INCLUDE_REGEXP = re.compile(r"(?<=includeIf )\"(gitdir|gitdir/i|onbr class MetaParserBuilder(abc.ABCMeta): - """Utlity class wrapping base-class methods into decorators that assure read-only properties""" def __new__(cls, name: str, bases: TBD, clsdict: Dict[str, Any]) -> TBD: """ @@ -115,7 +113,7 @@ def set_dirty_and_flush_changes(non_const_func: Callable) -> Callable: return flush_changes -class SectionConstraint(object): +class SectionConstraint(Generic[T_ConfigParser]): """Constrains a ConfigParser to only option commands which are constrained to always use the section we have been initialized with. @@ -128,7 +126,7 @@ class SectionConstraint(object): _valid_attrs_ = ("get_value", "set_value", "get", "set", "getint", "getfloat", "getboolean", "has_option", "remove_section", "remove_option", "options") - def __init__(self, config: 'GitConfigParser', section: str) -> None: + def __init__(self, config: T_ConfigParser, section: str) -> None: self._config = config self._section_name = section @@ -149,7 +147,7 @@ class SectionConstraint(object): return getattr(self._config, method)(self._section_name, *args, **kwargs) @property - def config(self) -> 'GitConfigParser': + def config(self) -> T_ConfigParser: """return: Configparser instance we constrain""" return self._config @@ -157,7 +155,7 @@ class SectionConstraint(object): """Equivalent to GitConfigParser.release(), which is called on our underlying parser instance""" return self._config.release() - def __enter__(self) -> 'SectionConstraint': + def __enter__(self) -> 'SectionConstraint[T_ConfigParser]': self._config.__enter__() return self @@ -165,10 +163,10 @@ class SectionConstraint(object): self._config.__exit__(exception_type, exception_value, traceback) -class _OMD(OrderedDict): +class _OMD(Dict[str, List[_T]]): """Ordered multi-dict.""" - def __setitem__(self, key: str, value: Any) -> None: + def __setitem__(self, key: str, value: _T) -> None: # type: ignore[override] super(_OMD, self).__setitem__(key, [value]) def add(self, key: str, value: Any) -> None: @@ -177,7 +175,7 @@ class _OMD(OrderedDict): return None super(_OMD, self).__getitem__(key).append(value) - def setall(self, key: str, values: Any) -> None: + def setall(self, key: str, values: List[_T]) -> None: super(_OMD, self).__setitem__(key, values) def __getitem__(self, key: str) -> Any: @@ -194,25 +192,17 @@ class _OMD(OrderedDict): prior = super(_OMD, self).__getitem__(key) prior[-1] = value - @overload - def get(self, key: str, default: None = ...) -> None: - ... - - @overload - def get(self, key: str, default: Any = ...) -> Any: - ... - - def get(self, key: str, default: Union[Any, None] = None) -> Union[Any, None]: - return super(_OMD, self).get(key, [default])[-1] + def get(self, key: str, default: Union[_T, None] = None) -> Union[_T, None]: # type: ignore + return super(_OMD, self).get(key, [default])[-1] # type: ignore - def getall(self, key: str) -> Any: + def getall(self, key: str) -> List[_T]: return super(_OMD, self).__getitem__(key) - def items(self) -> List[Tuple[str, Any]]: # type: ignore[override] + def items(self) -> List[Tuple[str, _T]]: # type: ignore[override] """List of (key, last value for key).""" return [(k, self[k]) for k in self] - def items_all(self) -> List[Tuple[str, List[Any]]]: + def items_all(self) -> List[Tuple[str, List[_T]]]: """List of (key, list of values for key).""" return [(k, self.getall(k)) for k in self] @@ -238,7 +228,7 @@ def get_config_path(config_level: Lit_config_levels) -> str: assert_never(config_level, ValueError(f"Invalid configuration level: {config_level!r}")) -class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # type: ignore ## mypy does not understand dynamic class creation # noqa: E501 +class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder): """Implements specifics required to read git style configuration files. @@ -298,7 +288,10 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # :param repo: Reference to repository to use if [includeIf] sections are found in configuration files. """ - cp.RawConfigParser.__init__(self, dict_type=_OMD) + cp.RawConfigParser.__init__(self, dict_type=_OMD) # type: ignore[arg-type] + self._dict: Callable[..., _OMD] # type: ignore[assignment] # mypy/typeshed bug + self._defaults: _OMD # type: ignore[assignment] # mypy/typeshed bug + self._sections: _OMD # type: ignore[assignment] # mypy/typeshed bug # Used in python 3, needs to stay in sync with sections for underlying implementation to work if not hasattr(self, '_proxies'): @@ -424,7 +417,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # # is it a section header? mo = self.SECTCRE.match(line.strip()) if not is_multi_line and mo: - sectname = mo.group('header').strip() + sectname: str = mo.group('header').strip() if sectname in self._sections: cursect = self._sections[sectname] elif sectname == cp.DEFAULTSECT: @@ -535,7 +528,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # return paths - def read(self) -> None: + def read(self) -> None: # type: ignore[override] """Reads the data stored in the files we have been initialized with. It will ignore files that cannot be read, possibly leaving an empty configuration @@ -626,7 +619,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # for name, value in self._sections.items(): write_section(name, value) - def items(self, section_name: str) -> List[Tuple[str, str]]: + def items(self, section_name: str) -> List[Tuple[str, str]]: # type: ignore[override] """:return: list((option, value), ...) pairs of all items in the given section""" return [(k, v) for k, v in super(GitConfigParser, self).items(section_name) if k != '__name__'] -- cgit v1.2.1 From cb5688d65f4f7bc5735e5403e71094745e9a2a0b Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 24 Jul 2021 22:15:42 +0100 Subject: Readd with_metaclass shim --- git/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'git/config.py') diff --git a/git/config.py b/git/config.py index 76200f31..b0ac8ff5 100644 --- a/git/config.py +++ b/git/config.py @@ -19,6 +19,7 @@ from git.compat import ( defenc, force_text, is_win, + with_metaclass, ) from git.util import LockFile @@ -228,7 +229,7 @@ def get_config_path(config_level: Lit_config_levels) -> str: assert_never(config_level, ValueError(f"Invalid configuration level: {config_level!r}")) -class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder): +class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # type: ignore ## mypy does not understand dynamic class creation # noqa: E501 """Implements specifics required to read git style configuration files. -- cgit v1.2.1 From 77ee247a9018c6964642cf31a2690f3a4367649c Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 24 Jul 2021 22:19:57 +0100 Subject: change ordereddict to typing.ordereddict --- git/config.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'git/config.py') diff --git a/git/config.py b/git/config.py index b0ac8ff5..17696fc5 100644 --- a/git/config.py +++ b/git/config.py @@ -7,6 +7,7 @@ configuration files""" import abc +from typing import OrderedDict from functools import wraps import inspect from io import BufferedReader, IOBase @@ -164,7 +165,7 @@ class SectionConstraint(Generic[T_ConfigParser]): self._config.__exit__(exception_type, exception_value, traceback) -class _OMD(Dict[str, List[_T]]): +class _OMD(OrderedDict[str, List[_T]]): """Ordered multi-dict.""" def __setitem__(self, key: str, value: _T) -> None: # type: ignore[override] -- cgit v1.2.1 From 981cfa8d6161d83383610733cf86487ced7a4e6c Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 24 Jul 2021 22:25:22 +0100 Subject: import ordereddict from types --- git/config.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'git/config.py') diff --git a/git/config.py b/git/config.py index 17696fc5..c4303270 100644 --- a/git/config.py +++ b/git/config.py @@ -7,7 +7,6 @@ configuration files""" import abc -from typing import OrderedDict from functools import wraps import inspect from io import BufferedReader, IOBase @@ -34,7 +33,7 @@ import configparser as cp from typing import (Any, Callable, Generic, IO, List, Dict, Sequence, TYPE_CHECKING, Tuple, TypeVar, Union, cast, overload) -from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never, _T +from git.types import Lit_config_levels, ConfigLevels_Tup, OrderedDict, PathLike, TBD, assert_never, _T if TYPE_CHECKING: from git.repo.base import Repo -- cgit v1.2.1 From 6d6aae11af2f1acc6aa384ed43e6897da8fe7057 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 24 Jul 2021 22:34:20 +0100 Subject: fix rdereddict, cannot subclass typing-extensiosn version --- git/config.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'git/config.py') diff --git a/git/config.py b/git/config.py index c4303270..51744bfe 100644 --- a/git/config.py +++ b/git/config.py @@ -6,6 +6,7 @@ """Module containing module parser implementation able to properly read and write configuration files""" +import sys import abc from functools import wraps import inspect @@ -33,13 +34,21 @@ import configparser as cp from typing import (Any, Callable, Generic, IO, List, Dict, Sequence, TYPE_CHECKING, Tuple, TypeVar, Union, cast, overload) -from git.types import Lit_config_levels, ConfigLevels_Tup, OrderedDict, PathLike, TBD, assert_never, _T +from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never, _T if TYPE_CHECKING: from git.repo.base import Repo from io import BytesIO T_ConfigParser = TypeVar('T_ConfigParser', bound='GitConfigParser') + +if sys.version_info[:2] < (3, 7): + from collections import OrderedDict + OrderedDict_OMD = OrderedDict +else: + from typing import OrderedDict + OrderedDict_OMD = OrderedDict[str, List[_T]] + # ------------------------------------------------------------- __all__ = ('GitConfigParser', 'SectionConstraint') @@ -164,7 +173,7 @@ class SectionConstraint(Generic[T_ConfigParser]): self._config.__exit__(exception_type, exception_value, traceback) -class _OMD(OrderedDict[str, List[_T]]): +class _OMD(OrderedDict_OMD): """Ordered multi-dict.""" def __setitem__(self, key: str, value: _T) -> None: # type: ignore[override] @@ -617,6 +626,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # if self._defaults: write_section(cp.DEFAULTSECT, self._defaults) + value: TBD for name, value in self._sections.items(): write_section(name, value) -- cgit v1.2.1 From be7bb868279f61d55594059690904baabe30503c Mon Sep 17 00:00:00 2001 From: Yobmod Date: Sat, 24 Jul 2021 22:38:25 +0100 Subject: Rmv with_metclass() shim again --- git/config.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'git/config.py') diff --git a/git/config.py b/git/config.py index 51744bfe..c4b26ba6 100644 --- a/git/config.py +++ b/git/config.py @@ -20,7 +20,6 @@ from git.compat import ( defenc, force_text, is_win, - with_metaclass, ) from git.util import LockFile @@ -238,7 +237,7 @@ def get_config_path(config_level: Lit_config_levels) -> str: assert_never(config_level, ValueError(f"Invalid configuration level: {config_level!r}")) -class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # type: ignore ## mypy does not understand dynamic class creation # noqa: E501 +class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder): """Implements specifics required to read git style configuration files. -- cgit v1.2.1