Movatterモバイル変換


[0]ホーム

URL:


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

Sign up
Appearance settings

Commit9523033

Browse files
authored
Merge pull request#1285 from Yobmod/main
Finish initial typing of Index and Submodule
2 parents0a6d9d6 +94c6652 commit9523033

File tree

20 files changed

+504
-311
lines changed

20 files changed

+504
-311
lines changed

‎git/cmd.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -831,7 +831,7 @@ def execute(self,
831831
exceptcmd_not_found_exceptionaserr:
832832
raiseGitCommandNotFound(redacted_command,err)fromerr
833833
else:
834-
proc=cast(Popen,proc)
834+
# replace with a typeguard for Popen[bytes]?
835835
proc.stdout=cast(BinaryIO,proc.stdout)
836836
proc.stderr=cast(BinaryIO,proc.stderr)
837837

‎git/config.py

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,14 @@
3131

3232
# typing-------------------------------------------------------
3333

34-
fromtypingimportAny,Callable,IO,List,Dict,Sequence,TYPE_CHECKING,Tuple,Union,cast,overload
34+
fromtypingimport (Any,Callable,IO,List,Dict,Sequence,
35+
TYPE_CHECKING,Tuple,Union,cast,overload)
3536

36-
fromgit.typesimportLiteral,Lit_config_levels,PathLike,TBD
37+
fromgit.typesimportLit_config_levels,ConfigLevels_Tup,PathLike,TBD,assert_never,is_config_level
3738

3839
ifTYPE_CHECKING:
3940
fromgit.repo.baseimportRepo
41+
fromioimportBytesIO
4042

4143
# -------------------------------------------------------------
4244

@@ -48,8 +50,10 @@
4850

4951
# invariants
5052
# represents the configuration level of a configuration file
51-
CONFIG_LEVELS= ("system","user","global","repository"
52-
)# type: Tuple[Literal['system'], Literal['user'], Literal['global'], Literal['repository']]
53+
54+
55+
CONFIG_LEVELS:ConfigLevels_Tup= ("system","user","global","repository")
56+
5357

5458
# Section pattern to detect conditional includes.
5559
# https://git-scm.com/docs/git-config#_conditional_includes
@@ -229,8 +233,9 @@ def get_config_path(config_level: Lit_config_levels) -> str:
229233
returnosp.normpath(osp.expanduser("~/.gitconfig"))
230234
elifconfig_level=="repository":
231235
raiseValueError("No repo to get repository configuration from. Use Repo._get_config_path")
232-
233-
raiseValueError("Invalid configuration level: %r"%config_level)
236+
else:
237+
# Should not reach here. Will raise ValueError if does. Static typing will warn missing elifs
238+
assert_never(config_level,ValueError(f"Invalid configuration level:{config_level!r}"))
234239

235240

236241
classGitConfigParser(with_metaclass(MetaParserBuilder,cp.RawConfigParser,object)):# type: ignore ## mypy does not understand dynamic class creation # noqa: E501
@@ -271,7 +276,7 @@ class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, obje
271276
# list of RawConfigParser methods able to change the instance
272277
_mutating_methods_= ("add_section","remove_section","remove_option","set")
273278

274-
def__init__(self,file_or_files:Union[None,PathLike,IO,Sequence[Union[PathLike,IO]]]=None,
279+
def__init__(self,file_or_files:Union[None,PathLike,'BytesIO',Sequence[Union[PathLike,'BytesIO']]]=None,
275280
read_only:bool=True,merge_includes:bool=True,
276281
config_level:Union[Lit_config_levels,None]=None,
277282
repo:Union['Repo',None]=None)->None:
@@ -300,13 +305,13 @@ def __init__(self, file_or_files: Union[None, PathLike, IO, Sequence[Union[PathL
300305
self._proxies=self._dict()
301306

302307
iffile_or_filesisnotNone:
303-
self._file_or_files=file_or_files# type: Union[PathLike,IO, Sequence[Union[PathLike,IO]]]
308+
self._file_or_files:Union[PathLike,'BytesIO',Sequence[Union[PathLike,'BytesIO']]]=file_or_files
304309
else:
305310
ifconfig_levelisNone:
306311
ifread_only:
307-
self._file_or_files= [get_config_path(f)# type: ignore
308-
forfinCONFIG_LEVELS# Can type f properly when 3.5 dropped
309-
iff!='repository']
312+
self._file_or_files= [get_config_path(f)
313+
forfinCONFIG_LEVELS
314+
ifis_config_level(f)andf!='repository']
310315
else:
311316
raiseValueError("No configuration level or configuration files specified")
312317
else:
@@ -323,15 +328,13 @@ def __init__(self, file_or_files: Union[None, PathLike, IO, Sequence[Union[PathL
323328
def_acquire_lock(self)->None:
324329
ifnotself._read_only:
325330
ifnotself._lock:
326-
ifisinstance(self._file_or_files, (tuple,list)):
327-
raiseValueError(
328-
"Write-ConfigParsers can operate on a single file only, multiple files have been passed")
329-
# END single file check
330-
331331
ifisinstance(self._file_or_files, (str,os.PathLike)):
332332
file_or_files=self._file_or_files
333+
elifisinstance(self._file_or_files, (tuple,list,Sequence)):
334+
raiseValueError(
335+
"Write-ConfigParsers can operate on a single file only, multiple files have been passed")
333336
else:
334-
file_or_files=cast(IO,self._file_or_files).name
337+
file_or_files=self._file_or_files.name
335338

336339
# END get filename from handle/stream
337340
# initialize lock base - we want to write
@@ -649,7 +652,7 @@ def write(self) -> None:
649652
a file lock"""
650653
self._assure_writable("write")
651654
ifnotself._dirty:
652-
return
655+
returnNone
653656

654657
ifisinstance(self._file_or_files, (list,tuple)):
655658
raiseAssertionError("Cannot write back if there is not exactly a single file to write to, have %i files"
@@ -665,7 +668,7 @@ def write(self) -> None:
665668
fp=self._file_or_files
666669

667670
# we have a physical file on disk, so get a lock
668-
is_file_lock=isinstance(fp, (str,IOBase))# can't use Pathlike until 3.5 dropped
671+
is_file_lock=isinstance(fp, (str,os.PathLike,IOBase))# can't use Pathlike until 3.5 dropped
669672
ifis_file_lockandself._lockisnotNone:# else raise Error?
670673
self._lock._obtain_lock()
671674

@@ -674,7 +677,7 @@ def write(self) -> None:
674677
withopen(fp,"wb")asfp_open:
675678
self._write(fp_open)
676679
else:
677-
fp=cast(IO,fp)
680+
fp=cast('BytesIO',fp)
678681
fp.seek(0)
679682
# make sure we do not overwrite into an existing file
680683
ifhasattr(fp,'truncate'):

‎git/diff.py

Lines changed: 58 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,26 @@
1515

1616
# typing ------------------------------------------------------------------
1717

18-
fromtypingimportAny,Iterator,List,Match,Optional,Tuple,Type,Union,TYPE_CHECKING
19-
fromgit.typesimportPathLike,TBD,Literal
18+
fromtypingimportAny,Iterator,List,Match,Optional,Tuple,Type,TypeVar,Union,TYPE_CHECKING
19+
fromgit.typesimportPathLike,TBD,Literal,TypeGuard
2020

2121
ifTYPE_CHECKING:
2222
from .objects.treeimportTree
23+
from .objectsimportCommit
2324
fromgit.repo.baseimportRepo
24-
25+
fromgit.objects.baseimportIndexObject
2526
fromsubprocessimportPopen
2627

27-
Lit_change_type=Literal['A','D','M','R','T']
28+
Lit_change_type=Literal['A','D','C','M','R','T','U']
29+
30+
31+
defis_change_type(inp:str)->TypeGuard[Lit_change_type]:
32+
# return True
33+
returninpin ['A','D','C','M','R','T','U']
2834

2935
# ------------------------------------------------------------------------
3036

37+
3138
__all__= ('Diffable','DiffIndex','Diff','NULL_TREE')
3239

3340
# Special object to compare against the empty tree in diffs
@@ -75,15 +82,16 @@ class Diffable(object):
7582
classIndex(object):
7683
pass
7784

78-
def_process_diff_args(self,args:List[Union[str,'Diffable',object]])->List[Union[str,'Diffable',object]]:
85+
def_process_diff_args(self,args:List[Union[str,'Diffable',Type['Diffable.Index'],object]]
86+
)->List[Union[str,'Diffable',Type['Diffable.Index'],object]]:
7987
"""
8088
:return:
8189
possibly altered version of the given args list.
8290
Method is called right before git command execution.
8391
Subclasses can use it to alter the behaviour of the superclass"""
8492
returnargs
8593

86-
defdiff(self,other:Union[Type[Index],Type['Tree'],object,None,str]=Index,
94+
defdiff(self,other:Union[Type['Index'],'Tree','Commit',None,str,object]=Index,
8795
paths:Union[PathLike,List[PathLike],Tuple[PathLike, ...],None]=None,
8896
create_patch:bool=False,**kwargs:Any)->'DiffIndex':
8997
"""Creates diffs between two items being trees, trees and index or an
@@ -116,7 +124,7 @@ def diff(self, other: Union[Type[Index], Type['Tree'], object, None, str] = Inde
116124
:note:
117125
On a bare repository, 'other' needs to be provided as Index or as
118126
as Tree/Commit, or a git command error will occur"""
119-
args= []# type: List[Union[str, Diffable, object]]
127+
args:List[Union[PathLike,Diffable,Type['Diffable.Index'],object]]= []
120128
args.append("--abbrev=40")# we need full shas
121129
args.append("--full-index")# get full index paths, not only filenames
122130

@@ -134,8 +142,8 @@ def diff(self, other: Union[Type[Index], Type['Tree'], object, None, str] = Inde
134142
ifpathsisnotNoneandnotisinstance(paths, (tuple,list)):
135143
paths= [paths]
136144

137-
ifhasattr(self,'repo'):# else raise Error?
138-
self.repo=self.repo# type: 'Repo'
145+
ifhasattr(self,'Has_Repo'):
146+
self.repo:Repo=self.repo
139147

140148
diff_cmd=self.repo.git.diff
141149
ifotherisself.Index:
@@ -169,7 +177,10 @@ def diff(self, other: Union[Type[Index], Type['Tree'], object, None, str] = Inde
169177
returnindex
170178

171179

172-
classDiffIndex(list):
180+
T_Diff=TypeVar('T_Diff',bound='Diff')
181+
182+
183+
classDiffIndex(List[T_Diff]):
173184

174185
"""Implements an Index for diffs, allowing a list of Diffs to be queried by
175186
the diff properties.
@@ -183,7 +194,7 @@ class DiffIndex(list):
183194
# T = Changed in the type
184195
change_type= ("A","C","D","R","M","T")
185196

186-
defiter_change_type(self,change_type:Lit_change_type)->Iterator['Diff']:
197+
defiter_change_type(self,change_type:Lit_change_type)->Iterator[T_Diff]:
187198
"""
188199
:return:
189200
iterator yielding Diff instances that match the given change_type
@@ -200,19 +211,19 @@ def iter_change_type(self, change_type: Lit_change_type) -> Iterator['Diff']:
200211
ifchange_typenotinself.change_type:
201212
raiseValueError("Invalid change type: %s"%change_type)
202213

203-
fordiffinself:# type: 'Diff'
204-
ifdiff.change_type==change_type:
205-
yielddiff
206-
elifchange_type=="A"anddiff.new_file:
207-
yielddiff
208-
elifchange_type=="D"anddiff.deleted_file:
209-
yielddiff
210-
elifchange_type=="C"anddiff.copied_file:
211-
yielddiff
212-
elifchange_type=="R"anddiff.renamed:
213-
yielddiff
214-
elifchange_type=="M"anddiff.a_blobanddiff.b_blobanddiff.a_blob!=diff.b_blob:
215-
yielddiff
214+
fordiffidxinself:
215+
ifdiffidx.change_type==change_type:
216+
yielddiffidx
217+
elifchange_type=="A"anddiffidx.new_file:
218+
yielddiffidx
219+
elifchange_type=="D"anddiffidx.deleted_file:
220+
yielddiffidx
221+
elifchange_type=="C"anddiffidx.copied_file:
222+
yielddiffidx
223+
elifchange_type=="R"anddiffidx.renamed:
224+
yielddiffidx
225+
elifchange_type=="M"anddiffidx.a_blobanddiffidx.b_blobanddiffidx.a_blob!=diffidx.b_blob:
226+
yielddiffidx
216227
# END for each diff
217228

218229

@@ -281,7 +292,7 @@ def __init__(self, repo: 'Repo',
281292
a_mode:Union[bytes,str,None],b_mode:Union[bytes,str,None],
282293
new_file:bool,deleted_file:bool,copied_file:bool,
283294
raw_rename_from:Optional[bytes],raw_rename_to:Optional[bytes],
284-
diff:Union[str,bytes,None],change_type:Optional[str],score:Optional[int])->None:
295+
diff:Union[str,bytes,None],change_type:Optional[Lit_change_type],score:Optional[int])->None:
285296

286297
asserta_rawpathisNoneorisinstance(a_rawpath,bytes)
287298
assertb_rawpathisNoneorisinstance(b_rawpath,bytes)
@@ -300,19 +311,21 @@ def __init__(self, repo: 'Repo',
300311
repo=submodule.module()
301312
break
302313

314+
self.a_blob:Union['IndexObject',None]
303315
ifa_blob_idisNoneora_blob_id==self.NULL_HEX_SHA:
304316
self.a_blob=None
305317
else:
306318
self.a_blob=Blob(repo,hex_to_bin(a_blob_id),mode=self.a_mode,path=self.a_path)
307319

320+
self.b_blob:Union['IndexObject',None]
308321
ifb_blob_idisNoneorb_blob_id==self.NULL_HEX_SHA:
309322
self.b_blob=None
310323
else:
311324
self.b_blob=Blob(repo,hex_to_bin(b_blob_id),mode=self.b_mode,path=self.b_path)
312325

313-
self.new_file=new_file
314-
self.deleted_file=deleted_file
315-
self.copied_file=copied_file
326+
self.new_file:bool=new_file
327+
self.deleted_file:bool=deleted_file
328+
self.copied_file:bool=copied_file
316329

317330
# be clear and use None instead of empty strings
318331
assertraw_rename_fromisNoneorisinstance(raw_rename_from,bytes)
@@ -321,7 +334,7 @@ def __init__(self, repo: 'Repo',
321334
self.raw_rename_to=raw_rename_toorNone
322335

323336
self.diff=diff
324-
self.change_type=change_type
337+
self.change_type:Union[Lit_change_type,None]=change_type
325338
self.score=score
326339

327340
def__eq__(self,other:object)->bool:
@@ -386,36 +399,36 @@ def __str__(self) -> str:
386399
# end
387400
returnres
388401

389-
@property
402+
@property
390403
defa_path(self)->Optional[str]:
391404
returnself.a_rawpath.decode(defenc,'replace')ifself.a_rawpathelseNone
392405

393-
@property
406+
@property
394407
defb_path(self)->Optional[str]:
395408
returnself.b_rawpath.decode(defenc,'replace')ifself.b_rawpathelseNone
396409

397-
@property
410+
@property
398411
defrename_from(self)->Optional[str]:
399412
returnself.raw_rename_from.decode(defenc,'replace')ifself.raw_rename_fromelseNone
400413

401-
@property
414+
@property
402415
defrename_to(self)->Optional[str]:
403416
returnself.raw_rename_to.decode(defenc,'replace')ifself.raw_rename_toelseNone
404417

405-
@property
418+
@property
406419
defrenamed(self)->bool:
407420
""":returns: True if the blob of our diff has been renamed
408421
:note: This property is deprecated, please use ``renamed_file`` instead.
409422
"""
410423
returnself.renamed_file
411424

412-
@property
425+
@property
413426
defrenamed_file(self)->bool:
414427
""":returns: True if the blob of our diff has been renamed
415428
"""
416429
returnself.rename_from!=self.rename_to
417430

418-
@classmethod
431+
@classmethod
419432
def_pick_best_path(cls,path_match:bytes,rename_match:bytes,path_fallback_match:bytes)->Optional[bytes]:
420433
ifpath_match:
421434
returndecode_path(path_match)
@@ -428,7 +441,7 @@ def _pick_best_path(cls, path_match: bytes, rename_match: bytes, path_fallback_m
428441

429442
returnNone
430443

431-
@classmethod
444+
@classmethod
432445
def_index_from_patch_format(cls,repo:'Repo',proc:TBD)->DiffIndex:
433446
"""Create a new DiffIndex from the given text which must be in patch format
434447
:param repo: is the repository we are operating on - it is required
@@ -441,7 +454,7 @@ def _index_from_patch_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:
441454

442455
# for now, we have to bake the stream
443456
text=b''.join(text_list)
444-
index=DiffIndex()
457+
index:'DiffIndex'=DiffIndex()
445458
previous_header=None
446459
header=None
447460
a_path,b_path=None,None# for mypy
@@ -491,19 +504,21 @@ def _index_from_patch_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex:
491504

492505
returnindex
493506

494-
@staticmethod
507+
@staticmethod
495508
def_handle_diff_line(lines_bytes:bytes,repo:'Repo',index:DiffIndex)->None:
496509
lines=lines_bytes.decode(defenc)
497510

498511
forlineinlines.split(':')[1:]:
499512
meta,_,path=line.partition('\x00')
500513
path=path.rstrip('\x00')
501-
a_blob_id,b_blob_id=None,None# Type: Optional[str]
514+
a_blob_id:Optional[str]
515+
b_blob_id:Optional[str]
502516
old_mode,new_mode,a_blob_id,b_blob_id,_change_type=meta.split(None,4)
503517
# Change type can be R100
504518
# R: status letter
505519
# 100: score (in case of copy and rename)
506-
change_type=_change_type[0]
520+
assertis_change_type(_change_type[0]),f"Unexpected value for change_type received:{_change_type[0]}"
521+
change_type:Lit_change_type=_change_type[0]
507522
score_str=''.join(_change_type[1:])
508523
score=int(score_str)ifscore_str.isdigit()elseNone
509524
path=path.strip()
@@ -543,14 +558,14 @@ def _handle_diff_line(lines_bytes: bytes, repo: 'Repo', index: DiffIndex) -> Non
543558
'',change_type,score)
544559
index.append(diff)
545560

546-
@classmethod
561+
@classmethod
547562
def_index_from_raw_format(cls,repo:'Repo',proc:'Popen')->'DiffIndex':
548563
"""Create a new DiffIndex from the given stream which must be in raw format.
549564
:return: git.DiffIndex"""
550565
# handles
551566
# :100644 100644 687099101... 37c5e30c8... M .gitignore
552567

553-
index=DiffIndex()
568+
index:'DiffIndex'=DiffIndex()
554569
handle_process_output(proc,lambdabyt:cls._handle_diff_line(byt,repo,index),
555570
None,finalize_process,decode_streams=False)
556571

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp