Skip to content
5 changes: 5 additions & 0 deletions .github/workflows/pythonpackage.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 4 additions & 3 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -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 *
Expand Down
2 changes: 1 addition & 1 deletion git/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ def dict_to_slots_and__excluded_are_none(self, d, excluded=()):

## 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)


Expand Down
30 changes: 28 additions & 2 deletions git/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,16 @@

# 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

# ---------------------------------------------------------------------------
Expand All @@ -30,6 +39,12 @@
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):
Expand All @@ -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):
Expand All @@ -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):
Expand All @@ -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"""

Expand Down
2 changes: 1 addition & 1 deletion git/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
1 change: 1 addition & 0 deletions git/exc.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
4 changes: 2 additions & 2 deletions git/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
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
Expand Down
3 changes: 2 additions & 1 deletion git/objects/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

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

Expand All @@ -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.
Expand Down
4 changes: 2 additions & 2 deletions git/refs/reference.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ def iter_items(cls, repo, common_path=None):

#{ 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):
"""
Expand All @@ -114,7 +114,7 @@ def remote_name(self):
# /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.
Expand Down
7 changes: 6 additions & 1 deletion mypy.ini
Original file line number Diff line number Diff line change
@@ -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
8 changes: 8 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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}

Expand Down