From 01c8d59e426ae097e486a0bffa5b21d2118a48c3 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Tue, 18 May 2021 14:39:47 +0100 Subject: Add initial types to objects.util.py --- git/objects/util.py | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index d15d83c3..e823d39a 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -17,6 +17,15 @@ import time import calendar from datetime import datetime, timedelta, tzinfo + +from typing import TYPE_CHECKING, Union + +if TYPE_CHECKING: + from .commit import Commit + from .blob import Blob + from .tag import TagObject + from .tree import Tree + __all__ = ('get_object_type_by_name', 'parse_date', 'parse_actor_and_date', 'ProcessStreamAdapter', 'Traversable', 'altz_to_utctz_str', 'utctz_to_altz', 'verify_utctz', 'Actor', 'tzoffset', 'utc') @@ -26,7 +35,7 @@ ZERO = timedelta(0) #{ Functions -def mode_str_to_int(modestr): +def mode_str_to_int(modestr: str) -> int: """ :param modestr: string like 755 or 644 or 100644 - only the last 6 chars will be used :return: @@ -41,7 +50,7 @@ def mode_str_to_int(modestr): return mode -def get_object_type_by_name(object_type_name): +def get_object_type_by_name(object_type_name: str) -> Union['Commit', 'TagObject', 'Tree', 'Blob']: """ :return: type suitable to handle the given object type name. Use the type to create new instances. @@ -65,7 +74,7 @@ def get_object_type_by_name(object_type_name): raise ValueError("Cannot handle unknown object type: %s" % object_type_name) -def utctz_to_altz(utctz): +def utctz_to_altz(utctz: str) -> int: """we convert utctz to the timezone in seconds, it is the format time.altzone returns. Git stores it as UTC timezone which has the opposite sign as well, which explains the -1 * ( that was made explicit here ) @@ -73,7 +82,7 @@ def utctz_to_altz(utctz): return -1 * int(float(utctz) / 100 * 3600) -def altz_to_utctz_str(altz): +def altz_to_utctz_str(altz: int) -> str: """As above, but inverses the operation, returning a string that can be used in commit objects""" utci = -1 * int((float(altz) / 3600) * 100) @@ -83,7 +92,7 @@ def altz_to_utctz_str(altz): return prefix + utcs -def verify_utctz(offset): +def verify_utctz(offset: str) -> str: """:raise ValueError: if offset is incorrect :return: offset""" fmt_exc = ValueError("Invalid timezone offset format: %s" % offset) @@ -101,6 +110,7 @@ def verify_utctz(offset): class tzoffset(tzinfo): + def __init__(self, secs_west_of_utc, name=None): self._offset = timedelta(seconds=-secs_west_of_utc) self._name = name or 'fixed' -- cgit v1.2.1 From 9c3255387fe2ce9b156cc06714148436ad2490d9 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 13:47:11 +0100 Subject: Add types to objects.util.py tzoffset parse_actor_and_date() --- git/objects/util.py | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index e823d39a..ebfb3758 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -17,14 +17,15 @@ import time import calendar from datetime import datetime, timedelta, tzinfo - -from typing import TYPE_CHECKING, Union +# typing ------------------------------------------------------------ +from typing import Literal, TYPE_CHECKING, Tuple, Union if TYPE_CHECKING: from .commit import Commit from .blob import Blob from .tag import TagObject from .tree import Tree + from subprocess import Popen __all__ = ('get_object_type_by_name', 'parse_date', 'parse_actor_and_date', 'ProcessStreamAdapter', 'Traversable', 'altz_to_utctz_str', 'utctz_to_altz', @@ -111,27 +112,27 @@ def verify_utctz(offset: str) -> str: class tzoffset(tzinfo): - def __init__(self, secs_west_of_utc, name=None): + def __init__(self, secs_west_of_utc: float, name: Union[None, str] = None) -> None: self._offset = timedelta(seconds=-secs_west_of_utc) self._name = name or 'fixed' - def __reduce__(self): + def __reduce__(self) -> Tuple['tzoffset', Tuple[float, str]]: return tzoffset, (-self._offset.total_seconds(), self._name) - def utcoffset(self, dt): + def utcoffset(self, dt) -> timedelta: return self._offset - def tzname(self, dt): + def tzname(self, dt) -> str: return self._name - def dst(self, dt): + def dst(self, dt) -> timedelta: return ZERO utc = tzoffset(0, 'UTC') -def from_timestamp(timestamp, tz_offset): +def from_timestamp(timestamp, tz_offset: float) -> datetime: """Converts a timestamp + tz_offset into an aware datetime instance.""" utc_dt = datetime.fromtimestamp(timestamp, utc) try: @@ -141,7 +142,7 @@ def from_timestamp(timestamp, tz_offset): return utc_dt -def parse_date(string_date): +def parse_date(string_date: str) -> Tuple[int, int]: """ Parse the given date as one of the following @@ -228,7 +229,7 @@ _re_actor_epoch = re.compile(r'^.+? (.*) (\d+) ([+-]\d+).*$') _re_only_actor = re.compile(r'^.+? (.*)$') -def parse_actor_and_date(line): +def parse_actor_and_date(line: str) -> Tuple[Actor, int, int]: """Parse out the actor (author or committer) info from a line like:: author Tom Preston-Werner 1191999972 -0700 @@ -257,7 +258,7 @@ class ProcessStreamAdapter(object): it if the instance goes out of scope.""" __slots__ = ("_proc", "_stream") - def __init__(self, process, stream_name): + def __init__(self, process: Popen, stream_name: str): self._proc = process self._stream = getattr(process, stream_name) -- cgit v1.2.1 From f875ddea28b09f2b78496266c80502d5dc2b7411 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 14:27:15 +0100 Subject: Mypy fixes --- git/objects/util.py | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index ebfb3758..6bc1b709 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -18,7 +18,7 @@ import calendar from datetime import datetime, timedelta, tzinfo # typing ------------------------------------------------------------ -from typing import Literal, TYPE_CHECKING, Tuple, Union +from typing import Literal, TYPE_CHECKING, Tuple, Type, Union, cast if TYPE_CHECKING: from .commit import Commit @@ -36,7 +36,7 @@ ZERO = timedelta(0) #{ Functions -def mode_str_to_int(modestr: str) -> int: +def mode_str_to_int(modestr: Union[bytes, str]) -> int: """ :param modestr: string like 755 or 644 or 100644 - only the last 6 chars will be used :return: @@ -46,12 +46,14 @@ def mode_str_to_int(modestr: str) -> int: for example.""" mode = 0 for iteration, char in enumerate(reversed(modestr[-6:])): + char = cast(Union[str, int], char) mode += int(char) << iteration * 3 # END for each char return mode -def get_object_type_by_name(object_type_name: str) -> Union['Commit', 'TagObject', 'Tree', 'Blob']: +def get_object_type_by_name(object_type_name: bytes + ) -> Union[Type['Commit'], Type['TagObject'], Type['Tree'], Type['Blob']]: """ :return: type suitable to handle the given object type name. Use the type to create new instances. @@ -72,7 +74,7 @@ def get_object_type_by_name(object_type_name: str) -> Union['Commit', 'TagObject from . import tree return tree.Tree else: - raise ValueError("Cannot handle unknown object type: %s" % object_type_name) + raise ValueError("Cannot handle unknown object type: %s" % object_type_name.decode()) def utctz_to_altz(utctz: str) -> int: @@ -116,7 +118,7 @@ class tzoffset(tzinfo): self._offset = timedelta(seconds=-secs_west_of_utc) self._name = name or 'fixed' - def __reduce__(self) -> Tuple['tzoffset', Tuple[float, str]]: + def __reduce__(self) -> Tuple[Type['tzoffset'], Tuple[float, str]]: return tzoffset, (-self._offset.total_seconds(), self._name) def utcoffset(self, dt) -> timedelta: @@ -163,18 +165,18 @@ def parse_date(string_date: str) -> Tuple[int, int]: # git time try: if string_date.count(' ') == 1 and string_date.rfind(':') == -1: - timestamp, offset = string_date.split() + timestamp, offset_str = string_date.split() if timestamp.startswith('@'): timestamp = timestamp[1:] - timestamp = int(timestamp) - return timestamp, utctz_to_altz(verify_utctz(offset)) + timestamp_int = int(timestamp) + return timestamp_int, utctz_to_altz(verify_utctz(offset_str)) else: - offset = "+0000" # local time by default + offset_str = "+0000" # local time by default if string_date[-5] in '-+': - offset = verify_utctz(string_date[-5:]) + offset_str = verify_utctz(string_date[-5:]) string_date = string_date[:-6] # skip space as well # END split timezone info - offset = utctz_to_altz(offset) + offset = utctz_to_altz(offset_str) # now figure out the date and time portion - split time date_formats = [] @@ -235,7 +237,7 @@ def parse_actor_and_date(line: str) -> Tuple[Actor, int, int]: author Tom Preston-Werner 1191999972 -0700 :return: [Actor, int_seconds_since_epoch, int_timezone_offset]""" - actor, epoch, offset = '', 0, 0 + actor, epoch, offset = '', '0', '0' m = _re_actor_epoch.search(line) if m: actor, epoch, offset = m.groups() -- cgit v1.2.1 From 82b03c2eb07f08dd5d6174a04e4288d41f49920f Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 14:29:11 +0100 Subject: flake8 fixes --- git/objects/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index 6bc1b709..b3073381 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -18,7 +18,7 @@ import calendar from datetime import datetime, timedelta, tzinfo # typing ------------------------------------------------------------ -from typing import Literal, TYPE_CHECKING, Tuple, Type, Union, cast +from typing import TYPE_CHECKING, Tuple, Type, Union, cast if TYPE_CHECKING: from .commit import Commit -- cgit v1.2.1 From c5c69071fd6c730d29c31759caddb0ba8b8e92c3 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 14:34:57 +0100 Subject: Mypy fixes --- git/objects/util.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index b3073381..c123b02a 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -27,6 +27,8 @@ if TYPE_CHECKING: from .tree import Tree from subprocess import Popen +# -------------------------------------------------------------------- + __all__ = ('get_object_type_by_name', 'parse_date', 'parse_actor_and_date', 'ProcessStreamAdapter', 'Traversable', 'altz_to_utctz_str', 'utctz_to_altz', 'verify_utctz', 'Actor', 'tzoffset', 'utc') -- cgit v1.2.1 From 82b60ab31cfa2ca146069df8dbc21ebfc917db0f Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 14:37:25 +0100 Subject: Change Popen to forwardref --- git/objects/util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index c123b02a..012f9f23 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -262,7 +262,7 @@ class ProcessStreamAdapter(object): it if the instance goes out of scope.""" __slots__ = ("_proc", "_stream") - def __init__(self, process: Popen, stream_name: str): + def __init__(self, process: 'Popen', stream_name: str): self._proc = process self._stream = getattr(process, stream_name) -- cgit v1.2.1 From c242b55d7c64ee43405f8b335c762bcf92189d38 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 17:34:26 +0100 Subject: Add types to objects.util.py ProcessStreamAdapter --- git/objects/util.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index 012f9f23..fdc1406b 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -18,7 +18,7 @@ import calendar from datetime import datetime, timedelta, tzinfo # typing ------------------------------------------------------------ -from typing import TYPE_CHECKING, Tuple, Type, Union, cast +from typing import Any, IO, TYPE_CHECKING, Tuple, Type, Union, cast if TYPE_CHECKING: from .commit import Commit @@ -262,11 +262,11 @@ class ProcessStreamAdapter(object): it if the instance goes out of scope.""" __slots__ = ("_proc", "_stream") - def __init__(self, process: 'Popen', stream_name: str): + def __init__(self, process: 'Popen', stream_name: str) -> None: self._proc = process - self._stream = getattr(process, stream_name) + self._stream = getattr(process, stream_name) # type: IO[str] ## guess - def __getattr__(self, attr): + def __getattr__(self, attr: str) -> Any: return getattr(self._stream, attr) -- cgit v1.2.1 From 5402a166a4971512f9d513bf36159dead9672ae9 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 20:44:53 +0100 Subject: Add types to objects _get_intermediate_items() --- git/objects/util.py | 64 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 13 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index fdc1406b..88183567 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -4,6 +4,8 @@ # This module is part of GitPython and is released under # the BSD License: http://www.opensource.org/licenses/bsd-license.php """Module for general utility functions""" + + from git.util import ( IterableList, Actor @@ -18,9 +20,10 @@ import calendar from datetime import datetime, timedelta, tzinfo # typing ------------------------------------------------------------ -from typing import Any, IO, TYPE_CHECKING, Tuple, Type, Union, cast +from typing import Any, Callable, IO, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload if TYPE_CHECKING: + from .submodule.base import Submodule from .commit import Commit from .blob import Blob from .tag import TagObject @@ -115,7 +118,7 @@ def verify_utctz(offset: str) -> str: class tzoffset(tzinfo): - + def __init__(self, secs_west_of_utc: float, name: Union[None, str] = None) -> None: self._offset = timedelta(seconds=-secs_west_of_utc) self._name = name or 'fixed' @@ -275,29 +278,61 @@ class Traversable(object): """Simple interface to perform depth-first or breadth-first traversals into one direction. Subclasses only need to implement one function. - Instances of the Subclass must be hashable""" + Instances of the Subclass must be hashable + + Defined subclasses = [Commit, Tree, SubModule] + """ __slots__ = () + @overload + @classmethod + def _get_intermediate_items(cls, item: 'Commit') -> Tuple['Commit', ...]: + ... + + @overload @classmethod - def _get_intermediate_items(cls, item): + def _get_intermediate_items(cls, item: 'Submodule') -> Tuple['Submodule', ...]: + ... + + @overload + @classmethod + def _get_intermediate_items(cls, item: 'Tree') -> Tuple['Tree', ...]: + ... + + @overload + @classmethod + def _get_intermediate_items(cls, item: 'Traversable') -> Tuple['Traversable', ...]: + ... + + @classmethod + def _get_intermediate_items(cls, item: 'Traversable' + ) -> Sequence['Traversable']: """ Returns: - List of items connected to the given item. + Tuple of items connected to the given item. Must be implemented in subclass + + class Commit:: (cls, Commit) -> Tuple[Commit, ...] + class Submodule:: (cls, Submodule) -> Iterablelist[Submodule] + class Tree:: (cls, Tree) -> Tuple[Tree, ...] """ raise NotImplementedError("To be implemented in subclass") - def list_traverse(self, *args, **kwargs): + def list_traverse(self, *args: Any, **kwargs: Any) -> IterableList: """ :return: IterableList with the results of the traversal as produced by traverse()""" - out = IterableList(self._id_attribute_) + out = IterableList(self._id_attribute_) # type: ignore[attr-defined] # defined in sublcasses out.extend(self.traverse(*args, **kwargs)) return out - def traverse(self, predicate=lambda i, d: True, - prune=lambda i, d: False, depth=-1, branch_first=True, - visit_once=True, ignore_self=1, as_edge=False): + def traverse(self, + predicate: Callable[[object, int], bool] = lambda i, d: True, + prune: Callable[[object, int], bool] = lambda i, d: False, + depth: int = -1, + branch_first: bool = True, + visit_once: bool = True, ignore_self: int = 1, as_edge: bool = False + ) -> Union[Iterator['Traversable'], Iterator[Tuple['Traversable', 'Traversable']]]: """:return: iterator yielding of items found when traversing self :param predicate: f(i,d) returns False if item i at depth d should not be included in the result @@ -329,13 +364,16 @@ class Traversable(object): destination, i.e. tuple(src, dest) with the edge spanning from source to destination""" visited = set() - stack = Deque() + stack = Deque() # type: Deque[Tuple[int, Traversable, Union[Traversable, None]]] stack.append((0, self, None)) # self is always depth level 0 - def addToStack(stack, item, branch_first, depth): + def addToStack(stack: Deque[Tuple[int, 'Traversable', Union['Traversable', None]]], + item: 'Traversable', + branch_first: bool, + depth) -> None: lst = self._get_intermediate_items(item) if not lst: - return + return None if branch_first: stack.extendleft((depth, i, item) for i in lst) else: -- cgit v1.2.1 From 6503ef72d90164840c06f168ab08f0426fb612bf Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 20:55:17 +0100 Subject: Add types to objects.util.py change deque to typing.Deque --- git/objects/util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index 88183567..106bab0e 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -12,7 +12,7 @@ from git.util import ( ) import re -from collections import deque as Deque +from collections import deque from string import digits import time @@ -20,7 +20,7 @@ import calendar from datetime import datetime, timedelta, tzinfo # typing ------------------------------------------------------------ -from typing import Any, Callable, IO, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload +from typing import Any, Callable, Deque, IO, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload if TYPE_CHECKING: from .submodule.base import Submodule @@ -364,7 +364,7 @@ class Traversable(object): destination, i.e. tuple(src, dest) with the edge spanning from source to destination""" visited = set() - stack = Deque() # type: Deque[Tuple[int, Traversable, Union[Traversable, None]]] + stack = deque() # type: Deque[Tuple[int, Traversable, Union[Traversable, None]]] stack.append((0, self, None)) # self is always depth level 0 def addToStack(stack: Deque[Tuple[int, 'Traversable', Union['Traversable', None]]], -- cgit v1.2.1 From c51f93823d46f0882b49822ce6f9e668228e5b8d Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 21:34:33 +0100 Subject: Add types to objects _serialize() and _deserialize() --- git/objects/util.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index 106bab0e..b94e9f12 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -5,7 +5,6 @@ # the BSD License: http://www.opensource.org/licenses/bsd-license.php """Module for general utility functions""" - from git.util import ( IterableList, Actor @@ -20,9 +19,10 @@ import calendar from datetime import datetime, timedelta, tzinfo # typing ------------------------------------------------------------ -from typing import Any, Callable, Deque, IO, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload +from typing import (Any, Callable, Deque, IO, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload) if TYPE_CHECKING: + from io import BytesIO from .submodule.base import Submodule from .commit import Commit from .blob import Blob @@ -412,14 +412,14 @@ class Serializable(object): """Defines methods to serialize and deserialize objects from and into a data stream""" __slots__ = () - def _serialize(self, stream): + def _serialize(self, stream: 'BytesIO') -> 'Serializable': """Serialize the data of this object into the given data stream :note: a serialized object would ``_deserialize`` into the same object :param stream: a file-like object :return: self""" raise NotImplementedError("To be implemented in subclass") - def _deserialize(self, stream): + def _deserialize(self, stream: 'BytesIO') -> 'Serializable': """Deserialize all information regarding this object from the stream :param stream: a file-like object :return: self""" -- cgit v1.2.1 From 90f0fb8f449b6d3e4f12c28d8699ee79a6763b80 Mon Sep 17 00:00:00 2001 From: Yobmod Date: Thu, 20 May 2021 21:51:56 +0100 Subject: change IO[str] to stringIO --- git/objects/util.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'git/objects/util.py') diff --git a/git/objects/util.py b/git/objects/util.py index b94e9f12..087f0166 100644 --- a/git/objects/util.py +++ b/git/objects/util.py @@ -19,10 +19,10 @@ import calendar from datetime import datetime, timedelta, tzinfo # typing ------------------------------------------------------------ -from typing import (Any, Callable, Deque, IO, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload) +from typing import (Any, Callable, Deque, Iterator, Sequence, TYPE_CHECKING, Tuple, Type, Union, cast, overload) if TYPE_CHECKING: - from io import BytesIO + from io import BytesIO, StringIO from .submodule.base import Submodule from .commit import Commit from .blob import Blob @@ -267,7 +267,7 @@ class ProcessStreamAdapter(object): def __init__(self, process: 'Popen', stream_name: str) -> None: self._proc = process - self._stream = getattr(process, stream_name) # type: IO[str] ## guess + self._stream = getattr(process, stream_name) # type: StringIO ## guess def __getattr__(self, attr: str) -> Any: return getattr(self._stream, attr) -- cgit v1.2.1