| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -10,14 +10,15 @@ | |||
| 10 | 10 | import locale | |
| 11 | 11 | import os | |
| 12 | 12 | import sys | |
| 13 | - from typing import AnyStr, Optional, Type | ||
| 14 | - | ||
| 15 | 13 | ||
| 16 | 14 | from gitdb.utils.encoding import ( | |
| 17 | 15 | force_bytes, # @UnusedImport | |
| 18 | 16 | force_text # @UnusedImport | |
| 19 | 17 | ) | |
| 20 | 18 | ||
| 19 | + from typing import Any, AnyStr, Dict, Optional, Type | ||
| 20 | + from git.types import TBD | ||
| 21 | + | ||
| 21 | 22 | ||
| 22 | 23 | is_win = (os.name == 'nt') # type: bool | |
| 23 | 24 | is_posix = (os.name == 'posix') | |
@@ -61,14 +62,17 @@ def win_encode(s: Optional[AnyStr]) -> Optional[bytes]: | |||
| 61 | 62 | return None | |
| 62 | 63 | ||
| 63 | 64 | ||
| 64 | - def with_metaclass(meta, *bases): | ||
| 65 | + def with_metaclass(meta: Type[Any], *bases: Any) -> 'metaclass': # type: ignore ## mypy cannot understand dynamic class creation | ||
| 65 | 66 | """copied from https://github.com/Byron/bcore/blob/master/src/python/butility/future.py#L15""" | |
| 66 | - class metaclass(meta): | ||
| 67 | + | ||
| 68 | + class metaclass(meta): # type: ignore | ||
| 67 | 69 | __call__ = type.__call__ | |
| 68 | - __init__ = type.__init__ | ||
| 70 | + __init__ = type.__init__ # type: ignore | ||
| 69 | 71 | ||
| 70 | - def __new__(cls, name, nbases, d): | ||
| 72 | + def __new__(cls, name: str, nbases: Optional[int], d: Dict[str, Any]) -> TBD: | ||
| 71 | 73 | if nbases is None: | |
| 72 | 74 | return type.__new__(cls, name, (), d) | |
| 73 | 75 | return meta(name, bases, d) | |
| 76 | + | ||
| 74 | 77 | return metaclass(meta.__name__ + 'Helper', None, {}) | |
| 78 | + | ||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -1,4 +1,5 @@ | |||
| 1 | 1 | """Module with our own gitdb implementation - it uses the git command""" | |
| 2 | + from typing import AnyStr | ||
| 2 | 3 | from git.util import bin_to_hex, hex_to_bin | |
| 3 | 4 | from gitdb.base import ( | |
| 4 | 5 | OInfo, | |
@@ -13,7 +14,7 @@ | |||
| 13 | 14 | # typing------------------------------------------------- | |
| 14 | 15 | ||
| 15 | 16 | from .cmd import Git | |
| 16 | - from .types import PathLike, TBD | ||
| 17 | + from .types import PathLike | ||
| 17 | 18 | ||
| 18 | 19 | # -------------------------------------------------------- | |
| 19 | 20 | ||
@@ -48,7 +49,7 @@ def stream(self, sha: bytes) -> OStream: | |||
| 48 | 49 | ||
| 49 | 50 | # { Interface | |
| 50 | 51 | ||
| 51 | - def partial_to_complete_sha_hex(self, partial_hexsha: str) -> bytes: | ||
| 52 | + def partial_to_complete_sha_hex(self, partial_hexsha: AnyStr) -> bytes: | ||
| 52 | 53 | """:return: Full binary 20 byte sha from the given partial hexsha | |
| 53 | 54 | :raise AmbiguousObjectName: | |
| 54 | 55 | :raise BadObject: | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -3,8 +3,8 @@ | |||
| 3 | 3 | # | |
| 4 | 4 | # This module is part of GitPython and is released under | |
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | - import re | ||
| 7 | 6 | ||
| 7 | + import re | ||
| 8 | 8 | from git.cmd import handle_process_output | |
| 9 | 9 | from git.compat import defenc | |
| 10 | 10 | from git.util import finalize_process, hex_to_bin | |
@@ -13,22 +13,33 @@ | |||
| 13 | 13 | from .objects.util import mode_str_to_int | |
| 14 | 14 | ||
| 15 | 15 | ||
| 16 | + # typing ------------------------------------------------------------------ | ||
| 17 | + | ||
| 18 | + from .objects.tree import Tree | ||
| 19 | + from git.repo.base import Repo | ||
| 20 | + from typing_extensions import Final, Literal | ||
| 21 | + from git.types import TBD | ||
| 22 | + from typing import Any, Iterator, List, Match, Optional, Tuple, Type, Union | ||
| 23 | + Lit_change_type = Literal['A', 'D', 'M', 'R', 'T'] | ||
| 24 | + | ||
| 25 | + # ------------------------------------------------------------------------ | ||
| 26 | + | ||
| 16 | 27 | __all__ = ('Diffable', 'DiffIndex', 'Diff', 'NULL_TREE') | |
| 17 | 28 | ||
| 18 | 29 | # Special object to compare against the empty tree in diffs | |
| 19 | - NULL_TREE = object() | ||
| 30 | + NULL_TREE: Final[object] = object() | ||
| 20 | 31 | ||
| 21 | 32 | _octal_byte_re = re.compile(b'\\\\([0-9]{3})') | |
| 22 | 33 | ||
| 23 | 34 | ||
| 24 | - def _octal_repl(matchobj): | ||
| 35 | + def _octal_repl(matchobj: Match) -> bytes: | ||
| 25 | 36 | value = matchobj.group(1) | |
| 26 | 37 | value = int(value, 8) | |
| 27 | 38 | value = bytes(bytearray((value,))) | |
| 28 | 39 | return value | |
| 29 | 40 | ||
| 30 | 41 | ||
| 31 | - def decode_path(path, has_ab_prefix=True): | ||
| 42 | + def decode_path(path: bytes, has_ab_prefix: bool = True) -> Optional[bytes]: | ||
| 32 | 43 | if path == b'/dev/null': | |
| 33 | 44 | return None | |
| 34 | 45 | ||
@@ -60,15 +71,17 @@ class Diffable(object): | |||
| 60 | 71 | class Index(object): | |
| 61 | 72 | pass | |
| 62 | 73 | ||
| 63 | - def _process_diff_args(self, args): | ||
| 74 | + def _process_diff_args(self, args: List[Union[str, 'Diffable', object]]) -> List[Union[str, 'Diffable', object]]: | ||
| 64 | 75 | """ | |
| 65 | 76 | :return: | |
| 66 | 77 | possibly altered version of the given args list. | |
| 67 | 78 | Method is called right before git command execution. | |
| 68 | 79 | Subclasses can use it to alter the behaviour of the superclass""" | |
| 69 | 80 | return args | |
| 70 | 81 | ||
| 71 | - def diff(self, other=Index, paths=None, create_patch=False, **kwargs): | ||
| 82 | + def diff(self, other: Union[Type[Index], Type[Tree], object, None, str] = Index, | ||
| 83 | + paths: Union[str, List[str], Tuple[str, ...], None] = None, | ||
| 84 | + create_patch: bool = False, **kwargs: Any) -> 'DiffIndex': | ||
| 72 | 85 | """Creates diffs between two items being trees, trees and index or an | |
| 73 | 86 | index and the working tree. It will detect renames automatically. | |
| 74 | 87 | ||
@@ -99,7 +112,7 @@ def diff(self, other=Index, paths=None, create_patch=False, **kwargs): | |||
| 99 | 112 | :note: | |
| 100 | 113 | On a bare repository, 'other' needs to be provided as Index or as | |
| 101 | 114 | as Tree/Commit, or a git command error will occur""" | |
| 102 | - args = [] | ||
| 115 | + args = [] # type: List[Union[str, Diffable, object]] | ||
| 103 | 116 | args.append("--abbrev=40") # we need full shas | |
| 104 | 117 | args.append("--full-index") # get full index paths, not only filenames | |
| 105 | 118 | ||
@@ -117,6 +130,9 @@ def diff(self, other=Index, paths=None, create_patch=False, **kwargs): | |||
| 117 | 130 | if paths is not None and not isinstance(paths, (tuple, list)): | |
| 118 | 131 | paths = [paths] | |
| 119 | 132 | ||
| 133 | + if hasattr(self, 'repo'): # else raise Error? | ||
| 134 | + self.repo = self.repo # type: 'Repo' | ||
| 135 | + | ||
| 120 | 136 | diff_cmd = self.repo.git.diff | |
| 121 | 137 | if other is self.Index: | |
| 122 | 138 | args.insert(0, '--cached') | |
@@ -163,7 +179,7 @@ class DiffIndex(list): | |||
| 163 | 179 | # T = Changed in the type | |
| 164 | 180 | change_type = ("A", "C", "D", "R", "M", "T") | |
| 165 | 181 | ||
| 166 | - def iter_change_type(self, change_type): | ||
| 182 | + def iter_change_type(self, change_type: Lit_change_type) -> Iterator['Diff']: | ||
| 167 | 183 | """ | |
| 168 | 184 | :return: | |
| 169 | 185 | iterator yielding Diff instances that match the given change_type | |
@@ -180,7 +196,7 @@ def iter_change_type(self, change_type): | |||
| 180 | 196 | if change_type not in self.change_type: | |
| 181 | 197 | raise ValueError("Invalid change type: %s" % change_type) | |
| 182 | 198 | ||
| 183 | - for diff in self: | ||
| 199 | + for diff in self: # type: 'Diff' | ||
| 184 | 200 | if diff.change_type == change_type: | |
| 185 | 201 | yield diff | |
| 186 | 202 | elif change_type == "A" and diff.new_file: | |
@@ -255,22 +271,21 @@ class Diff(object): | |||
| 255 | 271 | "new_file", "deleted_file", "copied_file", "raw_rename_from", | |
| 256 | 272 | "raw_rename_to", "diff", "change_type", "score") | |
| 257 | 273 | ||
| 258 | - def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode, | ||
| 259 | - b_mode, new_file, deleted_file, copied_file, raw_rename_from, | ||
| 260 | - raw_rename_to, diff, change_type, score): | ||
| 261 | - | ||
| 262 | - self.a_mode = a_mode | ||
| 263 | - self.b_mode = b_mode | ||
| 274 | + def __init__(self, repo: Repo, | ||
| 275 | + a_rawpath: Optional[bytes], b_rawpath: Optional[bytes], | ||
| 276 | + a_blob_id: Union[str, bytes, None], b_blob_id: Union[str, bytes, None], | ||
| 277 | + a_mode: Union[bytes, str, None], b_mode: Union[bytes, str, None], | ||
| 278 | + new_file: bool, deleted_file: bool, copied_file: bool, | ||
| 279 | + raw_rename_from: Optional[bytes], raw_rename_to: Optional[bytes], | ||
| 280 | + diff: Union[str, bytes, None], change_type: Optional[str], score: Optional[int]) -> None: | ||
| 264 | 281 | ||
| 265 | 282 | assert a_rawpath is None or isinstance(a_rawpath, bytes) | |
| 266 | 283 | assert b_rawpath is None or isinstance(b_rawpath, bytes) | |
| 267 | 284 | self.a_rawpath = a_rawpath | |
| 268 | 285 | self.b_rawpath = b_rawpath | |
| 269 | 286 | ||
| 270 | - if self.a_mode: | ||
| 271 | - self.a_mode = mode_str_to_int(self.a_mode) | ||
| 272 | - if self.b_mode: | ||
| 273 | - self.b_mode = mode_str_to_int(self.b_mode) | ||
| 287 | + self.a_mode = mode_str_to_int(a_mode) if a_mode else None | ||
| 288 | + self.b_mode = mode_str_to_int(b_mode) if b_mode else None | ||
| 274 | 289 | ||
| 275 | 290 | # Determine whether this diff references a submodule, if it does then | |
| 276 | 291 | # we need to overwrite "repo" to the corresponding submodule's repo instead | |
@@ -305,27 +320,27 @@ def __init__(self, repo, a_rawpath, b_rawpath, a_blob_id, b_blob_id, a_mode, | |||
| 305 | 320 | self.change_type = change_type | |
| 306 | 321 | self.score = score | |
| 307 | 322 | ||
| 308 | - def __eq__(self, other): | ||
| 323 | + def __eq__(self, other: object) -> bool: | ||
| 309 | 324 | for name in self.__slots__: | |
| 310 | 325 | if getattr(self, name) != getattr(other, name): | |
| 311 | 326 | return False | |
| 312 | 327 | # END for each name | |
| 313 | 328 | return True | |
| 314 | 329 | ||
| 315 | - def __ne__(self, other): | ||
| 330 | + def __ne__(self, other: object) -> bool: | ||
| 316 | 331 | return not (self == other) | |
| 317 | 332 | ||
| 318 | - def __hash__(self): | ||
| 333 | + def __hash__(self) -> int: | ||
| 319 | 334 | return hash(tuple(getattr(self, n) for n in self.__slots__)) | |
| 320 | 335 | ||
| 321 | - def __str__(self): | ||
| 322 | - h = "%s" | ||
| 336 | + def __str__(self) -> str: | ||
| 337 | + h = "%s" # type: str | ||
| 323 | 338 | if self.a_blob: | |
| 324 | 339 | h %= self.a_blob.path | |
| 325 | 340 | elif self.b_blob: | |
| 326 | 341 | h %= self.b_blob.path | |
| 327 | 342 | ||
| 328 | - msg = '' | ||
| 343 | + msg = '' # type: str | ||
| 329 | 344 | line = None # temp line | |
| 330 | 345 | line_length = 0 # line length | |
| 331 | 346 | for b, n in zip((self.a_blob, self.b_blob), ('lhs', 'rhs')): | |
@@ -354,7 +369,7 @@ def __str__(self): | |||
| 354 | 369 | if self.diff: | |
| 355 | 370 | msg += '\n---' | |
| 356 | 371 | try: | |
| 357 | - msg += self.diff.decode(defenc) | ||
| 372 | + msg += self.diff.decode(defenc) if isinstance(self.diff, bytes) else self.diff | ||
| 358 | 373 | except UnicodeDecodeError: | |
| 359 | 374 | msg += 'OMITTED BINARY DATA' | |
| 360 | 375 | # end handle encoding | |
@@ -368,36 +383,36 @@ def __str__(self): | |||
| 368 | 383 | return res | |
| 369 | 384 | ||
| 370 | 385 | @property | |
| 371 | - def a_path(self): | ||
| 386 | + def a_path(self) -> Optional[str]: | ||
| 372 | 387 | return self.a_rawpath.decode(defenc, 'replace') if self.a_rawpath else None | |
| 373 | 388 | ||
| 374 | 389 | @property | |
| 375 | - def b_path(self): | ||
| 390 | + def b_path(self) -> Optional[str]: | ||
| 376 | 391 | return self.b_rawpath.decode(defenc, 'replace') if self.b_rawpath else None | |
| 377 | 392 | ||
| 378 | 393 | @property | |
| 379 | - def rename_from(self): | ||
| 394 | + def rename_from(self) -> Optional[str]: | ||
| 380 | 395 | return self.raw_rename_from.decode(defenc, 'replace') if self.raw_rename_from else None | |
| 381 | 396 | ||
| 382 | 397 | @property | |
| 383 | - def rename_to(self): | ||
| 398 | + def rename_to(self) -> Optional[str]: | ||
| 384 | 399 | return self.raw_rename_to.decode(defenc, 'replace') if self.raw_rename_to else None | |
| 385 | 400 | ||
| 386 | 401 | @property | |
| 387 | - def renamed(self): | ||
| 402 | + def renamed(self) -> bool: | ||
| 388 | 403 | """:returns: True if the blob of our diff has been renamed | |
| 389 | 404 | :note: This property is deprecated, please use ``renamed_file`` instead. | |
| 390 | 405 | """ | |
| 391 | 406 | return self.renamed_file | |
| 392 | 407 | ||
| 393 | 408 | @property | |
| 394 | - def renamed_file(self): | ||
| 409 | + def renamed_file(self) -> bool: | ||
| 395 | 410 | """:returns: True if the blob of our diff has been renamed | |
| 396 | 411 | """ | |
| 397 | 412 | return self.rename_from != self.rename_to | |
| 398 | 413 | ||
| 399 | 414 | @classmethod | |
| 400 | - def _pick_best_path(cls, path_match, rename_match, path_fallback_match): | ||
| 415 | + def _pick_best_path(cls, path_match: bytes, rename_match: bytes, path_fallback_match: bytes) -> Optional[bytes]: | ||
| 401 | 416 | if path_match: | |
| 402 | 417 | return decode_path(path_match) | |
| 403 | 418 | ||
@@ -410,21 +425,23 @@ def _pick_best_path(cls, path_match, rename_match, path_fallback_match): | |||
| 410 | 425 | return None | |
| 411 | 426 | ||
| 412 | 427 | @classmethod | |
| 413 | - def _index_from_patch_format(cls, repo, proc): | ||
| 428 | + def _index_from_patch_format(cls, repo: Repo, proc: TBD) -> DiffIndex: | ||
| 414 | 429 | """Create a new DiffIndex from the given text which must be in patch format | |
| 415 | 430 | :param repo: is the repository we are operating on - it is required | |
| 416 | 431 | :param stream: result of 'git diff' as a stream (supporting file protocol) | |
| 417 | 432 | :return: git.DiffIndex """ | |
| 418 | 433 | ||
| 419 | 434 | ## FIXME: Here SLURPING raw, need to re-phrase header-regexes linewise. | |
| 420 | - text = [] | ||
| 421 | - handle_process_output(proc, text.append, None, finalize_process, decode_streams=False) | ||
| 435 | + text_list = [] # type: List[bytes] | ||
| 436 | + handle_process_output(proc, text_list.append, None, finalize_process, decode_streams=False) | ||
| 422 | 437 | ||
| 423 | 438 | # for now, we have to bake the stream | |
| 424 | - text = b''.join(text) | ||
| 439 | + text = b''.join(text_list) | ||
| 425 | 440 | index = DiffIndex() | |
| 426 | 441 | previous_header = None | |
| 427 | 442 | header = None | |
| 443 | + a_path, b_path = None, None # for mypy | ||
| 444 | + a_mode, b_mode = None, None # for mypy | ||
| 428 | 445 | for _header in cls.re_header.finditer(text): | |
| 429 | 446 | a_path_fallback, b_path_fallback, \ | |
| 430 | 447 | old_mode, new_mode, \ | |
@@ -464,27 +481,28 @@ def _index_from_patch_format(cls, repo, proc): | |||
| 464 | 481 | previous_header = _header | |
| 465 | 482 | header = _header | |
| 466 | 483 | # end for each header we parse | |
| 467 | - if index: | ||
| 484 | + if index and header: | ||
| 468 | 485 | index[-1].diff = text[header.end():] | |
| 469 | 486 | # end assign last diff | |
| 470 | 487 | ||
| 471 | 488 | return index | |
| 472 | 489 | ||
| 473 | 490 | @classmethod | |
| 474 | - def _index_from_raw_format(cls, repo, proc): | ||
| 491 | + def _index_from_raw_format(cls, repo: 'Repo', proc: TBD) -> DiffIndex: | ||
| 475 | 492 | """Create a new DiffIndex from the given stream which must be in raw format. | |
| 476 | 493 | :return: git.DiffIndex""" | |
| 477 | 494 | # handles | |
| 478 | 495 | # :100644 100644 687099101... 37c5e30c8... M .gitignore | |
| 479 | 496 | ||
| 480 | 497 | index = DiffIndex() | |
| 481 | 498 | ||
| 482 | - def handle_diff_line(lines): | ||
| 483 | - lines = lines.decode(defenc) | ||
| 499 | + def handle_diff_line(lines_bytes: bytes) -> None: | ||
| 500 | + lines = lines_bytes.decode(defenc) | ||
| 484 | 501 | ||
| 485 | 502 | for line in lines.split(':')[1:]: | |
| 486 | 503 | meta, _, path = line.partition('\x00') | |
| 487 | 504 | path = path.rstrip('\x00') | |
| 505 | + a_blob_id, b_blob_id = None, None # Type: Optional[str] | ||
| 488 | 506 | old_mode, new_mode, a_blob_id, b_blob_id, _change_type = meta.split(None, 4) | |
| 489 | 507 | # Change type can be R100 | |
| 490 | 508 | # R: status letter | |
@@ -504,20 +522,20 @@ def handle_diff_line(lines): | |||
| 504 | 522 | # NOTE: We cannot conclude from the existence of a blob to change type | |
| 505 | 523 | # as diffs with the working do not have blobs yet | |
| 506 | 524 | if change_type == 'D': | |
| 507 | - b_blob_id = None | ||
| 525 | + b_blob_id = None # Optional[str] | ||
| 508 | 526 | deleted_file = True | |
| 509 | 527 | elif change_type == 'A': | |
| 510 | 528 | a_blob_id = None | |
| 511 | 529 | new_file = True | |
| 512 | 530 | elif change_type == 'C': | |
| 513 | 531 | copied_file = True | |
| 514 | - a_path, b_path = path.split('\x00', 1) | ||
| 515 | - a_path = a_path.encode(defenc) | ||
| 516 | - b_path = b_path.encode(defenc) | ||
| 532 | + a_path_str, b_path_str = path.split('\x00', 1) | ||
| 533 | + a_path = a_path_str.encode(defenc) | ||
| 534 | + b_path = b_path_str.encode(defenc) | ||
| 517 | 535 | elif change_type == 'R': | |
| 518 | - a_path, b_path = path.split('\x00', 1) | ||
| 519 | - a_path = a_path.encode(defenc) | ||
| 520 | - b_path = b_path.encode(defenc) | ||
| 536 | + a_path_str, b_path_str = path.split('\x00', 1) | ||
| 537 | + a_path = a_path_str.encode(defenc) | ||
| 538 | + b_path = b_path_str.encode(defenc) | ||
| 521 | 539 | rename_from, rename_to = a_path, b_path | |
| 522 | 540 | elif change_type == 'T': | |
| 523 | 541 | # Nothing to do | |
| Back | FazBrowse Home | New Git URL |
0 commit comments