Repository: 4Catalyzer/flask-annex (language: python)

Issue:
Chore/migrate GitHub actions tox GitHub fixes
@c0state This should fix the issue where the tests were skipping.  There was some missing configuration in the usage of `tox-gh-actions`.  See: https://github.com/ymyzk/tox-gh-actions?tab=readme-ov-file#advanced-examples
The successful action: https://github.com/4Catalyzer/flask-annex/actions/runs/10729836844. (it's not running again since this PR isn't against master)


Discussion / hints:

Fix patch:
diff --git a/.flake8 b/.flake8
index 043e7a0..c2399d7 100644
--- a/.flake8
+++ b/.flake8
@@ -1,5 +1,7 @@
 [flake8]
-ignore = E,W503  # Let Black handle all the formatting.
+ignore =
+  # Let Black handle all the formatting.
+  E,W503
 exclude =
   tests/snapshots,
   .svn,CVS,.bzr,.hg,.git,__pycache__,.tox,.eggs,*.egg
diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
new file mode 100644
index 0000000..46cadf2
--- /dev/null
+++ b/.github/workflows/main.yml
@@ -0,0 +1,83 @@
+name: CI
+
+on:
+  push:
+    branches: ["master"]
+    tags:
+      - "v[0-9].[0-9].[0-9]*"
+  pull_request:
+    branches: ["master"]
+  workflow_dispatch:
+
+env:
+  COVERAGE_PYTHON_VERSION: "3.12"
+
+jobs:
+  tests:
+    name: "Python ${{ matrix.python-version }}"
+    runs-on: "ubuntu-latest"
+
+    strategy:
+      matrix:
+        python-version: ["3.10", "3.11", "3.12"]
+
+    steps:
+      - uses: "actions/checkout@v4"
+      - uses: "actions/setup-python@v5"
+        with:
+          python-version: "${{ matrix.python-version }}"
+      - name: "Install dependencies"
+        run: |
+          set -xe
+          python -VV
+          python -m site
+          python -m pip install --upgrade pip setuptools wheel
+          python -m pip install --upgrade coverage[toml] tox tox-gh-actions
+      - name: "Run tox targets for ${{ matrix.python-version }}"
+        run: tox
+
+      # use a modern Python version for code coverage
+      - uses: "actions/setup-python@v5"
+        with:
+          python-version: ${{ env.COVERAGE_PYTHON_VERSION }}
+
+      - name: "Generate code coverage"
+        if: "${{ env.COVERAGE_PYTHON_VERSION == matrix.python-version }}"
+        run: |
+          set -xe
+          python -m coverage xml
+      - name: "Upload coverage"
+        if: "${{ env.COVERAGE_PYTHON_VERSION == matrix.python-version }}"
+        env:
+          CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
+        uses: "codecov/codecov-action@v4"
+        with:
+          fail_ci_if_error: true
+
+  package:
+    name: "Build, verify, and publish package"
+    runs-on: "ubuntu-latest"
+
+    steps:
+      - uses: "actions/checkout@v4"
+      - uses: "actions/setup-python@v5"
+        with:
+          python-version: ${{ env.COVERAGE_PYTHON_VERSION }}
+      - name: "Install build, check-wheel-content, and twine"
+        run: "python -m pip install build twine check-wheel-contents"
+      - name: "Build package"
+        run: "python -m build --sdist --wheel ."
+      - name: "List result"
+        run: "ls -l dist"
+      - name: "Check wheel contents"
+        run: "check-wheel-contents dist/*.whl"
+      - name: "Check long_description"
+        run: "python -m twine check dist/*"
+      # Automatically publish to PyPI when tags are pushed
+      # Added to https://github.com/python-attrs/attrs/blob/main/.github/workflows/main.yml
+      - name: Publish distribution to PyPI
+        if: github.event_name == 'push' && startsWith(github.ref, 'refs/tags')
+        uses: pypa/gh-action-pypi-publish@release/v1
+        with:
+          user: __token__
+          password: ${{ secrets.PYPI_API_TOKEN }}
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 3f9a8cf..29aea20 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,10 +1,11 @@
 repos:
   - repo: https://github.com/asottile/pyupgrade
-    rev: v2.31.1
+    rev: v3.17.0
     hooks:
       - id: pyupgrade
-        args: [--py37-plus]
+        args: [--py310-plus]
   - repo: https://github.com/4Catalyzer/fourmat
-    rev: v0.11.1
+    rev: v1.0.0
     hooks:
       - id: fourmat
+        additional_dependencies: ['setuptools>=74']
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 5d6c79f..0000000
--- a/.travis.yml
+++ /dev/null
@@ -1,31 +0,0 @@
-language: python
-python:
-  - "3.10"
-  - "3.9"
-  - "3.8"
-  - "3.7"
-
-env:
-  - TOXENV=py-s3
-
-jobs:
-  include:
-    - env: TOXENV=lint
-    - env: TOXENV=py-base
-
-cache: pip
-
-before_install:
-  - pip install -U pip
-install:
-  - pip install -U codecov tox
-
-script:
-  - python setup.py test
-
-after_success:
-  - codecov
-
-branches:
-  only:
-    - master
diff --git a/README.md b/README.md
index d836ea4..04c1f79 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-# Flask-Annex [![Travis][build-badge]][build] [![PyPI][pypi-badge]][pypi]
+# Flask-Annex [![GitHub Actions][build-badge]][build] [![PyPI][pypi-badge]][pypi]
 
 Efficient integration of external storage services for [Flask](http://flask.pocoo.org/).
 
@@ -6,8 +6,8 @@ Run `pip install -e .[s3,tests]` to install for development and with `S3` suppor
 
 [![Codecov][codecov-badge]][codecov]
 
-[build-badge]: https://img.shields.io/travis/4Catalyzer/flask-annex/master.svg
-[build]: https://travis-ci.org/4Catalyzer/flask-annex
+[build-badge]: https://github.com/4Catalyzer/flask-annex/actions/workflows/main.yml/badge.svg
+[build]: https://github.com/4Catalyzer/flask-annex/actions
 [pypi-badge]: https://img.shields.io/pypi/v/Flask-Annex.svg
 [pypi]: https://pypi.python.org/pypi/Flask-Annex
 [codecov-badge]: https://img.shields.io/codecov/c/github/4Catalyzer/flask-annex/master.svg
diff --git a/pyproject.toml b/pyproject.toml
index 3c0a461..7c9849b 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,3 +1,3 @@
 [tool.black]
 line-length = 79
-target-version = ['py37', 'py38', 'py39', 'py310']
+target-version = ['py310', 'py311', 'py312']
diff --git a/setup.py b/setup.py
index d0ba76a..e95e551 100644
--- a/setup.py
+++ b/setup.py
@@ -30,9 +30,8 @@ def run(self):
     author="Jimmy Jia",
     author_email="tesrin@gmail.com",
     license="MIT",
-    python_requires=">=3.7",
+    python_requires=">=3.10",
     classifiers=[
-        "Development Status :: 2 - Pre-Alpha",
         "Framework :: Flask",
         "Environment :: Web Environment",
         "Intended Audience :: Developers",
@@ -40,16 +39,17 @@ def run(self):
         "Operating System :: OS Independent",
         "Programming Language :: Python",
         "Programming Language :: Python :: 3",
-        "Programming Language :: Python :: 3.7",
-        "Programming Language :: Python :: 3.8",
-        "Programming Language :: Python :: 3.9",
         "Programming Language :: Python :: 3.10",
+        "Programming Language :: Python :: 3.11",
+        "Programming Language :: Python :: 3.12",
         "Programming Language :: Python :: 3 :: Only",
         "Topic :: Internet :: WWW/HTTP :: Dynamic Content",
         "Topic :: Software Development :: Libraries :: Python Modules",
     ],
     keywords="storage s3 flask",
-    packages=("flask_annex",),
+    packages=[
+        "flask_annex",
+    ],
     install_requires=("Flask >= 2.0", "packaging >= 17.0"),
     extras_require={
         "s3": ("boto3 >= 1.4.0",),
diff --git a/tox.ini b/tox.ini
index 949b075..6b31f3e 100644
--- a/tox.ini
+++ b/tox.ini
@@ -1,7 +1,13 @@
 [tox]
 envlist =
     lint
-    py{37,38,39,310}-{base,s3}
+    py{310, 311, 312}-{base,s3}
+
+[gh-actions]
+python =
+    3.10: lint, py310
+    3.11: lint, py311
+    3.12: lint, py312
 
 [testenv]
 usedevelop = True


Test patch:
diff --git a/tests/test_s3.py b/tests/test_s3.py
index be02ede..363ef28 100644
--- a/tests/test_s3.py
+++ b/tests/test_s3.py
@@ -13,16 +13,16 @@
 try:
     import boto3
     import requests
-    from moto import mock_s3
+    from moto import mock_aws
 except ImportError:
     pytestmark = pytest.mark.skipif(True, reason="S3 support not installed")
 
 # -----------------------------------------------------------------------------
 
 
-@pytest.yield_fixture
+@pytest.fixture
 def bucket_name():
-    with mock_s3():
+    with mock_aws():
         bucket = boto3.resource("s3").Bucket("flask-annex")
         bucket.create()
 
@@ -88,7 +88,7 @@ def test_get_upload_info(self, client):
         assert upload_info["url"] == "https://flask-annex.s3.amazonaws.com/"
         assert upload_info["post_data"][0] == ["Content-Type", "text/plain"]
         assert upload_info["post_data"][1] == ["key", "foo/qux.txt"]
-        assert upload_info["post_data"][2] == ["AWSAccessKeyId", "foobar_key"]
+        assert upload_info["post_data"][2] == ["AWSAccessKeyId", "FOOBARKEY"]
         assert upload_info["post_data"][3][0] == "policy"
         assert upload_info["post_data"][4][0] == "signature"