commit - bbf100b63fb00ebb4a1d0ca698b1abe337611bae
commit + 0699568deeaea8aea1f564862b73c13c68032630
blob - 19f540e69893a800afb90122765f0e02d003faf1
blob + 81feb78ee5f3402d748c351071d28da3886741c9
--- dulwich/client.py
+++ dulwich/client.py
except KeyError:
pass
for needle in needles:
+ assert isinstance(needle, bytes)
yield needle.decode('utf-8'), replacement.decode('utf-8')
blob - 30b67fb3173e2adf104c10ee6f23c8b697b8b6d4
blob + f979d3cdf036e519ffd79209a431c3736611ee0c
--- dulwich/config.py
+++ dulwich/config.py
BinaryIO,
Iterable,
Iterator,
+ List,
KeysView,
MutableMapping,
Optional,
Tuple,
Union,
+ overload,
)
from dulwich.file import GitFile
return self[key]
+BytesLike = Union[bytes, str]
+Key = Tuple[bytes, ...]
+KeyLike = Union[bytes, str, Tuple[BytesLike, ...]]
+Value = Union[bytes, bool]
+ValueLike = Union[bytes, str, bool]
+
+
class Config(object):
"""A Git configuration."""
- def get(self, section, name):
+ def get(self, section: KeyLike, name: BytesLike) -> Value:
"""Retrieve the contents of a configuration setting.
Args:
- section: Tuple with section name and optional subsection namee
+ section: Tuple with section name and optional subsection name
name: Variable name
Returns:
Contents of the setting
"""
raise NotImplementedError(self.get)
- def get_multivar(self, section, name):
+ def get_multivar(self, section: KeyLike, name: BytesLike) -> Iterator[Value]:
"""Retrieve the contents of a multivar configuration setting.
Args:
"""
raise NotImplementedError(self.get_multivar)
- def get_boolean(self, section, name, default=None):
+ @overload
+ def get_boolean(self, section: KeyLike, name: BytesLike, default: bool) -> bool: ...
+ @overload
+ def get_boolean(self, section: KeyLike, name: BytesLike) -> Optional[bool]: ...
+
+ def get_boolean(self, section: KeyLike, name: BytesLike, default: Optional[bool] = None) -> Optional[bool]:
"""Retrieve a configuration setting as boolean.
Args:
subsection.
Returns:
Contents of the setting
- Raises:
- KeyError: if the value is not set
"""
try:
value = self.get(section, name)
except KeyError:
return default
+ if isinstance(value, bool):
+ return value
if value.lower() == b"true":
return True
elif value.lower() == b"false":
return False
raise ValueError("not a valid boolean string: %r" % value)
- def set(self, section, name, value):
+ def set(self, section: KeyLike, name: BytesLike, value: ValueLike) -> None:
"""Set a configuration value.
Args:
"""
raise NotImplementedError(self.set)
- def items(self, section):
+ def items(self, section: KeyLike) -> Iterator[Tuple[bytes, Value]]:
"""Iterate over the configuration pairs for a specific section.
Args:
"""
raise NotImplementedError(self.items)
- def iteritems(self, section):
+ def iteritems(self, section: KeyLike) -> Iterator[Tuple[bytes, Value]]:
"""Iterate over the configuration pairs for a specific section.
Args:
)
return self.items(section)
- def itersections(self):
+ def itersections(self) -> Iterator[Key]:
warnings.warn(
"Use %s.items instead." % type(self).__name__,
DeprecationWarning,
)
return self.sections()
- def sections(self):
+ def sections(self) -> Iterator[Key]:
"""Iterate over the sections.
Returns: Iterator over section tuples
"""
raise NotImplementedError(self.sections)
- def has_section(self, name: Tuple[bytes, ...]) -> bool:
+ def has_section(self, name: Key) -> bool:
"""Check if a specified section exists.
Args:
return name in self.sections()
-BytesLike = Union[bytes, str]
-Key = Tuple[bytes, ...]
-KeyLike = Union[bytes, str, Tuple[BytesLike, ...]]
-Value = Union[bytes, bool]
-ValueLike = Union[bytes, str, bool]
-
-
class ConfigDict(Config, MutableMapping[Key, MutableMapping[bytes, Value]]):
"""Git configuration stored in a dictionary."""
return self._values.__len__()
@classmethod
- def _parse_setting(cls, name):
+ def _parse_setting(cls, name: str):
parts = name.split(".")
if len(parts) == 3:
return (parts[0], parts[1], parts[2])
self,
section: KeyLike,
name: BytesLike,
- ) -> Optional[Value]:
+ ) -> Value:
section, name = self._check_section_and_name(section, name)
if len(section) > 1:
def items( # type: ignore[override]
self,
section: Key
- ) -> Iterator[Value]:
+ ) -> Iterator[Tuple[bytes, Value]]:
return self._values.get(section).items()
def sections(self) -> Iterator[Key]:
_WHITESPACE_CHARS = [ord(b"\t"), ord(b" ")]
-def _parse_string(value):
+def _parse_string(value: bytes) -> bytes:
value = bytearray(value.strip())
ret = bytearray()
whitespace = bytearray()
return bytes(ret)
-def _escape_value(value):
+def _escape_value(value: bytes) -> bytes:
"""Escape a value."""
value = value.replace(b"\\", b"\\\\")
value = value.replace(b"\n", b"\\n")
return value
-def _check_variable_name(name):
+def _check_variable_name(name: bytes) -> bool:
for i in range(len(name)):
c = name[i : i + 1]
if not c.isalnum() and c != b"-":
return True
-def _check_section_name(name):
+def _check_section_name(name: bytes) -> bool:
for i in range(len(name)):
c = name[i : i + 1]
if not c.isalnum() and c not in (b"-", b"."):
return True
-def _strip_comments(line):
+def _strip_comments(line: bytes) -> bytes:
comment_bytes = {ord(b"#"), ord(b";")}
quote = ord(b'"')
string_open = False
class ConfigFile(ConfigDict):
"""A Git configuration file, like .git/config or ~/.gitconfig."""
- def __init__(self, values=None, encoding=None):
+ def __init__(
+ self,
+ values: Union[
+ MutableMapping[Key, MutableMapping[bytes, Value]], None
+ ] = None,
+ encoding: Union[str, None] = None
+ ) -> None:
super(ConfigFile, self).__init__(values=values, encoding=encoding)
- self.path = None
+ self.path: Optional[str] = None
@classmethod # noqa: C901
def from_file(cls, f: BinaryIO) -> "ConfigFile": # noqa: C901
return ret
@classmethod
- def from_path(cls, path) -> "ConfigFile":
+ def from_path(cls, path: str) -> "ConfigFile":
"""Read configuration from a file on disk."""
with GitFile(path, "rb") as f:
ret = cls.from_file(f)
ret.path = path
return ret
- def write_to_path(self, path=None) -> None:
+ def write_to_path(self, path: Optional[str] = None) -> None:
"""Write configuration to a file on disk."""
if path is None:
path = self.path
class StackedConfig(Config):
"""Configuration which reads from multiple config files.."""
- def __init__(self, backends, writable=None):
+ def __init__(
+ self, backends: List[ConfigFile], writable: Optional[ConfigFile] = None
+ ):
self.backends = backends
self.writable = writable
- def __repr__(self):
+ def __repr__(self) -> str:
return "<%s for %r>" % (self.__class__.__name__, self.backends)
@classmethod
- def default(cls):
+ def default(cls) -> "StackedConfig":
return cls(cls.default_backends())
@classmethod
- def default_backends(cls):
+ def default_backends(cls) -> List[ConfigFile]:
"""Retrieve the default configuration.
See git-config(1) for details on the files searched.
backends.append(cf)
return backends
- def get(self, section, name):
+ def get(self, section: KeyLike, name: BytesLike) -> Value:
if not isinstance(section, tuple):
section = (section,)
for backend in self.backends:
pass
raise KeyError(name)
- def get_multivar(self, section, name):
+ def get_multivar(self, section: KeyLike, name: BytesLike) -> Iterator[Value]:
if not isinstance(section, tuple):
section = (section,)
for backend in self.backends:
except KeyError:
pass
- def set(self, section, name, value):
+ def set(self, section: KeyLike, name: BytesLike, value: ValueLike) -> None:
if self.writable is None:
raise NotImplementedError(self.set)
return self.writable.set(section, name, value)
- def sections(self):
+ def sections(self) -> Iterator[Key]:
seen = set()
for backend in self.backends:
for section in backend.sections():
blob - 55a821f46c14bf7e8392d1d7d4ca85dd77cf3551
blob + 1831fe7d0266f3e7414db8ddae86af302fa42e1b
--- dulwich/ignore.py
+++ dulwich/ignore.py
Path to a global ignore file
"""
try:
- return config.get((b"core",), b"excludesFile")
+ value = config.get((b"core",), b"excludesFile")
+ assert isinstance(value, bytes)
+ return value.decode(encoding="utf-8")
except KeyError:
pass
blob - 80c2ad575723a1452ebcc6bd4b34a2fe267fc7e1
blob + 396069b9de456f1bde341145a311b23b46130da8
--- dulwich/repo.py
+++ dulwich/repo.py
email = email_uc.encode("utf-8")
if user is None:
try:
- user = config.get(("user",), "name")
+ config_value = config.get(("user",), "name")
+ assert isinstance(config_value, bytes)
+ user = config_value
except KeyError:
user = None
if email is None:
try:
- email = config.get(("user",), "email")
+ config_value = config.get(("user",), "email")
+ assert isinstance(config_value, bytes)
+ email = config_value
except KeyError:
email = None
default_user, default_email = _get_default_identity()