diff --git a/.github/workflows/cygwin-test.yml b/.github/workflows/cygwin-test.yml index 808dc5608..962791ae7 100644 --- a/.github/workflows/cygwin-test.yml +++ b/.github/workflows/cygwin-test.yml @@ -12,38 +12,53 @@ jobs: SHELLOPTS: igncr TMP: "/tmp" TEMP: "/tmp" + defaults: + run: + shell: bash.exe --noprofile --norc -exo pipefail -o igncr "{0}" steps: - name: Force LF line endings run: git config --global core.autocrlf input + - uses: actions/checkout@v4 with: - fetch-depth: 9999 + fetch-depth: 0 + submodules: recursive + - uses: cygwin/cygwin-install-action@v4 with: packages: python39 python39-pip python39-virtualenv git + + - name: Show python and git versions + run: | + /usr/bin/python --version + /usr/bin/git version + - name: Tell git to trust this repo - shell: bash.exe -eo pipefail -o igncr "{0}" run: | - /usr/bin/git config --global --add safe.directory "$(pwd)" - - name: Install dependencies and prepare tests - shell: bash.exe -eo pipefail -o igncr "{0}" + /usr/bin/git config --global --add safe.directory "$(pwd)" + + - name: Prepare this repo for tests run: | - set -x - /usr/bin/python -m pip install --upgrade pip setuptools wheel - /usr/bin/python --version; /usr/bin/git --version - /usr/bin/git submodule update --init --recursive - /usr/bin/git fetch --tags - /usr/bin/python -m pip install -r requirements.txt - /usr/bin/python -m pip install -r test-requirements.txt TRAVIS=yes ./init-tests-after-clone.sh + + - name: Further prepare git configuration for tests + run: | /usr/bin/git config --global user.email "travis@ci.com" /usr/bin/git config --global user.name "Travis Runner" # If we rewrite the user's config by accident, we will mess it up # and cause subsequent tests to fail cat test/fixtures/.gitconfig >> ~/.gitconfig + + - name: Update PyPA packages + run: | + /usr/bin/python -m pip install --upgrade pip setuptools wheel + + - name: Install project and test dependencies + run: | + /usr/bin/python -m pip install ".[test]" + - name: Test with pytest - shell: bash.exe -eo pipefail -o igncr "{0}" run: | + set +x /usr/bin/python -m pytest - continue-on-error: false diff --git a/.github/workflows/pythonpackage.yml b/.github/workflows/pythonpackage.yml index a6af507d1..a5467ef94 100644 --- a/.github/workflows/pythonpackage.yml +++ b/.github/workflows/pythonpackage.yml @@ -15,51 +15,70 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.7, 3.8, 3.9, "3.10", "3.11"] + python-version: ["3.7", "3.8", "3.9", "3.10", "3.11", "3.12"] + include: + - experimental: false + - python-version: "3.12" + experimental: true + defaults: + run: + shell: /bin/bash --noprofile --norc -exo pipefail {0} steps: - uses: actions/checkout@v4 with: - fetch-depth: 9999 + fetch-depth: 0 + submodules: recursive + - name: Set up Python ${{ matrix.python-version }} uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} - - name: Install dependencies and prepare tests - run: | - set -x + allow-prereleases: ${{ matrix.experimental }} - python -m pip install --upgrade pip setuptools wheel - python --version; git --version - git submodule update --init --recursive - git fetch --tags --force + - name: Show python and git versions + run: | + python --version + git version - pip install -r requirements.txt - pip install -r test-requirements.txt + - name: Prepare this repo for tests + run: | TRAVIS=yes ./init-tests-after-clone.sh + - name: Prepare git configuration for tests + run: | git config --global user.email "travis@ci.com" git config --global user.name "Travis Runner" # If we rewrite the user's config by accident, we will mess it up # and cause subsequent tests to fail cat test/fixtures/.gitconfig >> ~/.gitconfig + - name: Update PyPA packages + run: | + python -m pip install --upgrade pip + if pip freeze --all | grep --quiet '^setuptools=='; then + # Python prior to 3.12 ships setuptools. Upgrade it if present. + python -m pip install --upgrade setuptools + fi + python -m pip install --upgrade wheel + + - name: Install project and test dependencies + run: | + pip install ".[test]" + - name: Check types with mypy - # With new versions of pypi new issues might arise. This is a problem if there is nobody able to fix them, - # so we have to ignore errors until that changes. - continue-on-error: true run: | - set -x mypy -p git + # With new versions of mypy new issues might arise. This is a problem if there is nobody able to fix them, + # so we have to ignore errors until that changes. + continue-on-error: true - name: Test with pytest run: | - set -x pytest continue-on-error: false - name: Documentation run: | - set -x pip install -r doc/requirements.txt make -C doc html diff --git a/Makefile b/Makefile index 2af8de084..f2cbf826a 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,8 @@ release: clean make force_release force_release: clean - git push --tags origin main - python3 setup.py sdist bdist_wheel + # IF we're in a virtual environment, add build tools + test -z "$$VIRTUAL_ENV" || pip install -U build twine + python3 -m build --sdist --wheel twine upload dist/* + git push --tags origin main diff --git a/README.md b/README.md index 94fcc76d9..ca470a851 100644 --- a/README.md +++ b/README.md @@ -49,30 +49,51 @@ The installer takes care of installing them for you. ### INSTALL -If you have downloaded the source code: +GitPython and its required package dependencies can be installed in any of the following ways, all of which should typically be done in a [virtual environment](https://docs.python.org/3/tutorial/venv.html). -```bash -python setup.py install -``` +#### From PyPI -or if you want to obtain a copy from the Pypi repository: +To obtain and install a copy [from PyPI](https://pypi.org/project/GitPython/), run: ```bash pip install GitPython ``` -Both commands will install the required package dependencies. +(A distribution package can also be downloaded for manual installation at [the PyPI page](https://pypi.org/project/GitPython/).) + +#### From downloaded source code + +If you have downloaded the source code, run this from inside the unpacked `GitPython` directory: + +```bash +pip install . +``` -A distribution package can be obtained for manual installation at: . +#### By cloning the source code repository -If you like to clone from source, you can do it like so: +To clone the [the GitHub repository](https://github.com/gitpython-developers/GitPython) from source to work on the code, you can do it like so: ```bash git clone https://github.com/gitpython-developers/GitPython -git submodule update --init --recursive +cd GitPython +git fetch --tags ./init-tests-after-clone.sh ``` +If you are cloning [your own fork](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/working-with-forks/about-forks), then replace the above `git clone` command with one that gives the URL of your fork. Or use this [`gh`](https://cli.github.com/) command (assuming you have `gh` and your fork is called `GitPython`): + +```bash +gh repo clone GitPython +``` + +Having cloned the repo, create and activate your [virtual environment](https://docs.python.org/3/tutorial/venv.html). Then make an [editable install](https://pip.pypa.io/en/stable/topics/local-project-installs/#editable-installs): + +```bash +pip install -e ".[test]" +``` + +In the less common case that you do not want to install test dependencies, `pip install -e .` can be used instead. + ### Limitations #### Leakage of System Resources @@ -101,20 +122,49 @@ On _Windows_, make sure you have `git-daemon` in your PATH. For MINGW-git, the ` exists in `Git\mingw64\libexec\git-core\`; CYGWIN has no daemon, but should get along fine with MINGW's. -Ensure testing libraries are installed. -In the root directory, run: `pip install -r test-requirements.txt` +#### Install test dependencies -To lint, run: `pre-commit run --all-files` +Ensure testing libraries are installed. This is taken care of already if you installed with: -To typecheck, run: `mypy -p git` +```bash +pip install -e ".[test]" +``` -To test, run: `pytest` +Otherwise, you can run: -For automatic code formatting run: `black git` +```bash +pip install -r test-requirements.txt +``` + +#### Test commands + +To test, run: + +```bash +pytest +``` + +To lint, run: + +```bash +pre-commit run --all-files +``` + +To typecheck, run: + +```bash +mypy -p git +``` + +For automatic code formatting, run: + +```bash +black git +``` -Configuration for flake8 is in the ./.flake8 file. +Configuration for flake8 is in the `./.flake8` file. -Configurations for mypy, pytest and coverage.py are in ./pyproject.toml. +Configurations for `mypy`, `pytest`, `coverage.py`, and `black` are in `./pyproject.toml`. The same linting and testing will also be performed against different supported python versions upon submitting a pull request (or on each push if you have a fork with a "main" branch and actions enabled). @@ -138,13 +188,15 @@ Please have a look at the [contributions file][contributing]. ### How to make a new release -- Update/verify the **version** in the `VERSION` file -- Update/verify that the `doc/source/changes.rst` changelog file was updated -- Commit everything -- Run `git tag -s ` to tag the version in Git -- Run `make release` +- Update/verify the **version** in the `VERSION` file. +- Update/verify that the `doc/source/changes.rst` changelog file was updated. +- Commit everything. +- Run `git tag -s ` to tag the version in Git. +- _Optionally_ create and activate a [virtual environment](https://packaging.python.org/en/latest/guides/installing-using-pip-and-virtual-environments/#creating-a-virtual-environment) using `venv` or `virtualenv`.\ +(When run in a virtual environment, the next step will automatically take care of installing `build` and `twine` in it.) +- Run `make release`. - Close the milestone mentioned in the _changelog_ and create a new one. _Do not reuse milestones by renaming them_. -- Got to [GitHub Releases](https://github.com/gitpython-developers/GitPython/releases) and publish a new one with the recently pushed tag. Generate the changelog. +- Go to [GitHub Releases](https://github.com/gitpython-developers/GitPython/releases) and publish a new one with the recently pushed tag. Generate the changelog. ### How to verify a release (DEPRECATED) diff --git a/VERSION b/VERSION index d87cdbb81..b402c1a8b 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -3.1.35 +3.1.36 diff --git a/doc/source/changes.rst b/doc/source/changes.rst index 6302176bd..06ec4b72c 100644 --- a/doc/source/changes.rst +++ b/doc/source/changes.rst @@ -2,6 +2,14 @@ Changelog ========= +3.1.36 +====== + +Note that this release should be a no-op, it's mainly for testing the changed release-process. + +See the following for all changes. +https://github.com/gitpython-developers/gitpython/milestone/66?closed=1 + 3.1.35 ====== diff --git a/init-tests-after-clone.sh b/init-tests-after-clone.sh index e852f3cd9..95ced98b7 100755 --- a/init-tests-after-clone.sh +++ b/init-tests-after-clone.sh @@ -1,7 +1,9 @@ -#!/bin/bash -e +#!/usr/bin/env bash + +set -e if [[ -z "$TRAVIS" ]]; then - read -p "This operation will destroy locally modified files. Continue ? [N/y]: " answer + read -rp "This operation will destroy locally modified files. Continue ? [N/y]: " answer if [[ ! $answer =~ [yY] ]]; then exit 2 fi @@ -13,4 +15,4 @@ git reset --hard HEAD~1 git reset --hard HEAD~1 git reset --hard HEAD~1 git reset --hard __testing_point__ -git submodule update --init --recursive \ No newline at end of file +git submodule update --init --recursive diff --git a/pyproject.toml b/pyproject.toml index 32c9d4a26..42bb31eda 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,5 +1,5 @@ [build-system] -requires = ["setuptools", "wheel"] +requires = ["setuptools"] build-backend = "setuptools.build_meta" [tool.pytest.ini_options] diff --git a/requirements-dev.txt b/requirements-dev.txt index 946b4c94f..f6705341c 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -4,7 +4,6 @@ # libraries for additional local testing/linting - to be added to test-requirements.txt when all pass flake8-type-checking;python_version>="3.8" # checks for TYPE_CHECKING only imports -black pytest-icdiff # pytest-profiling diff --git a/setup.py b/setup.py index ebece64eb..bc53bf6c8 100755 --- a/setup.py +++ b/setup.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + from typing import Sequence from setuptools import setup, find_packages from setuptools.command.build_py import build_py as _build_py @@ -6,8 +8,8 @@ import os import sys -with open(os.path.join(os.path.dirname(__file__), "VERSION")) as v: - VERSION = v.readline().strip() +with open(os.path.join(os.path.dirname(__file__), "VERSION")) as ver_file: + VERSION = ver_file.readline().strip() with open("requirements.txt") as reqs_file: requirements = reqs_file.read().splitlines() @@ -47,7 +49,7 @@ def _stamp_version(filename: str) -> None: with open(filename) as f: for line in f: if "__version__ =" in line: - line = line.replace("\"git\"", "'%s'" % VERSION) + line = line.replace('"git"', "'%s'" % VERSION) found = True out.append(line) except OSError: @@ -93,7 +95,7 @@ def build_py_modules(basedir: str, excludes: Sequence = ()) -> Sequence: package_dir={"git": "git"}, python_requires=">=3.7", install_requires=requirements, - tests_require=requirements + test_requirements, + extras_require={"test": test_requirements}, zip_safe=False, long_description=long_description, long_description_content_type="text/markdown", @@ -122,5 +124,6 @@ def build_py_modules(basedir: str, excludes: Sequence = ()) -> Sequence: "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", ], ) diff --git a/test-requirements.txt b/test-requirements.txt index 6c6d57060..62f409824 100644 --- a/test-requirements.txt +++ b/test-requirements.txt @@ -1,15 +1,9 @@ +black +coverage[toml] ddt>=1.1.1, !=1.4.3 mypy - -black - pre-commit - -virtualenv - pytest pytest-cov -coverage[toml] pytest-sugar - -gitdb +virtualenv diff --git a/test/test_installation.py b/test/test_installation.py index c092aef5e..d856ebc94 100644 --- a/test/test_installation.py +++ b/test/test_installation.py @@ -4,6 +4,7 @@ import ast import os import subprocess +from git.compat import is_win from test.lib import TestBase from test.lib.helper import with_rw_directory @@ -12,8 +13,9 @@ class TestInstallation(TestBase): def setUp_venv(self, rw_dir): self.venv = rw_dir subprocess.run(["virtualenv", self.venv], stdout=subprocess.PIPE) - self.python = os.path.join(self.venv, "bin/python3") - self.pip = os.path.join(self.venv, "bin/pip3") + bin_name = "Scripts" if is_win else "bin" + self.python = os.path.join(self.venv, bin_name, "python") + self.pip = os.path.join(self.venv, bin_name, "pip") self.sources = os.path.join(self.venv, "src") self.cwd = os.path.dirname(os.path.dirname(__file__)) os.symlink(self.cwd, self.sources, target_is_directory=True) @@ -22,24 +24,14 @@ def setUp_venv(self, rw_dir): def test_installation(self, rw_dir): self.setUp_venv(rw_dir) result = subprocess.run( - [self.pip, "install", "-r", "requirements.txt"], + [self.pip, "install", "."], stdout=subprocess.PIPE, cwd=self.sources, ) self.assertEqual( 0, result.returncode, - msg=result.stderr or result.stdout or "Can't install requirements", - ) - result = subprocess.run( - [self.python, "setup.py", "install"], - stdout=subprocess.PIPE, - cwd=self.sources, - ) - self.assertEqual( - 0, - result.returncode, - msg=result.stderr or result.stdout or "Can't build - setup.py failed", + msg=result.stderr or result.stdout or "Can't install project", ) result = subprocess.run([self.python, "-c", "import git"], stdout=subprocess.PIPE, cwd=self.sources) self.assertEqual(