Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit d812818

Browse filesBrowse files
committed
Rmv with_metaclass shim, make section constraint generic wrt its configparser type
1 parent 2bc2ac0 commit d812818
Copy full SHA for d812818

8 files changed

+41-60Lines changed: 41 additions & 60 deletions

File tree

Expand file treeCollapse file tree
Open diff view settings
Filter options
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎.flake8‎

Copy file name to clipboardExpand all lines: .flake8
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ ignore = E265,E266,E731,E704,
2020
W293, W504,
2121
ANN0 ANN1 ANN2,
2222
TC002,
23-
# TC0, TC1, TC2
23+
TC0, TC1, TC2
2424
# B,
2525
A,
2626
D,
Collapse file

‎git/compat.py‎

Copy file name to clipboardExpand all lines: git/compat.py
-16Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -97,19 +97,3 @@ def win_encode(s: Optional[AnyStr]) -> Optional[bytes]:
9797
elif s is not None:
9898
raise TypeError('Expected bytes or text, but got %r' % (s,))
9999
return None
100-
101-
102-
# type: ignore ## mypy cannot understand dynamic class creation
103-
def with_metaclass(meta: Type[Any], *bases: Any) -> TBD:
104-
"""copied from https://github.com/Byron/bcore/blob/master/src/python/butility/future.py#L15"""
105-
106-
class metaclass(meta): # type: ignore
107-
__call__ = type.__call__
108-
__init__ = type.__init__ # type: ignore
109-
110-
def __new__(cls, name: str, nbases: Optional[Tuple[int, ...]], d: Dict[str, Any]) -> TBD:
111-
if nbases is None:
112-
return type.__new__(cls, name, (), d)
113-
return meta(name, bases, d)
114-
115-
return metaclass(meta.__name__ + 'Helper', None, {}) # type: ignore
Collapse file

‎git/config.py‎

Copy file name to clipboardExpand all lines: git/config.py
+24-31Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,10 @@
1414
import os
1515
import re
1616
import fnmatch
17-
from collections import OrderedDict
1817

1918
from git.compat import (
2019
defenc,
2120
force_text,
22-
with_metaclass,
2321
is_win,
2422
)
2523

@@ -31,15 +29,16 @@
3129

3230
# typing-------------------------------------------------------
3331

34-
from typing import (Any, Callable, IO, List, Dict, Sequence,
35-
TYPE_CHECKING, Tuple, Union, cast, overload)
32+
from typing import (Any, Callable, Generic, IO, List, Dict, Sequence,
33+
TYPE_CHECKING, Tuple, TypeVar, Union, cast, overload)
3634

37-
from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never
35+
from git.types import Lit_config_levels, ConfigLevels_Tup, PathLike, TBD, assert_never, _T
3836

3937
if TYPE_CHECKING:
4038
from git.repo.base import Repo
4139
from io import BytesIO
4240

41+
T_ConfigParser = TypeVar('T_ConfigParser', bound='GitConfigParser')
4342
# -------------------------------------------------------------
4443

4544
__all__ = ('GitConfigParser', 'SectionConstraint')
@@ -61,7 +60,6 @@
6160

6261

6362
class MetaParserBuilder(abc.ABCMeta):
64-
6563
"""Utlity class wrapping base-class methods into decorators that assure read-only properties"""
6664
def __new__(cls, name: str, bases: TBD, clsdict: Dict[str, Any]) -> TBD:
6765
"""
@@ -115,7 +113,7 @@ def flush_changes(self, *args: Any, **kwargs: Any) -> Any:
115113
return flush_changes
116114

117115

118-
class SectionConstraint(object):
116+
class SectionConstraint(Generic[T_ConfigParser]):
119117

120118
"""Constrains a ConfigParser to only option commands which are constrained to
121119
always use the section we have been initialized with.
@@ -128,7 +126,7 @@ class SectionConstraint(object):
128126
_valid_attrs_ = ("get_value", "set_value", "get", "set", "getint", "getfloat", "getboolean", "has_option",
129127
"remove_section", "remove_option", "options")
130128

131-
def __init__(self, config: 'GitConfigParser', section: str) -> None:
129+
def __init__(self, config: T_ConfigParser, section: str) -> None:
132130
self._config = config
133131
self._section_name = section
134132

@@ -149,26 +147,26 @@ def _call_config(self, method: str, *args: Any, **kwargs: Any) -> Any:
149147
return getattr(self._config, method)(self._section_name, *args, **kwargs)
150148

151149
@property
152-
def config(self) -> 'GitConfigParser':
150+
def config(self) -> T_ConfigParser:
153151
"""return: Configparser instance we constrain"""
154152
return self._config
155153

156154
def release(self) -> None:
157155
"""Equivalent to GitConfigParser.release(), which is called on our underlying parser instance"""
158156
return self._config.release()
159157

160-
def __enter__(self) -> 'SectionConstraint':
158+
def __enter__(self) -> 'SectionConstraint[T_ConfigParser]':
161159
self._config.__enter__()
162160
return self
163161

164162
def __exit__(self, exception_type: str, exception_value: str, traceback: str) -> None:
165163
self._config.__exit__(exception_type, exception_value, traceback)
166164

167165

168-
class _OMD(OrderedDict):
166+
class _OMD(Dict[str, List[_T]]):
169167
"""Ordered multi-dict."""
170168

171-
def __setitem__(self, key: str, value: Any) -> None:
169+
def __setitem__(self, key: str, value: _T) -> None: # type: ignore[override]
172170
super(_OMD, self).__setitem__(key, [value])
173171

174172
def add(self, key: str, value: Any) -> None:
@@ -177,7 +175,7 @@ def add(self, key: str, value: Any) -> None:
177175
return None
178176
super(_OMD, self).__getitem__(key).append(value)
179177

180-
def setall(self, key: str, values: Any) -> None:
178+
def setall(self, key: str, values: List[_T]) -> None:
181179
super(_OMD, self).__setitem__(key, values)
182180

183181
def __getitem__(self, key: str) -> Any:
@@ -194,25 +192,17 @@ def setlast(self, key: str, value: Any) -> None:
194192
prior = super(_OMD, self).__getitem__(key)
195193
prior[-1] = value
196194

197-
@overload
198-
def get(self, key: str, default: None = ...) -> None:
199-
...
200-
201-
@overload
202-
def get(self, key: str, default: Any = ...) -> Any:
203-
...
204-
205-
def get(self, key: str, default: Union[Any, None] = None) -> Union[Any, None]:
206-
return super(_OMD, self).get(key, [default])[-1]
195+
def get(self, key: str, default: Union[_T, None] = None) -> Union[_T, None]: # type: ignore
196+
return super(_OMD, self).get(key, [default])[-1] # type: ignore
207197

208-
def getall(self, key: str) -> Any:
198+
def getall(self, key: str) -> List[_T]:
209199
return super(_OMD, self).__getitem__(key)
210200

211-
def items(self) -> List[Tuple[str, Any]]: # type: ignore[override]
201+
def items(self) -> List[Tuple[str, _T]]: # type: ignore[override]
212202
"""List of (key, last value for key)."""
213203
return [(k, self[k]) for k in self]
214204

215-
def items_all(self) -> List[Tuple[str, List[Any]]]:
205+
def items_all(self) -> List[Tuple[str, List[_T]]]:
216206
"""List of (key, list of values for key)."""
217207
return [(k, self.getall(k)) for k in self]
218208

@@ -238,7 +228,7 @@ def get_config_path(config_level: Lit_config_levels) -> str:
238228
assert_never(config_level, ValueError(f"Invalid configuration level: {config_level!r}"))
239229

240230

241-
class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser)): # type: ignore ## mypy does not understand dynamic class creation # noqa: E501
231+
class GitConfigParser(cp.RawConfigParser, metaclass=MetaParserBuilder):
242232

243233
"""Implements specifics required to read git style configuration files.
244234
@@ -298,7 +288,10 @@ def __init__(self, file_or_files: Union[None, PathLike, 'BytesIO', Sequence[Unio
298288
:param repo: Reference to repository to use if [includeIf] sections are found in configuration files.
299289
300290
"""
301-
cp.RawConfigParser.__init__(self, dict_type=_OMD)
291+
cp.RawConfigParser.__init__(self, dict_type=_OMD) # type: ignore[arg-type]
292+
self._dict: Callable[..., _OMD] # type: ignore[assignment] # mypy/typeshed bug
293+
self._defaults: _OMD # type: ignore[assignment] # mypy/typeshed bug
294+
self._sections: _OMD # type: ignore[assignment] # mypy/typeshed bug
302295

303296
# Used in python 3, needs to stay in sync with sections for underlying implementation to work
304297
if not hasattr(self, '_proxies'):
@@ -424,7 +417,7 @@ def string_decode(v: str) -> str:
424417
# is it a section header?
425418
mo = self.SECTCRE.match(line.strip())
426419
if not is_multi_line and mo:
427-
sectname = mo.group('header').strip()
420+
sectname: str = mo.group('header').strip()
428421
if sectname in self._sections:
429422
cursect = self._sections[sectname]
430423
elif sectname == cp.DEFAULTSECT:
@@ -535,7 +528,7 @@ def _included_paths(self) -> List[Tuple[str, str]]:
535528

536529
return paths
537530

538-
def read(self) -> None:
531+
def read(self) -> None: # type: ignore[override]
539532
"""Reads the data stored in the files we have been initialized with. It will
540533
ignore files that cannot be read, possibly leaving an empty configuration
541534
@@ -626,7 +619,7 @@ def write_section(name, section_dict):
626619
for name, value in self._sections.items():
627620
write_section(name, value)
628621

629-
def items(self, section_name: str) -> List[Tuple[str, str]]:
622+
def items(self, section_name: str) -> List[Tuple[str, str]]: # type: ignore[override]
630623
""":return: list((option, value), ...) pairs of all items in the given section"""
631624
return [(k, v) for k, v in super(GitConfigParser, self).items(section_name) if k != '__name__']
632625

Collapse file

‎git/index/typ.py‎

Copy file name to clipboardExpand all lines: git/index/typ.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,8 @@ class BaseIndexEntry(BaseIndexEntryHelper):
8282
8383
As the first 4 data members match exactly to the IndexEntry type, methods
8484
expecting a BaseIndexEntry can also handle full IndexEntries even if they
85-
use numeric indices for performance reasons. """
85+
use numeric indices for performance reasons.
86+
"""
8687

8788
def __new__(cls, inp_tuple: Union[Tuple[int, bytes, int, PathLike],
8889
Tuple[int, bytes, int, PathLike, bytes, bytes, int, int, int, int, int]]
Collapse file

‎git/objects/submodule/base.py‎

Copy file name to clipboardExpand all lines: git/objects/submodule/base.py
+7-7Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -965,13 +965,12 @@ def remove(self, module: bool = True, force: bool = False,
965965

966966
# now git config - need the config intact, otherwise we can't query
967967
# information anymore
968-
writer: Union[GitConfigParser, SectionConstraint]
969968

970-
with self.repo.config_writer() as writer:
971-
writer.remove_section(sm_section(self.name))
969+
with self.repo.config_writer() as gcp_writer:
970+
gcp_writer.remove_section(sm_section(self.name))
972971

973-
with self.config_writer() as writer:
974-
writer.remove_section()
972+
with self.config_writer() as sc_writer:
973+
sc_writer.remove_section()
975974
# END delete configuration
976975

977976
return self
@@ -1024,7 +1023,8 @@ def set_parent_commit(self, commit: Union[Commit_ish, None], check: bool = True)
10241023
return self
10251024

10261025
@unbare_repo
1027-
def config_writer(self, index: Union['IndexFile', None] = None, write: bool = True) -> SectionConstraint:
1026+
def config_writer(self, index: Union['IndexFile', None] = None, write: bool = True
1027+
) -> SectionConstraint['SubmoduleConfigParser']:
10281028
""":return: a config writer instance allowing you to read and write the data
10291029
belonging to this submodule into the .gitmodules file.
10301030
@@ -1201,7 +1201,7 @@ def name(self) -> str:
12011201
"""
12021202
return self._name
12031203

1204-
def config_reader(self) -> SectionConstraint:
1204+
def config_reader(self) -> SectionConstraint[SubmoduleConfigParser]:
12051205
"""
12061206
:return: ConfigReader instance which allows you to qurey the configuration values
12071207
of this submodule, as provided by the .gitmodules file
Collapse file

‎git/objects/submodule/util.py‎

Copy file name to clipboardExpand all lines: git/objects/submodule/util.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ def flush_to_index(self) -> None:
100100
#} END interface
101101

102102
#{ Overridden Methods
103-
def write(self) -> None:
103+
def write(self) -> None: # type: ignore[override]
104104
rval: None = super(SubmoduleConfigParser, self).write()
105105
self.flush_to_index()
106106
return rval
Collapse file

‎git/remote.py‎

Copy file name to clipboardExpand all lines: git/remote.py
+2-1Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
)
2424

2525
from .config import (
26+
GitConfigParser,
2627
SectionConstraint,
2728
cp,
2829
)
@@ -911,7 +912,7 @@ def push(self, refspec: Union[str, List[str], None] = None,
911912
return self._get_push_info(proc, progress)
912913

913914
@ property
914-
def config_reader(self) -> SectionConstraint:
915+
def config_reader(self) -> SectionConstraint[GitConfigParser]:
915916
"""
916917
:return:
917918
GitConfigParser compatible object able to read options for only our remote.
Collapse file

‎git/repo/base.py‎

Copy file name to clipboardExpand all lines: git/repo/base.py
+4-2Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,8 @@ def _get_config_path(self, config_level: Lit_config_levels) -> str:
482482

483483
raise ValueError("Invalid configuration level: %r" % config_level)
484484

485-
def config_reader(self, config_level: Optional[Lit_config_levels] = None) -> GitConfigParser:
485+
def config_reader(self, config_level: Optional[Lit_config_levels] = None
486+
) -> GitConfigParser:
486487
"""
487488
:return:
488489
GitConfigParser allowing to read the full git configuration, but not to write it
@@ -504,7 +505,8 @@ def config_reader(self, config_level: Optional[Lit_config_levels] = None) -> Git
504505
files = [self._get_config_path(config_level)]
505506
return GitConfigParser(files, read_only=True, repo=self)
506507

507-
def config_writer(self, config_level: Lit_config_levels = "repository") -> GitConfigParser:
508+
def config_writer(self, config_level: Lit_config_levels = "repository"
509+
) -> GitConfigParser:
508510
"""
509511
:return:
510512
GitConfigParser allowing to write values of the specified configuration file level.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.