diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml index 0c0032bb..a766a5a6 100644 --- a/.github/workflows/build-release.yml +++ b/.github/workflows/build-release.yml @@ -3,17 +3,6 @@ on: push: pull_request: jobs: - lint: - name: lint - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3.1.0 - - uses: actions/setup-python@v4.3.0 - with: - python-version: '3.11' - - run: python -m pip install --upgrade pip wheel - - run: pip install tox - - run: tox -elint tests: name: ${{ matrix.name }} runs-on: ubuntu-latest @@ -21,29 +10,69 @@ jobs: fail-fast: false matrix: include: - - {name: '3.8', python: '3.8', tox: py38} - - {name: '3.12', python: '3.12', tox: py312} + - { name: '3.8', python: '3.8', tox: py38 } + - { name: '3.12', python: '3.12', tox: py312 } steps: - - uses: actions/checkout@v3.1.0 - - uses: actions/setup-python@v4.3.0 + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 with: python-version: ${{ matrix.python }} + allow-prereleases: true - name: Run test run: | - python -m pip install --upgrade pip wheel - pip install tox - tox -e${{ matrix.tox }} + python -m pip install tox + python -m tox -e ${{ matrix.tox }} - name: Upload coverage uses: codecov/codecov-action@v3 - release: - needs: [lint, tests] - name: PyPI release + build: + name: Build package + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - name: Install pypa/build + run: python -m pip install build + - name: Build a binary wheel and a source tarball + run: python -m build + - name: Install twine + run: python -m pip install twine + - name: Check build + run: python -m twine check --strict dist/* + - name: Store the distribution packages + uses: actions/upload-artifact@v4 + with: + name: python-package-distributions + path: dist/ + # this duplicates pre-commit.ci, so only run it on tags + # it guarantees that linting is passing prior to a release + lint-pre-release: if: startsWith(github.ref, 'refs/tags') runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3.1.0 - - uses: actions/setup-python@v4.3.0 - - run: python -m pip install --upgrade pip wheel - - run: pip install twine - - run: python setup.py sdist bdist_wheel - - run: twine upload -u __token__ -p ${{ secrets.PYPI_API_TOKEN }} dist/* + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.11" + - run: python -m pip install tox + - run: python -m tox -e lint + publish-to-pypi: + name: PyPI release + if: startsWith(github.ref, 'refs/tags/') + needs: [build, tests, lint-pre-release] + runs-on: ubuntu-latest + environment: + name: pypi + url: https://pypi.org/p/flask-smorest + permissions: + id-token: write + steps: + - name: Download all the dists + uses: actions/download-artifact@v4 + with: + name: python-package-distributions + path: dist/ + - name: Publish distribution to PyPI + # TODO: Configure GH permissions, remove TOKEN + uses: pypa/gh-action-pypi-publish@release/v1 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index d55b7d38..478a7f4c 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,21 +1,16 @@ repos: -- repo: https://github.com/asottile/pyupgrade - rev: v3.15.1 +- repo: https://github.com/astral-sh/ruff-pre-commit + rev: v0.2.2 hooks: - - id: pyupgrade - args: [--py38-plus] -- repo: https://github.com/psf/black - rev: 24.2.0 + - id: ruff + - id: ruff-format +- repo: https://github.com/python-jsonschema/check-jsonschema + rev: 0.28.0 hooks: - - id: black - language_version: python3 -- repo: https://github.com/pycqa/flake8 - rev: 7.0.0 - hooks: - - id: flake8 - additional_dependencies: [flake8-bugbear==24.2.6] + - id: check-github-workflows + - id: check-readthedocs - repo: https://github.com/asottile/blacken-docs rev: 1.16.0 hooks: - id: blacken-docs - additional_dependencies: [black==22.3.0] + additional_dependencies: [black==23.12.1] diff --git a/README.rst b/README.rst index 1ab625c5..b8fd6786 100644 --- a/README.rst +++ b/README.rst @@ -30,6 +30,10 @@ flask-smorest :target: https://codecov.io/gh/marshmallow-code/flask-smorest :alt: Code coverage +.. image:: https://results.pre-commit.ci/badge/github/marshmallow-code/flask-smorest/dev.svg + :target: https://results.pre-commit.ci/latest/github/marshmallow-code/flask-smorest/dev + :alt: pre-commit.ci status + .. image:: https://readthedocs.org/projects/flask-smorest/badge/ :target: http://flask-smorest.readthedocs.io/ :alt: Documentation diff --git a/docs/openapi.rst b/docs/openapi.rst index df3ff962..54213a8a 100644 --- a/docs/openapi.rst +++ b/docs/openapi.rst @@ -214,6 +214,7 @@ The :meth:`Api.register_converter` allows to register a converter in the # Register MongoDB's ObjectId converter in Flask application app.url_map.converters["objectid"] = ObjectIdConverter + # Define custom converter to schema function def objectidconverter2paramschema(converter): return {"type": "string", "format": "ObjectID"} diff --git a/flask_smorest/arguments.py b/flask_smorest/arguments.py index b6cdaeed..21b83a42 100644 --- a/flask_smorest/arguments.py +++ b/flask_smorest/arguments.py @@ -25,7 +25,7 @@ def arguments( description=None, example=None, examples=None, - **kwargs + **kwargs, ): """Decorator specifying the schema used to deserialize parameters diff --git a/flask_smorest/etag.py b/flask_smorest/etag.py index 5fcef904..9ef3f832 100644 --- a/flask_smorest/etag.py +++ b/flask_smorest/etag.py @@ -244,7 +244,7 @@ def _prepare_etag_doc(self, doc, doc_info, *, api, spec, method, **kwargs): for success_status_code in success_status_codes: doc["responses"][success_status_code].setdefault("headers", {})[ "ETag" - ] = (ETAG_HEADER if spec.openapi_version.major < 3 else "ETAG") + ] = ETAG_HEADER if spec.openapi_version.major < 3 else "ETAG" if responses: doc = deepupdate(doc, {"responses": responses}) diff --git a/setup.py b/setup.py deleted file mode 100644 index 17483257..00000000 --- a/setup.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python3 - -from setuptools import setup, find_packages - -EXTRAS_REQUIRE = { - "tests": [ - "pytest==8.0.2", - "pytest-cov==4.1.0", - "coverage==7.4.3", - "werkzeug==3.0.1", - "flask==3.0.2", - "marshmallow==3.20.2", - "webargs==8.4.0", - "apispec==6.4.0", - "PyYAML==6.0.1", - ], - "lint": [ - "pre-commit==3.6.2", - ], -} -EXTRAS_REQUIRE["dev"] = EXTRAS_REQUIRE["tests"] + EXTRAS_REQUIRE["lint"] - - -# Get the long description from the README file -with open("README.rst", encoding="utf-8") as f: - long_description = f.read() - -setup( - name="flask-smorest", - version="0.44.0", - description="Flask/Marshmallow-based REST API framework", - long_description=long_description, - url="https://github.com/marshmallow-code/flask-smorest", - author="Jérôme Lafréchoux", - author_email="jerome@jolimont.fr", - license="MIT", - # See https://pypi.python.org/pypi?%3Aaction=list_classifiers - classifiers=[ - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "Topic :: Internet :: WWW/HTTP", - "Environment :: Web Environment", - "Framework :: Flask", - "License :: OSI Approved :: MIT License", - "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", - ], - keywords=[ - "REST", - "openapi", - "swagger", - "flask", - "marshmallow", - "apispec", - "webargs", - ], - packages=find_packages(exclude=["tests*"]), - include_package_data=True, - package_data={ - "": ["spec/templates/*"], - }, - python_requires=">=3.8", - install_requires=[ - "werkzeug>=3.0.1,<4", - "flask>=3.0.2,<4", - "marshmallow>=3.18.0,<4", - "webargs>=8.0.0,<9", - "apispec[marshmallow]>=6.0.0,<7", - ], - extras_require=EXTRAS_REQUIRE, -) diff --git a/tests/test_response.py b/tests/test_response.py index a7dd1b30..85047c15 100644 --- a/tests/test_response.py +++ b/tests/test_response.py @@ -172,8 +172,9 @@ def func(): else: assert "produces" not in get assert get["responses"]["200"]["content"] == { - content_type - or "application/json": {"schema": build_ref(api.spec, "schema", "Doc")} + content_type or "application/json": { + "schema": build_ref(api.spec, "schema", "Doc") + } } @pytest.mark.parametrize("openapi_version", ["2.0", "3.0.2"])