Skip to content

Commit a59944b

Browse files
committed
improve types according to test/test_submodule.py
1 parent 6569d66 commit a59944b

File tree

4 files changed

+58
-33
lines changed

4 files changed

+58
-33
lines changed

pygit2/_pygit2.pyi

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ from .enums import (
77
ApplyLocation,
88
BranchType,
99
BlobFilter,
10+
CheckoutStrategy,
1011
DeltaStatus,
1112
DiffFind,
1213
DiffFlag,
@@ -25,7 +26,9 @@ from .enums import (
2526
from collections.abc import Generator
2627

2728
from .repository import BaseRepository
29+
from .submodules import SubmoduleCollection, Submodule
2830
from .remotes import Remote
31+
from .callbacks import CheckoutCallbacks
2932

3033
GIT_OBJ_BLOB = Literal[3]
3134
GIT_OBJ_COMMIT = Literal[1]
@@ -700,10 +703,12 @@ class Repository:
700703
references: References
701704
remotes: RemoteCollection
702705
branches: Branches
706+
submodules: SubmoduleCollection
707+
index: Index
703708
def __init__(self, *args, **kwargs) -> None: ...
704709
def TreeBuilder(self, src: Tree | _OidArg = ...) -> TreeBuilder: ...
705710
def _disown(self, *args, **kwargs) -> None: ...
706-
def _from_c(self, *args, **kwargs) -> None: ...
711+
def _from_c(self, *args, **kwargs) -> 'Repository': ...
707712
def __getitem__(self, key: str | Oid) -> Object: ...
708713
def add_worktree(self, name: str, path: str, ref: Reference = ...) -> Worktree: ...
709714
def applies(
@@ -715,6 +720,15 @@ class Repository:
715720
def apply(
716721
self, diff: Diff, location: ApplyLocation = ApplyLocation.WORKDIR
717722
) -> None: ...
723+
def checkout(
724+
self,
725+
refname: Optional[_OidArg],
726+
*,
727+
strategy: CheckoutStrategy | None = None,
728+
directory: str | None = None,
729+
paths: list[str] | None = None,
730+
callbacks: CheckoutCallbacks | None = None,
731+
) -> None: ...
718732
def cherrypick(self, id: _OidArg) -> None: ...
719733
def compress_references(self) -> None: ...
720734
def create_blob(self, data: bytes) -> Oid: ...

pygit2/submodules.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
from __future__ import annotations
2727
from typing import TYPE_CHECKING, Iterable, Iterator, Optional, Union
28+
from pathlib import Path
2829

2930
from ._pygit2 import Oid
3031
from .callbacks import git_fetch_options, RemoteCallbacks
@@ -36,6 +37,7 @@
3637
# Need BaseRepository for type hints, but don't let it cause a circular dependency
3738
if TYPE_CHECKING:
3839
from .repository import BaseRepository
40+
from pygit2 import Repository
3941

4042

4143
class Submodule:
@@ -51,18 +53,18 @@ def _from_c(cls, repo: BaseRepository, cptr):
5153

5254
return subm
5355

54-
def __del__(self):
56+
def __del__(self) -> None:
5557
C.git_submodule_free(self._subm)
5658

57-
def open(self):
59+
def open(self) -> Repository:
5860
"""Open the repository for a submodule."""
5961
crepo = ffi.new('git_repository **')
6062
err = C.git_submodule_open(crepo, self._subm)
6163
check_error(err)
6264

6365
return self._repo._from_c(crepo[0], True)
6466

65-
def init(self, overwrite: bool = False):
67+
def init(self, overwrite: bool = False) -> None:
6668
"""
6769
Just like "git submodule init", this copies information about the submodule
6870
into ".git/config".
@@ -173,7 +175,7 @@ class SubmoduleCollection:
173175
def __init__(self, repository: BaseRepository):
174176
self._repository = repository
175177

176-
def __getitem__(self, name: str) -> Submodule:
178+
def __getitem__(self, name: str | Path) -> Submodule:
177179
"""
178180
Look up submodule information by name or path.
179181
Raises KeyError if there is no such submodule.

test/test_submodule.py

Lines changed: 27 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,10 @@
2626
"""Tests for Submodule objects."""
2727

2828
from pathlib import Path
29+
from typing import Generator
2930

3031
import pygit2
32+
from pygit2 import Repository, Submodule
3133
import pytest
3234

3335
from . import utils
@@ -42,48 +44,48 @@
4244

4345

4446
@pytest.fixture
45-
def repo(tmp_path):
47+
def repo(tmp_path: Path) -> Generator[Repository, None, None]:
4648
with utils.TemporaryRepository('submodulerepo.zip', tmp_path) as path:
4749
yield pygit2.Repository(path)
4850

4951

50-
def test_lookup_submodule(repo):
51-
s = repo.submodules[SUBM_PATH]
52+
def test_lookup_submodule(repo: Repository) -> None:
53+
s: Submodule | None = repo.submodules[SUBM_PATH]
5254
assert s is not None
5355
s = repo.submodules.get(SUBM_PATH)
5456
assert s is not None
5557

5658

57-
def test_lookup_submodule_aspath(repo):
59+
def test_lookup_submodule_aspath(repo: Repository) -> None:
5860
s = repo.submodules[Path(SUBM_PATH)]
5961
assert s is not None
6062

6163

62-
def test_lookup_missing_submodule(repo):
64+
def test_lookup_missing_submodule(repo: Repository) -> None:
6365
with pytest.raises(KeyError):
6466
repo.submodules['does-not-exist']
6567
assert repo.submodules.get('does-not-exist') is None
6668

6769

68-
def test_listall_submodules(repo):
70+
def test_listall_submodules(repo: Repository) -> None:
6971
submodules = repo.listall_submodules()
7072
assert len(submodules) == 1
7173
assert submodules[0] == SUBM_PATH
7274

7375

74-
def test_contains_submodule(repo):
76+
def test_contains_submodule(repo: Repository) -> None:
7577
assert SUBM_PATH in repo.submodules
7678
assert 'does-not-exist' not in repo.submodules
7779

7880

79-
def test_submodule_iterator(repo):
81+
def test_submodule_iterator(repo: Repository) -> None:
8082
for s in repo.submodules:
8183
assert isinstance(s, pygit2.Submodule)
8284
assert s.path == repo.submodules[s.path].path
8385

8486

8587
@utils.requires_network
86-
def test_submodule_open(repo):
88+
def test_submodule_open(repo: Repository) -> None:
8789
s = repo.submodules[SUBM_PATH]
8890
repo.submodules.init()
8991
repo.submodules.update()
@@ -93,7 +95,7 @@ def test_submodule_open(repo):
9395

9496

9597
@utils.requires_network
96-
def test_submodule_open_from_repository_subclass(repo):
98+
def test_submodule_open_from_repository_subclass(repo: Repository) -> None:
9799
class CustomRepoClass(pygit2.Repository):
98100
pass
99101

@@ -106,22 +108,22 @@ class CustomRepoClass(pygit2.Repository):
106108
assert r.head.target == SUBM_HEAD_SHA
107109

108110

109-
def test_name(repo):
111+
def test_name(repo: Repository) -> None:
110112
s = repo.submodules[SUBM_PATH]
111113
assert SUBM_NAME == s.name
112114

113115

114-
def test_path(repo):
116+
def test_path(repo: Repository) -> None:
115117
s = repo.submodules[SUBM_PATH]
116118
assert SUBM_PATH == s.path
117119

118120

119-
def test_url(repo):
121+
def test_url(repo: Repository) -> None:
120122
s = repo.submodules[SUBM_PATH]
121123
assert SUBM_URL == s.url
122124

123125

124-
def test_missing_url(repo):
126+
def test_missing_url(repo: Repository) -> None:
125127
# Remove "url" from .gitmodules
126128
with open(Path(repo.workdir, '.gitmodules'), 'wt') as f:
127129
f.write('[submodule "TestGitRepository"]\n')
@@ -131,7 +133,7 @@ def test_missing_url(repo):
131133

132134

133135
@utils.requires_network
134-
def test_init_and_update(repo):
136+
def test_init_and_update(repo: Repository) -> None:
135137
subrepo_file_path = Path(repo.workdir) / SUBM_PATH / 'master.txt'
136138
assert not subrepo_file_path.exists()
137139

@@ -148,7 +150,7 @@ def test_init_and_update(repo):
148150

149151

150152
@utils.requires_network
151-
def test_specified_update(repo):
153+
def test_specified_update(repo: Repository) -> None:
152154
subrepo_file_path = Path(repo.workdir) / SUBM_PATH / 'master.txt'
153155
assert not subrepo_file_path.exists()
154156
repo.submodules.init(submodules=['TestGitRepository'])
@@ -157,7 +159,7 @@ def test_specified_update(repo):
157159

158160

159161
@utils.requires_network
160-
def test_update_instance(repo):
162+
def test_update_instance(repo: Repository) -> None:
161163
subrepo_file_path = Path(repo.workdir) / SUBM_PATH / 'master.txt'
162164
assert not subrepo_file_path.exists()
163165
sm = repo.submodules['TestGitRepository']
@@ -168,7 +170,7 @@ def test_update_instance(repo):
168170

169171
@utils.requires_network
170172
@pytest.mark.parametrize('depth', [0, 1])
171-
def test_oneshot_update(repo, depth):
173+
def test_oneshot_update(repo: Repository, depth: int) -> None:
172174
status = repo.submodules.status(SUBM_NAME)
173175
assert status == (SS.IN_HEAD | SS.IN_INDEX | SS.IN_CONFIG | SS.WD_UNINITIALIZED)
174176

@@ -190,7 +192,7 @@ def test_oneshot_update(repo, depth):
190192

191193
@utils.requires_network
192194
@pytest.mark.parametrize('depth', [0, 1])
193-
def test_oneshot_update_instance(repo, depth):
195+
def test_oneshot_update_instance(repo: Repository, depth: int) -> None:
194196
subrepo_file_path = Path(repo.workdir) / SUBM_PATH / 'master.txt'
195197
assert not subrepo_file_path.exists()
196198
sm = repo.submodules[SUBM_NAME]
@@ -206,12 +208,12 @@ def test_oneshot_update_instance(repo, depth):
206208

207209

208210
@utils.requires_network
209-
def test_head_id(repo):
211+
def test_head_id(repo: Repository) -> None:
210212
assert repo.submodules[SUBM_PATH].head_id == SUBM_HEAD_SHA
211213

212214

213215
@utils.requires_network
214-
def test_head_id_null(repo):
216+
def test_head_id_null(repo: Repository) -> None:
215217
gitmodules_newlines = (
216218
'\n'
217219
'[submodule "uncommitted_submodule"]\n'
@@ -230,7 +232,7 @@ def test_head_id_null(repo):
230232

231233
@utils.requires_network
232234
@pytest.mark.parametrize('depth', [0, 1])
233-
def test_add_submodule(repo, depth):
235+
def test_add_submodule(repo: Repository, depth: int) -> None:
234236
sm_repo_path = 'test/testrepo'
235237
sm = repo.submodules.add(SUBM_URL, sm_repo_path, depth=depth)
236238

@@ -250,7 +252,7 @@ def test_add_submodule(repo, depth):
250252

251253

252254
@utils.requires_network
253-
def test_submodule_status(repo):
255+
def test_submodule_status(repo: Repository) -> None:
254256
common_status = SS.IN_HEAD | SS.IN_INDEX | SS.IN_CONFIG
255257

256258
# Submodule needs initializing
@@ -302,7 +304,7 @@ def test_submodule_status(repo):
302304
)
303305

304306

305-
def test_submodule_cache(repo):
307+
def test_submodule_cache(repo: Repository) -> None:
306308
# When the cache is turned on, looking up the same submodule twice must return the same git_submodule object
307309
repo.submodules.cache_all()
308310
sm1 = repo.submodules[SUBM_NAME]
@@ -317,7 +319,7 @@ def test_submodule_cache(repo):
317319
assert sm3._subm != sm4._subm
318320

319321

320-
def test_submodule_reload(repo):
322+
def test_submodule_reload(repo: Repository) -> None:
321323
sm = repo.submodules[SUBM_NAME]
322324
assert sm.url == 'https://github.com/libgit2/TestGitRepository'
323325

test/utils.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
import stat
3232
import sys
3333
import zipfile
34+
from typing import Optional
35+
from types import TracebackType
3436

3537
# Requirements
3638
import pytest
@@ -94,11 +96,11 @@ def rmtree(path):
9496

9597

9698
class TemporaryRepository:
97-
def __init__(self, name, tmp_path):
99+
def __init__(self, name: str, tmp_path: Path) -> None:
98100
self.name = name
99101
self.tmp_path = tmp_path
100102

101-
def __enter__(self):
103+
def __enter__(self) -> Path:
102104
path = Path(__file__).parent / 'data' / self.name
103105
temp_repo_path = Path(self.tmp_path) / path.stem
104106
if path.suffix == '.zip':
@@ -111,7 +113,12 @@ def __enter__(self):
111113

112114
return temp_repo_path
113115

114-
def __exit__(self, exc_type, exc_value, traceback):
116+
def __exit__(
117+
self,
118+
exc_type: Optional[type[BaseException]],
119+
exc_value: Optional[BaseException],
120+
traceback: Optional[TracebackType],
121+
) -> None:
115122
pass
116123

117124

0 commit comments

Comments
 (0)