summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/pythonpackage.yml5
-rw-r--r--MANIFEST.in7
-rw-r--r--git/cmd.py2
-rw-r--r--git/compat.py30
-rw-r--r--git/config.py2
-rw-r--r--git/exc.py1
-rw-r--r--git/objects/__init__.py4
-rw-r--r--git/objects/base.py3
-rw-r--r--git/refs/reference.py4
-rw-r--r--mypy.ini7
-rw-r--r--tox.ini8
11 files changed, 60 insertions, 13 deletions
diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml
index eb5c894e..3c7215cb 100644
--- a/.github/workflows/pythonpackage.yml
+++ b/.github/workflows/pythonpackage.yml
@@ -47,6 +47,11 @@ jobs:
pip install flake8
# stop the build if there are Python syntax errors or undefined names
flake8 --ignore=W293,E265,E266,W503,W504,E731 --count --show-source --statistics
+ - name: Check types with mypy
+ run: |
+ set -x
+ pip install tox
+ tox -e type
- name: Test with nose
run: |
set -x
diff --git a/MANIFEST.in b/MANIFEST.in
index 5fd771db..f02721fc 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,10 +1,11 @@
-include VERSION
-include LICENSE
-include CHANGES
include AUTHORS
+include CHANGES
include CONTRIBUTING.md
+include LICENSE
include README.md
+include VERSION
include requirements.txt
+include test-requirements.txt
recursive-include doc *
recursive-exclude test *
diff --git a/git/cmd.py b/git/cmd.py
index e38261a0..ac3ca2ec 100644
--- a/git/cmd.py
+++ b/git/cmd.py
@@ -138,7 +138,7 @@ CREATE_NO_WINDOW = 0x08000000
## CREATE_NEW_PROCESS_GROUP is needed to allow killing it afterwards,
# see https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal
-PROC_CREATIONFLAGS = (CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP
+PROC_CREATIONFLAGS = (CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP # type: ignore[attr-defined]
if is_win else 0)
diff --git a/git/compat.py b/git/compat.py
index c9b83ba4..c4bd2aa3 100644
--- a/git/compat.py
+++ b/git/compat.py
@@ -18,7 +18,16 @@ from gitdb.utils.encoding import (
# typing --------------------------------------------------------------------
-from typing import IO, Any, AnyStr, Dict, Optional, Type, Union
+from typing import (
+ Any,
+ AnyStr,
+ Dict,
+ IO,
+ Optional,
+ Type,
+ Union,
+ overload,
+)
from git.types import TBD
# ---------------------------------------------------------------------------
@@ -30,6 +39,12 @@ is_darwin = (os.name == 'darwin')
defenc = sys.getfilesystemencoding()
+@overload
+def safe_decode(s: None) -> None: ...
+
+@overload
+def safe_decode(s: Union[IO[str], AnyStr]) -> str: ...
+
def safe_decode(s: Union[IO[str], AnyStr, None]) -> Optional[str]:
"""Safely decodes a binary string to unicode"""
if isinstance(s, str):
@@ -42,6 +57,12 @@ def safe_decode(s: Union[IO[str], AnyStr, None]) -> Optional[str]:
raise TypeError('Expected bytes or text, but got %r' % (s,))
+@overload
+def safe_encode(s: None) -> None: ...
+
+@overload
+def safe_encode(s: AnyStr) -> bytes: ...
+
def safe_encode(s: Optional[AnyStr]) -> Optional[bytes]:
"""Safely encodes a binary string to unicode"""
if isinstance(s, str):
@@ -54,6 +75,12 @@ def safe_encode(s: Optional[AnyStr]) -> Optional[bytes]:
raise TypeError('Expected bytes or text, but got %r' % (s,))
+@overload
+def win_encode(s: None) -> None: ...
+
+@overload
+def win_encode(s: AnyStr) -> bytes: ...
+
def win_encode(s: Optional[AnyStr]) -> Optional[bytes]:
"""Encode unicodes for process arguments on Windows."""
if isinstance(s, str):
@@ -65,7 +92,6 @@ def win_encode(s: Optional[AnyStr]) -> Optional[bytes]:
return None
-
def with_metaclass(meta: Type[Any], *bases: Any) -> 'metaclass': # type: ignore ## mypy cannot understand dynamic class creation
"""copied from https://github.com/Byron/bcore/blob/master/src/python/butility/future.py#L15"""
diff --git a/git/config.py b/git/config.py
index aadb0aac..1cb80475 100644
--- a/git/config.py
+++ b/git/config.py
@@ -216,7 +216,7 @@ def get_config_path(config_level: Literal['system', 'global', 'user', 'repositor
raise ValueError("Invalid configuration level: %r" % config_level)
-class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, object)):
+class GitConfigParser(with_metaclass(MetaParserBuilder, cp.RawConfigParser, object)): # type: ignore ## mypy does not understand dynamic class creation # noqa: E501
"""Implements specifics required to read git style configuration files.
diff --git a/git/exc.py b/git/exc.py
index 358e7ae4..6e646921 100644
--- a/git/exc.py
+++ b/git/exc.py
@@ -5,6 +5,7 @@
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
""" Module containing all exceptions thrown throughout the git package, """
+from gitdb.exc import BadName # NOQA @UnusedWildImport skipcq: PYL-W0401, PYL-W0614
from gitdb.exc import * # NOQA @UnusedWildImport skipcq: PYL-W0401, PYL-W0614
from git.compat import safe_decode
diff --git a/git/objects/__init__.py b/git/objects/__init__.py
index 23b2416a..897eb98f 100644
--- a/git/objects/__init__.py
+++ b/git/objects/__init__.py
@@ -16,8 +16,8 @@ from .tag import *
from .tree import *
# Fix import dependency - add IndexObject to the util module, so that it can be
# imported by the submodule.base
-smutil.IndexObject = IndexObject
-smutil.Object = Object
+smutil.IndexObject = IndexObject # type: ignore[attr-defined]
+smutil.Object = Object # type: ignore[attr-defined]
del(smutil)
# must come after submodule was made available
diff --git a/git/objects/base.py b/git/objects/base.py
index cccb5ec6..59f0e836 100644
--- a/git/objects/base.py
+++ b/git/objects/base.py
@@ -7,6 +7,7 @@ from git.util import LazyMixin, join_path_native, stream_copy, bin_to_hex
import gitdb.typ as dbtyp
import os.path as osp
+from typing import Optional # noqa: F401 unused import
from .util import get_object_type_by_name
@@ -24,7 +25,7 @@ class Object(LazyMixin):
TYPES = (dbtyp.str_blob_type, dbtyp.str_tree_type, dbtyp.str_commit_type, dbtyp.str_tag_type)
__slots__ = ("repo", "binsha", "size")
- type = None # to be set by subclass
+ type = None # type: Optional[str] # to be set by subclass
def __init__(self, repo, binsha):
"""Initialize an object by identifying it by its binary sha.
diff --git a/git/refs/reference.py b/git/refs/reference.py
index aaa9b63f..9014f555 100644
--- a/git/refs/reference.py
+++ b/git/refs/reference.py
@@ -103,7 +103,7 @@ class Reference(SymbolicReference, LazyMixin, Iterable):
#{ Remote Interface
- @property
+ @property # type: ignore ## mypy cannot deal with properties with an extra decorator (2021-04-21)
@require_remote_ref_path
def remote_name(self):
"""
@@ -114,7 +114,7 @@ class Reference(SymbolicReference, LazyMixin, Iterable):
# /refs/remotes/<remote name>/<branch_name>
return tokens[2]
- @property
+ @property # type: ignore ## mypy cannot deal with properties with an extra decorator (2021-04-21)
@require_remote_ref_path
def remote_head(self):
""":return: Name of the remote head itself, i.e. master.
diff --git a/mypy.ini b/mypy.ini
index 349266b7..b63d68fd 100644
--- a/mypy.ini
+++ b/mypy.ini
@@ -1,4 +1,9 @@
[mypy]
-disallow_untyped_defs = True
+# TODO: enable when we've fully annotated everything
+#disallow_untyped_defs = True
+
+# TODO: remove when 'gitdb' is fully annotated
+[mypy-gitdb.*]
+ignore_missing_imports = True
diff --git a/tox.ini b/tox.ini
index d9d1594d..a0cb1c9f 100644
--- a/tox.ini
+++ b/tox.ini
@@ -14,6 +14,14 @@ commands = coverage run --omit="git/test/*" -m unittest --buffer {posargs}
[testenv:flake8]
commands = flake8 --ignore=W293,E265,E266,W503,W504,E731 {posargs}
+[testenv:type]
+description = type check ourselves
+deps =
+ {[testenv]deps}
+ mypy
+commands =
+ mypy -p git
+
[testenv:venv]
commands = {posargs}