Skip to content

Drop 3.6, increase type strictness #1311

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 36 commits into from
Aug 3, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
39d37d5
replace some TBDs wiht runtime types
Yobmod Jul 31, 2021
c878771
replace more TBDs wiht runtime types
Yobmod Jul 31, 2021
009017e
Merge branch 'gitpython-developers:main' into main
Yobmod Aug 2, 2021
2163322
increase mypy strictness (warn unused ignored)
Yobmod Aug 2, 2021
0525c17
Merge branch 'main' of https://github.com/Yobmod/GitPython
Yobmod Aug 2, 2021
91fce33
increase mypy strictness (warn unused ignored and warn unreachable)
Yobmod Aug 2, 2021
15ace87
rmv 3.6 from CI matrix
Yobmod Aug 2, 2021
bef2182
rmv 3.6 from setup.py
Yobmod Aug 2, 2021
270c3d7
rmv 3.6 README
Yobmod Aug 2, 2021
c3f3501
Add __future__.annotations to cmd.py
Yobmod Aug 2, 2021
829142d
Add __future__.annotations to cmd.py2
Yobmod Aug 2, 2021
13e0730
Fix parse_date typing
Yobmod Aug 2, 2021
730f119
Fix parse_date typing 2
Yobmod Aug 2, 2021
2fe13ca
Fix parse_date typing 3
Yobmod Aug 2, 2021
024b696
Fix parse_date typing 4
Yobmod Aug 2, 2021
e2f8367
Fix parse_date typing 5
Yobmod Aug 2, 2021
d30bc07
Fix parse_date typing 6
Yobmod Aug 2, 2021
6470ad4
Fix parse_date typing 7
Yobmod Aug 2, 2021
481f672
Add __future__.annotations to repo/base.py
Yobmod Aug 2, 2021
9de7310
Minor type fixes
Yobmod Aug 2, 2021
5647d58
Merge branch 'gitpython-developers:main' into main
Yobmod Aug 2, 2021
f34a39f
Test new union syntax (Pep604)
Yobmod Aug 2, 2021
3b53d28
Merge branch 'main' of https://github.com/Yobmod/GitPython
Yobmod Aug 2, 2021
4dd06c3
Test trailing comma in args (>py3.6?)
Yobmod Aug 2, 2021
94ae0c5
Test Dataclass in repo.base.blame()
Yobmod Aug 2, 2021
a3f5b13
Test Dataclass in repo.base.blame() 2
Yobmod Aug 2, 2021
a2a36e0
Test Dataclass in repo.base.blame() 3
Yobmod Aug 2, 2021
ed137cb
Test TypedDict in repo.base.blame() 2
Yobmod Aug 2, 2021
e4761ff
Test TypedDict in repo.base.blame() 1
Yobmod Aug 2, 2021
1aaa704
Test Dataclass in repo.base.blame() 4
Yobmod Aug 2, 2021
bc9bcf5
Test Dataclass in repo.base.blame() 5
Yobmod Aug 2, 2021
ad417ba
Test Dataclass in repo.base.blame() 6
Yobmod Aug 2, 2021
ecb1f79
Choose TypedDict!
Yobmod Aug 2, 2021
5aa8c34
Improve type of repo.blame_incremental()
Yobmod Aug 2, 2021
8b8aa16
Improve type of repo.currently_rebasing_on()
Yobmod Aug 2, 2021
84232f7
Add Typing :: Typed to setup.py
Yobmod Aug 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Test Dataclass in repo.base.blame()
  • Loading branch information
Yobmod committed Aug 2, 2021
commit 94ae0c5839cf8de3b67c8dfd449ad9cef696aefb
103 changes: 66 additions & 37 deletions git/repo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import logging
import os
import re
from dataclasses import dataclass
import shlex
import warnings
from gitdb.db.loose import LooseObjectDB
Expand Down Expand Up @@ -41,7 +42,7 @@
from git.types import TBD, PathLike, Lit_config_levels, Commit_ish, Tree_ish, assert_never
from typing import (Any, BinaryIO, Callable, Dict,
Iterator, List, Mapping, Optional, Sequence,
TextIO, Tuple, Type, Union,
TextIO, Tuple, Type, TypedDict, Union,
NamedTuple, cast, TYPE_CHECKING)

from git.types import ConfigLevels_Tup
Expand All @@ -53,7 +54,6 @@
from git.objects.submodule.base import UpdateProgress
from git.remote import RemoteProgress


# -----------------------------------------------------------

log = logging.getLogger(__name__)
Expand Down Expand Up @@ -874,7 +874,7 @@ def blame_incremental(self, rev: str | HEAD, file: str, **kwargs: Any) -> Iterat
range(orig_lineno, orig_lineno + num_lines))

def blame(self, rev: Union[str, HEAD], file: str, incremental: bool = False, **kwargs: Any
) -> Union[List[List[Union[Optional['Commit'], List[str]]]], Optional[Iterator[BlameEntry]]]:
) -> List[List[Commit | List[str | bytes] | None]] | Iterator[BlameEntry] | None:
"""The blame information for the given file at the given revision.

:param rev: revision specifier, see git-rev-parse for viable options.
Expand All @@ -886,25 +886,52 @@ def blame(self, rev: Union[str, HEAD], file: str, incremental: bool = False, **k
if incremental:
return self.blame_incremental(rev, file, **kwargs)

data = self.git.blame(rev, '--', file, p=True, stdout_as_string=False, **kwargs)
commits: Dict[str, TBD] = {}
blames: List[List[Union[Optional['Commit'], List[str]]]] = []

info: Dict[str, TBD] = {} # use Any until TypedDict available
data: bytes = self.git.blame(rev, '--', file, p=True, stdout_as_string=False, **kwargs)
commits: Dict[str, Commit] = {}
blames: List[List[Commit | List[str | bytes] | None]] = []

class InfoTC(TypedDict, total=False):
sha: str
id: str
filename: str
summary: str
author: str
author_email: str
author_date: int
committer: str
committer_email: str
committer_date: int

@dataclass
class InfoDC(Dict[str, Union[str, int]]):
sha: str = ''
id: str = ''
filename: str = ''
summary: str = ''
author: str = ''
author_email: str = ''
author_date: int = 0
committer: str = ''
committer_email: str = ''
committer_date: int = 0

# info: InfoTD = {}
info = InfoDC()

keepends = True
for line in data.splitlines(keepends):
for line_bytes in data.splitlines(keepends):
try:
line = line.rstrip().decode(defenc)
line_str = line_bytes.rstrip().decode(defenc)
except UnicodeDecodeError:
firstpart = ''
parts = ['']
is_binary = True
else:
# As we don't have an idea when the binary data ends, as it could contain multiple newlines
# in the process. So we rely on being able to decode to tell us what is is.
# This can absolutely fail even on text files, but even if it does, we should be fine treating it
# as binary instead
parts = self.re_whitespace.split(line, 1)
parts = self.re_whitespace.split(line_str, 1)
firstpart = parts[0]
is_binary = False
# end handle decode of line
Expand All @@ -916,10 +943,10 @@ def blame(self, rev: Union[str, HEAD], file: str, incremental: bool = False, **k
# another line of blame with the same data
digits = parts[-1].split(" ")
if len(digits) == 3:
info = {'id': firstpart}
info.id = firstpart
blames.append([None, []])
elif info['id'] != firstpart:
info = {'id': firstpart}
elif info.id != firstpart:
info.id = firstpart
blames.append([commits.get(firstpart), []])
# END blame data initialization
else:
Expand All @@ -936,9 +963,9 @@ def blame(self, rev: Union[str, HEAD], file: str, incremental: bool = False, **k
# committer-tz -0700 - IGNORED BY US
role = m.group(0)
if firstpart.endswith('-mail'):
info["%s_email" % role] = parts[-1]
info[f"{role}_email"] = parts[-1]
elif firstpart.endswith('-time'):
info["%s_date" % role] = int(parts[-1])
info[f"{role}_date"] = int(parts[-1])
elif role == firstpart:
info[role] = parts[-1]
# END distinguish mail,time,name
Expand All @@ -953,38 +980,40 @@ def blame(self, rev: Union[str, HEAD], file: str, incremental: bool = False, **k
info['summary'] = parts[-1]
elif firstpart == '':
if info:
sha = info['id']
sha = info.id
c = commits.get(sha)
if c is None:
c = Commit(self, hex_to_bin(sha),
author=Actor._from_string(info['author'] + ' ' + info['author_email']),
authored_date=info['author_date'],
author=Actor._from_string(info.author + ' ' + info.author_email),
authored_date=info.author_date,
committer=Actor._from_string(
info['committer'] + ' ' + info['committer_email']),
committed_date=info['committer_date'])
info.committer + ' ' + info.committer_email),
committed_date=info.committer_date)
commits[sha] = c
blames[-1][0] = c
# END if commit objects needs initial creation
if not is_binary:
if line and line[0] == '\t':
line = line[1:]
else:
# NOTE: We are actually parsing lines out of binary data, which can lead to the
# binary being split up along the newline separator. We will append this to the blame
# we are currently looking at, even though it should be concatenated with the last line
# we have seen.
pass
# end handle line contents
blames[-1][0] = c
if blames[-1][1] is not None:
blames[-1][1].append(line)
info = {'id': sha}
if not is_binary:
if line_str and line_str[0] == '\t':
line_str = line_str[1:]

blames[-1][1].append(line_str)
else:
# NOTE: We are actually parsing lines out of binary data, which can lead to the
# binary being split up along the newline separator. We will append this to the
# blame we are currently looking at, even though it should be concatenated with
# the last line we have seen.
blames[-1][1].append(line_bytes)
# end handle line contents

info.id = sha
# END if we collected commit info
# END distinguish filename,summary,rest
# END distinguish author|committer vs filename,summary,rest
# END distinguish hexsha vs other information
return blames

@classmethod
@ classmethod
def init(cls, path: Union[PathLike, None] = None, mkdir: bool = True, odbt: Type[GitCmdObjectDB] = GitCmdObjectDB,
expand_vars: bool = True, **kwargs: Any) -> 'Repo':
"""Initialize a git repository at the given path if specified
Expand Down Expand Up @@ -1023,7 +1052,7 @@ def init(cls, path: Union[PathLike, None] = None, mkdir: bool = True, odbt: Type
git.init(**kwargs)
return cls(path, odbt=odbt)

@classmethod
@ classmethod
def _clone(cls, git: 'Git', url: PathLike, path: PathLike, odb_default_type: Type[GitCmdObjectDB],
progress: Union['RemoteProgress', 'UpdateProgress', Callable[..., 'RemoteProgress'], None] = None,
multi_options: Optional[List[str]] = None, **kwargs: Any
Expand Down Expand Up @@ -1101,7 +1130,7 @@ def clone(self, path: PathLike, progress: Optional[Callable] = None,
:return: ``git.Repo`` (the newly cloned repo)"""
return self._clone(self.git, self.common_dir, path, type(self.odb), progress, multi_options, **kwargs)

@classmethod
@ classmethod
def clone_from(cls, url: PathLike, to_path: PathLike, progress: Optional[Callable] = None,
env: Optional[Mapping[str, Any]] = None,
multi_options: Optional[List[str]] = None, **kwargs: Any) -> 'Repo':
Expand Down
2 changes: 1 addition & 1 deletion git/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
PathLike = Union[str, os.PathLike]
elif sys.version_info[:2] >= (3, 9):
# os.PathLike only becomes subscriptable from Python 3.9 onwards
PathLike = Union[str, 'os.PathLike[str]'] # forward ref as pylance complains unless editing with py3.9+
PathLike = Union[str, os.PathLike]

if TYPE_CHECKING:
from git.repo import Repo
Expand Down