Skip to content

Commit 468f196

Browse files
committed
mypy: enable disallow_untyped_calls for test folder
and fix remaining errors mainly driven by test/test_config.py
1 parent 69dd9f4 commit 468f196

File tree

8 files changed

+75
-48
lines changed

8 files changed

+75
-48
lines changed

mypy.ini

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22

33
[mypy-test.*]
44
disallow_untyped_defs = True
5+
disallow_untyped_calls = True

pygit2/_libgit2/ffi.pyi

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ char_pointer = NewType('char_pointer', object)
3838
class size_t:
3939
def __getitem__(self, item: Literal[0]) -> int: ...
4040

41+
class int_c:
42+
def __getitem__(self, item: Literal[0]) -> int: ...
43+
44+
class int64_t:
45+
def __getitem__(self, item: Literal[0]) -> int: ...
46+
4147
class _Pointer(Generic[T]):
4248
def __setitem__(self, item: Literal[0], a: T) -> None: ...
4349
@overload
@@ -141,9 +147,14 @@ class GitConfigC:
141147
# incomplete
142148
pass
143149

150+
class GitConfigIteratorC:
151+
# incomplete
152+
pass
153+
144154
class GitConfigEntryC:
145155
# incomplete
146156
name: char_pointer
157+
value: char_pointer
147158
level: int
148159

149160
class GitDescribeFormatOptionsC:
@@ -269,6 +280,8 @@ def new(a: Literal['git_config *']) -> GitConfigC: ...
269280
@overload
270281
def new(a: Literal['git_config **']) -> _Pointer[GitConfigC]: ...
271282
@overload
283+
def new(a: Literal['git_config_iterator **']) -> _Pointer[GitConfigIteratorC]: ...
284+
@overload
272285
def new(a: Literal['git_config_entry **']) -> _Pointer[GitConfigEntryC]: ...
273286
@overload
274287
def new(a: Literal['git_describe_format_options *']) -> GitDescribeFormatOptionsC: ...
@@ -297,6 +310,10 @@ def new(a: Literal['git_signature *']) -> GitSignatureC: ...
297310
@overload
298311
def new(a: Literal['git_signature **']) -> _Pointer[GitSignatureC]: ...
299312
@overload
313+
def new(a: Literal['int *']) -> int_c: ...
314+
@overload
315+
def new(a: Literal['int64_t *']) -> int64_t: ...
316+
@overload
300317
def new(
301318
a: Literal['git_remote_head ***'],
302319
) -> _Pointer[_MultiPointer[GitRemoteHeadC]]: ...

pygit2/config.py

Lines changed: 33 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@
2424
# Boston, MA 02110-1301, USA.
2525

2626
from os import PathLike
27-
from typing import TYPE_CHECKING
27+
from pathlib import Path
28+
from typing import TYPE_CHECKING, Callable, Iterator
2829

2930
try:
3031
from functools import cached_property
@@ -48,20 +49,20 @@ def str_to_bytes(value: str | PathLike[str] | bytes, name: str) -> bytes:
4849

4950

5051
class ConfigIterator:
51-
def __init__(self, config, ptr):
52+
def __init__(self, config, ptr) -> None:
5253
self._iter = ptr
5354
self._config = config
5455

55-
def __del__(self):
56+
def __del__(self) -> None:
5657
C.git_config_iterator_free(self._iter)
5758

58-
def __iter__(self):
59+
def __iter__(self) -> 'ConfigIterator':
5960
return self
6061

61-
def __next__(self):
62+
def __next__(self) -> 'ConfigEntry':
6263
return self._next_entry()
6364

64-
def _next_entry(self):
65+
def _next_entry(self) -> 'ConfigEntry':
6566
centry = ffi.new('git_config_entry **')
6667
err = C.git_config_next(centry, self._iter)
6768
check_error(err)
@@ -70,7 +71,7 @@ def _next_entry(self):
7071

7172

7273
class ConfigMultivarIterator(ConfigIterator):
73-
def __next__(self):
74+
def __next__(self) -> str: # type: ignore[override]
7475
entry = self._next_entry()
7576
return entry.value
7677

@@ -124,7 +125,7 @@ def _get_entry(self, key: str | bytes) -> 'ConfigEntry':
124125
check_error(err)
125126
return entry
126127

127-
def __contains__(self, key):
128+
def __contains__(self, key: str | bytes) -> bool:
128129
err, cstr = self._get(key)
129130

130131
if err == C.GIT_ENOTFOUND:
@@ -134,7 +135,7 @@ def __contains__(self, key):
134135

135136
return True
136137

137-
def __getitem__(self, key):
138+
def __getitem__(self, key: str | bytes) -> str:
138139
"""
139140
When using the mapping interface, the value is returned as a string. In
140141
order to apply the git-config parsing rules, you can use
@@ -144,7 +145,7 @@ def __getitem__(self, key):
144145

145146
return entry.value
146147

147-
def __setitem__(self, key, value):
148+
def __setitem__(self, key: str | bytes, value: bool | int | str | bytes) -> None:
148149
key = str_to_bytes(key, 'key')
149150

150151
err = 0
@@ -157,13 +158,13 @@ def __setitem__(self, key, value):
157158

158159
check_error(err)
159160

160-
def __delitem__(self, key):
161+
def __delitem__(self, key: str | bytes) -> None:
161162
key = str_to_bytes(key, 'key')
162163

163164
err = C.git_config_delete_entry(self._config, key)
164165
check_error(err)
165166

166-
def __iter__(self):
167+
def __iter__(self) -> Iterator['ConfigEntry']:
167168
"""
168169
Iterate over configuration entries, returning a ``ConfigEntry``
169170
objects. These contain the name, level, and value of each configuration
@@ -176,22 +177,26 @@ def __iter__(self):
176177

177178
return ConfigIterator(self, citer[0])
178179

179-
def get_multivar(self, name, regex=None):
180+
def get_multivar(
181+
self, name: str | bytes, regex: str | None = None
182+
) -> ConfigMultivarIterator:
180183
"""Get each value of a multivar ''name'' as a list of strings.
181184
182185
The optional ''regex'' parameter is expected to be a regular expression
183186
to filter the variables we're interested in.
184187
"""
185188
name = str_to_bytes(name, 'name')
186-
regex = to_bytes(regex or None)
189+
regex_bytes = to_bytes(regex or None)
187190

188191
citer = ffi.new('git_config_iterator **')
189-
err = C.git_config_multivar_iterator_new(citer, self._config, name, regex)
192+
err = C.git_config_multivar_iterator_new(citer, self._config, name, regex_bytes)
190193
check_error(err)
191194

192195
return ConfigMultivarIterator(self, citer[0])
193196

194-
def set_multivar(self, name, regex, value):
197+
def set_multivar(
198+
self, name: str | bytes, regex: str | bytes, value: str | bytes
199+
) -> None:
195200
"""Set a multivar ''name'' to ''value''. ''regexp'' is a regular
196201
expression to indicate which values to replace.
197202
"""
@@ -202,7 +207,7 @@ def set_multivar(self, name, regex, value):
202207
err = C.git_config_set_multivar(self._config, name, regex, value)
203208
check_error(err)
204209

205-
def delete_multivar(self, name, regex):
210+
def delete_multivar(self, name: str | bytes, regex: str | bytes) -> None:
206211
"""Delete a multivar ''name''. ''regexp'' is a regular expression to
207212
indicate which values to delete.
208213
"""
@@ -212,7 +217,7 @@ def delete_multivar(self, name, regex):
212217
err = C.git_config_delete_multivar(self._config, name, regex)
213218
check_error(err)
214219

215-
def get_bool(self, key):
220+
def get_bool(self, key: str | bytes) -> bool:
216221
"""Look up *key* and parse its value as a boolean as per the git-config
217222
rules. Return a boolean value (True or False).
218223
@@ -227,7 +232,7 @@ def get_bool(self, key):
227232

228233
return res[0] != 0
229234

230-
def get_int(self, key):
235+
def get_int(self, key: bytes | str) -> int:
231236
"""Look up *key* and parse its value as an integer as per the git-config
232237
rules. Return an integer.
233238
@@ -242,15 +247,15 @@ def get_int(self, key):
242247

243248
return res[0]
244249

245-
def add_file(self, path, level=0, force=0):
250+
def add_file(self, path: str | Path, level: int = 0, force: int = 0) -> None:
246251
"""Add a config file instance to an existing config."""
247252

248253
err = C.git_config_add_file_ondisk(
249254
self._config, to_bytes(path), level, ffi.NULL, force
250255
)
251256
check_error(err)
252257

253-
def snapshot(self):
258+
def snapshot(self) -> 'Config':
254259
"""Create a snapshot from this Config object.
255260
256261
This means that looking up multiple values will use the same version
@@ -267,15 +272,15 @@ def snapshot(self):
267272
#
268273

269274
@staticmethod
270-
def parse_bool(text):
275+
def parse_bool(text: str) -> bool:
271276
res = ffi.new('int *')
272277
err = C.git_config_parse_bool(res, to_bytes(text))
273278
check_error(err)
274279

275280
return res[0] != 0
276281

277282
@staticmethod
278-
def parse_int(text):
283+
def parse_int(text: str) -> int:
279284
res = ffi.new('int64_t *')
280285
err = C.git_config_parse_int64(res, to_bytes(text))
281286
check_error(err)
@@ -287,7 +292,7 @@ def parse_int(text):
287292
#
288293

289294
@staticmethod
290-
def _from_found_config(fn):
295+
def _from_found_config(fn: Callable) -> 'Config':
291296
buf = ffi.new('git_buf *', (ffi.NULL, 0))
292297
err = fn(buf)
293298
check_error(err, io=True)
@@ -297,17 +302,17 @@ def _from_found_config(fn):
297302
return Config(cpath)
298303

299304
@staticmethod
300-
def get_system_config():
305+
def get_system_config() -> 'Config':
301306
"""Return a <Config> object representing the system configuration file."""
302307
return Config._from_found_config(C.git_config_find_system)
303308

304309
@staticmethod
305-
def get_global_config():
310+
def get_global_config() -> 'Config':
306311
"""Return a <Config> object representing the global configuration file."""
307312
return Config._from_found_config(C.git_config_find_global)
308313

309314
@staticmethod
310-
def get_xdg_config():
315+
def get_xdg_config() -> 'Config':
311316
"""Return a <Config> object representing the global configuration file."""
312317
return Config._from_found_config(C.git_config_find_xdg)
313318

@@ -349,7 +354,7 @@ def __del__(self) -> None:
349354
C.git_config_entry_free(self._entry)
350355

351356
@property
352-
def c_value(self):
357+
def c_value(self) -> 'ffi.char_pointer':
353358
"""The raw ``cData`` entry value."""
354359
return self._entry.value
355360

pygit2/index.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ def __getitem__(self, key: str | int | PathLike[str]) -> 'IndexEntry':
103103
def __iter__(self):
104104
return GenericIterator(self)
105105

106-
def read(self, force=True):
106+
def read(self, force: bool = True) -> None:
107107
"""
108108
Update the contents of the Index by reading from a file.
109109

pygit2/refspec.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
2424
# Boston, MA 02110-1301, USA.
2525

26+
from typing import Callable
27+
2628
# Import from pygit2
2729
from .errors import check_error
2830
from .ffi import C, ffi
@@ -37,22 +39,22 @@ def __init__(self, owner, ptr):
3739
self._refspec = ptr
3840

3941
@property
40-
def src(self):
42+
def src(self) -> str:
4143
"""Source or lhs of the refspec"""
4244
return ffi.string(C.git_refspec_src(self._refspec)).decode('utf-8')
4345

4446
@property
45-
def dst(self):
47+
def dst(self) -> str:
4648
"""Destination or rhs of the refspec"""
4749
return ffi.string(C.git_refspec_dst(self._refspec)).decode('utf-8')
4850

4951
@property
50-
def force(self):
52+
def force(self) -> bool:
5153
"""Whether this refspeca llows non-fast-forward updates"""
5254
return bool(C.git_refspec_force(self._refspec))
5355

5456
@property
55-
def string(self):
57+
def string(self) -> str:
5658
"""String which was used to create this refspec"""
5759
return ffi.string(C.git_refspec_string(self._refspec)).decode('utf-8')
5860

@@ -61,18 +63,18 @@ def direction(self):
6163
"""Direction of this refspec (fetch or push)"""
6264
return C.git_refspec_direction(self._refspec)
6365

64-
def src_matches(self, ref):
66+
def src_matches(self, ref: str) -> bool:
6567
"""Return True if the given string matches the source of this refspec,
6668
False otherwise.
6769
"""
6870
return bool(C.git_refspec_src_matches(self._refspec, to_bytes(ref)))
6971

70-
def dst_matches(self, ref):
72+
def dst_matches(self, ref: str) -> bool:
7173
"""Return True if the given string matches the destination of this
7274
refspec, False otherwise."""
7375
return bool(C.git_refspec_dst_matches(self._refspec, to_bytes(ref)))
7476

75-
def _transform(self, ref, fn):
77+
def _transform(self, ref: str, fn: Callable) -> str:
7678
buf = ffi.new('git_buf *', (ffi.NULL, 0))
7779
err = fn(buf, self._refspec, to_bytes(ref))
7880
check_error(err)
@@ -82,13 +84,13 @@ def _transform(self, ref, fn):
8284
finally:
8385
C.git_buf_dispose(buf)
8486

85-
def transform(self, ref):
87+
def transform(self, ref: str) -> str:
8688
"""Transform a reference name according to this refspec from the lhs to
8789
the rhs. Return an string.
8890
"""
8991
return self._transform(ref, C.git_refspec_transform)
9092

91-
def rtransform(self, ref):
93+
def rtransform(self, ref: str) -> str:
9294
"""Transform a reference name according to this refspec from the lhs to
9395
the rhs. Return an string.
9496
"""

pygit2/remotes.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ def refspec_count(self):
246246

247247
return C.git_remote_refspec_count(self._remote)
248248

249-
def get_refspec(self, n):
249+
def get_refspec(self, n: int) -> Refspec:
250250
"""Return the <Refspec> object at the given position."""
251251
spec = C.git_remote_get_refspec(self._remote, n)
252252
return Refspec(self, spec)

0 commit comments

Comments
 (0)