Skip to content

Commit fe54118

Browse files
authored
Merge pull request #1311 from Yobmod/main
Drop 3.6, increase type strictness
2 parents d8a6398 + 84232f7 commit fe54118

22 files changed

+247
-218
lines changed

.github/workflows/pythonpackage.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ jobs:
1515
runs-on: ubuntu-latest
1616
strategy:
1717
matrix:
18-
python-version: [3.6, 3.7, 3.8, 3.9, "3.10.0-beta.4"]
18+
python-version: [3.7, 3.8, 3.9, "3.10.0-beta.4"]
1919

2020
steps:
2121
- uses: actions/checkout@v2

README.md

+42-45
Original file line numberDiff line numberDiff line change
@@ -24,32 +24,30 @@ or low-level like git-plumbing.
2424

2525
It provides abstractions of git objects for easy access of repository data, and additionally
2626
allows you to access the git repository more directly using either a pure python implementation,
27-
or the faster, but more resource intensive *git command* implementation.
27+
or the faster, but more resource intensive _git command_ implementation.
2828

2929
The object database implementation is optimized for handling large quantities of objects and large datasets,
3030
which is achieved by using low-level structures and data streaming.
3131

32-
3332
### DEVELOPMENT STATUS
3433

3534
This project is in **maintenance mode**, which means that
3635

37-
* …there will be no feature development, unless these are contributed
38-
* …there will be no bug fixes, unless they are relevant to the safety of users, or contributed
39-
* …issues will be responded to with waiting times of up to a month
36+
- …there will be no feature development, unless these are contributed
37+
- …there will be no bug fixes, unless they are relevant to the safety of users, or contributed
38+
- …issues will be responded to with waiting times of up to a month
4039

4140
The project is open to contributions of all kinds, as well as new maintainers.
4241

43-
4442
### REQUIREMENTS
4543

4644
GitPython needs the `git` executable to be installed on the system and available
4745
in your `PATH` for most operations.
4846
If it is not in your `PATH`, you can help GitPython find it by setting
4947
the `GIT_PYTHON_GIT_EXECUTABLE=<path/to/git>` environment variable.
5048

51-
* Git (1.7.x or newer)
52-
* Python >= 3.6
49+
- Git (1.7.x or newer)
50+
- Python >= 3.7
5351

5452
The list of dependencies are listed in `./requirements.txt` and `./test-requirements.txt`.
5553
The installer takes care of installing them for you.
@@ -98,57 +96,56 @@ See [Issue #525](https://github.com/gitpython-developers/GitPython/issues/525).
9896

9997
### RUNNING TESTS
10098

101-
*Important*: Right after cloning this repository, please be sure to have executed
99+
_Important_: Right after cloning this repository, please be sure to have executed
102100
the `./init-tests-after-clone.sh` script in the repository root. Otherwise
103101
you will encounter test failures.
104102

105-
On *Windows*, make sure you have `git-daemon` in your PATH. For MINGW-git, the `git-daemon.exe`
103+
On _Windows_, make sure you have `git-daemon` in your PATH. For MINGW-git, the `git-daemon.exe`
106104
exists in `Git\mingw64\libexec\git-core\`; CYGWIN has no daemon, but should get along fine
107105
with MINGW's.
108106

109-
Ensure testing libraries are installed.
110-
In the root directory, run: `pip install -r test-requirements.txt`
107+
Ensure testing libraries are installed.
108+
In the root directory, run: `pip install -r test-requirements.txt`
111109

112110
To lint, run: `flake8`
113111

114-
To typecheck, run: `mypy -p git`
112+
To typecheck, run: `mypy -p git`
115113

116114
To test, run: `pytest`
117115

118116
Configuration for flake8 is in the ./.flake8 file.
119117

120118
Configurations for mypy, pytest and coverage.py are in ./pyproject.toml.
121119

122-
The same linting and testing will also be performed against different supported python versions
120+
The same linting and testing will also be performed against different supported python versions
123121
upon submitting a pull request (or on each push if you have a fork with a "main" branch and actions enabled).
124122

125-
126123
### Contributions
127124

128125
Please have a look at the [contributions file][contributing].
129126

130127
### INFRASTRUCTURE
131128

132-
* [User Documentation](http://gitpython.readthedocs.org)
133-
* [Questions and Answers](http://stackexchange.com/filters/167317/gitpython)
134-
* Please post on stackoverflow and use the `gitpython` tag
135-
* [Issue Tracker](https://github.com/gitpython-developers/GitPython/issues)
136-
* Post reproducible bugs and feature requests as a new issue.
129+
- [User Documentation](http://gitpython.readthedocs.org)
130+
- [Questions and Answers](http://stackexchange.com/filters/167317/gitpython)
131+
- Please post on stackoverflow and use the `gitpython` tag
132+
- [Issue Tracker](https://github.com/gitpython-developers/GitPython/issues)
133+
- Post reproducible bugs and feature requests as a new issue.
137134
Please be sure to provide the following information if posting bugs:
138-
* GitPython version (e.g. `import git; git.__version__`)
139-
* Python version (e.g. `python --version`)
140-
* The encountered stack-trace, if applicable
141-
* Enough information to allow reproducing the issue
135+
- GitPython version (e.g. `import git; git.__version__`)
136+
- Python version (e.g. `python --version`)
137+
- The encountered stack-trace, if applicable
138+
- Enough information to allow reproducing the issue
142139

143140
### How to make a new release
144141

145-
* Update/verify the **version** in the `VERSION` file
146-
* Update/verify that the `doc/source/changes.rst` changelog file was updated
147-
* Commit everything
148-
* Run `git tag -s <version>` to tag the version in Git
149-
* Run `make release`
150-
* Close the milestone mentioned in the _changelog_ and create a new one. _Do not reuse milestones by renaming them_.
151-
* set the upcoming version in the `VERSION` file, usually be
142+
- Update/verify the **version** in the `VERSION` file
143+
- Update/verify that the `doc/source/changes.rst` changelog file was updated
144+
- Commit everything
145+
- Run `git tag -s <version>` to tag the version in Git
146+
- Run `make release`
147+
- Close the milestone mentioned in the _changelog_ and create a new one. _Do not reuse milestones by renaming them_.
148+
- set the upcoming version in the `VERSION` file, usually be
152149
incrementing the patch level, and possibly by appending `-dev`. Probably you
153150
want to `git push` once more.
154151

@@ -200,22 +197,22 @@ gpg --edit-key 4C08421980C9
200197

201198
### Projects using GitPython
202199

203-
* [PyDriller](https://github.com/ishepard/pydriller)
204-
* [Kivy Designer](https://github.com/kivy/kivy-designer)
205-
* [Prowl](https://github.com/nettitude/Prowl)
206-
* [Python Taint](https://github.com/python-security/pyt)
207-
* [Buster](https://github.com/axitkhurana/buster)
208-
* [git-ftp](https://github.com/ezyang/git-ftp)
209-
* [Git-Pandas](https://github.com/wdm0006/git-pandas)
210-
* [PyGitUp](https://github.com/msiemens/PyGitUp)
211-
* [PyJFuzz](https://github.com/mseclab/PyJFuzz)
212-
* [Loki](https://github.com/Neo23x0/Loki)
213-
* [Omniwallet](https://github.com/OmniLayer/omniwallet)
214-
* [GitViper](https://github.com/BeayemX/GitViper)
215-
* [Git Gud](https://github.com/bthayer2365/git-gud)
200+
- [PyDriller](https://github.com/ishepard/pydriller)
201+
- [Kivy Designer](https://github.com/kivy/kivy-designer)
202+
- [Prowl](https://github.com/nettitude/Prowl)
203+
- [Python Taint](https://github.com/python-security/pyt)
204+
- [Buster](https://github.com/axitkhurana/buster)
205+
- [git-ftp](https://github.com/ezyang/git-ftp)
206+
- [Git-Pandas](https://github.com/wdm0006/git-pandas)
207+
- [PyGitUp](https://github.com/msiemens/PyGitUp)
208+
- [PyJFuzz](https://github.com/mseclab/PyJFuzz)
209+
- [Loki](https://github.com/Neo23x0/Loki)
210+
- [Omniwallet](https://github.com/OmniLayer/omniwallet)
211+
- [GitViper](https://github.com/BeayemX/GitViper)
212+
- [Git Gud](https://github.com/bthayer2365/git-gud)
216213

217214
### LICENSE
218215

219-
New BSD License. See the LICENSE file.
216+
New BSD License. See the LICENSE file.
220217

221218
[contributing]: https://github.com/gitpython-developers/GitPython/blob/master/CONTRIBUTING.md

doc/source/intro.rst

+4-2
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,17 @@ The object database implementation is optimized for handling large quantities of
1313
Requirements
1414
============
1515

16-
* `Python`_ >= 3.6
16+
* `Python`_ >= 3.7
1717
* `Git`_ 1.7.0 or newer
1818
It should also work with older versions, but it may be that some operations
1919
involving remotes will not work as expected.
2020
* `GitDB`_ - a pure python git database implementation
21+
* `typing_extensions`_ >= 3.7.3.4 (if python < 3.10)
2122

2223
.. _Python: https://www.python.org
2324
.. _Git: https://git-scm.com/
2425
.. _GitDB: https://pypi.python.org/pypi/gitdb
26+
.. _typing_extensions: https://pypi.org/project/typing-extensions/
2527

2628
Installing GitPython
2729
====================
@@ -60,7 +62,7 @@ Leakage of System Resources
6062
---------------------------
6163

6264
GitPython is not suited for long-running processes (like daemons) as it tends to
63-
leak system resources. It was written in a time where destructors (as implemented
65+
leak system resources. It was written in a time where destructors (as implemented
6466
in the `__del__` method) still ran deterministically.
6567

6668
In case you still want to use it in such a context, you will want to search the

git/cmd.py

+17-20
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
from typing import (Any, AnyStr, BinaryIO, Callable, Dict, IO, Iterator, List, Mapping,
4343
Sequence, TYPE_CHECKING, TextIO, Tuple, Union, cast, overload)
4444

45-
from git.types import PathLike, Literal
45+
from git.types import PathLike, Literal, TBD
4646

4747
if TYPE_CHECKING:
4848
from git.repo.base import Repo
@@ -68,7 +68,7 @@
6868
# Documentation
6969
## @{
7070

71-
def handle_process_output(process: subprocess.Popen,
71+
def handle_process_output(process: Union[subprocess.Popen, 'Git.AutoInterrupt'],
7272
stdout_handler: Union[None,
7373
Callable[[AnyStr], None],
7474
Callable[[List[AnyStr]], None],
@@ -77,7 +77,7 @@ def handle_process_output(process: subprocess.Popen,
7777
Callable[[AnyStr], None],
7878
Callable[[List[AnyStr]], None]],
7979
finalizer: Union[None,
80-
Callable[[subprocess.Popen], None]] = None,
80+
Callable[[Union[subprocess.Popen, 'Git.AutoInterrupt']], None]] = None,
8181
decode_streams: bool = True) -> None:
8282
"""Registers for notifications to learn that process output is ready to read, and dispatches lines to
8383
the respective line handlers.
@@ -165,7 +165,7 @@ def dict_to_slots_and__excluded_are_none(self: object, d: Mapping[str, Any], exc
165165
## CREATE_NEW_PROCESS_GROUP is needed to allow killing it afterwards,
166166
# see https://docs.python.org/3/library/subprocess.html#subprocess.Popen.send_signal
167167
PROC_CREATIONFLAGS = (CREATE_NO_WINDOW | subprocess.CREATE_NEW_PROCESS_GROUP # type: ignore[attr-defined]
168-
if is_win else 0)
168+
if is_win else 0) # mypy error if not windows
169169

170170

171171
class Git(LazyMixin):
@@ -421,27 +421,27 @@ def __getattr__(self, attr: str) -> Any:
421421
return getattr(self.proc, attr)
422422

423423
# TODO: Bad choice to mimic `proc.wait()` but with different args.
424-
def wait(self, stderr: Union[None, bytes] = b'') -> int:
424+
def wait(self, stderr: Union[None, str, bytes] = b'') -> int:
425425
"""Wait for the process and return its status code.
426426
427427
:param stderr: Previously read value of stderr, in case stderr is already closed.
428428
:warn: may deadlock if output or error pipes are used and not handled separately.
429429
:raise GitCommandError: if the return status is not 0"""
430430
if stderr is None:
431-
stderr = b''
432-
stderr = force_bytes(data=stderr, encoding='utf-8')
431+
stderr_b = b''
432+
stderr_b = force_bytes(data=stderr, encoding='utf-8')
433433

434434
if self.proc is not None:
435435
status = self.proc.wait()
436436

437437
def read_all_from_possibly_closed_stream(stream: Union[IO[bytes], None]) -> bytes:
438438
if stream:
439439
try:
440-
return stderr + force_bytes(stream.read())
440+
return stderr_b + force_bytes(stream.read())
441441
except ValueError:
442-
return stderr or b''
442+
return stderr_b or b''
443443
else:
444-
return stderr or b''
444+
return stderr_b or b''
445445

446446
if status != 0:
447447
errstr = read_all_from_possibly_closed_stream(self.proc.stderr)
@@ -575,8 +575,8 @@ def __init__(self, working_dir: Union[None, PathLike] = None):
575575
self._environment: Dict[str, str] = {}
576576

577577
# cached command slots
578-
self.cat_file_header = None
579-
self.cat_file_all = None
578+
self.cat_file_header: Union[None, TBD] = None
579+
self.cat_file_all: Union[None, TBD] = None
580580

581581
def __getattr__(self, name: str) -> Any:
582582
"""A convenience method as it allows to call the command as if it was
@@ -1012,17 +1012,14 @@ def transform_kwargs(self, split_single_char_options: bool = True, **kwargs: Any
10121012

10131013
@classmethod
10141014
def __unpack_args(cls, arg_list: Sequence[str]) -> List[str]:
1015-
if not isinstance(arg_list, (list, tuple)):
1016-
return [str(arg_list)]
10171015

10181016
outlist = []
1019-
for arg in arg_list:
1020-
if isinstance(arg_list, (list, tuple)):
1017+
if isinstance(arg_list, (list, tuple)):
1018+
for arg in arg_list:
10211019
outlist.extend(cls.__unpack_args(arg))
1022-
# END recursion
1023-
else:
1024-
outlist.append(str(arg))
1025-
# END for each arg
1020+
else:
1021+
outlist.append(str(arg_list))
1022+
10261023
return outlist
10271024

10281025
def __call__(self, **kwargs: Any) -> 'Git':

git/compat.py

-18
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@
2929
Union,
3030
overload,
3131
)
32-
from git.types import TBD
33-
3432
# ---------------------------------------------------------------------------
3533

3634

@@ -97,19 +95,3 @@ def win_encode(s: Optional[AnyStr]) -> Optional[bytes]:
9795
elif s is not None:
9896
raise TypeError('Expected bytes or text, but got %r' % (s,))
9997
return None
100-
101-
102-
# type: ignore ## mypy cannot understand dynamic class creation
103-
def with_metaclass(meta: Type[Any], *bases: Any) -> TBD:
104-
"""copied from https://github.com/Byron/bcore/blob/master/src/python/butility/future.py#L15"""
105-
106-
class metaclass(meta): # type: ignore
107-
__call__ = type.__call__
108-
__init__ = type.__init__ # type: ignore
109-
110-
def __new__(cls, name: str, nbases: Optional[Tuple[int, ...]], d: Dict[str, Any]) -> TBD:
111-
if nbases is None:
112-
return type.__new__(cls, name, (), d)
113-
return meta(name, bases, d)
114-
115-
return metaclass(meta.__name__ + 'Helper', None, {}) # type: ignore

0 commit comments

Comments
 (0)