Skip to content

Commit

Permalink
Add support of Python 3.13
Browse files Browse the repository at this point in the history
Update pyproject.toml and dependencies
Add tox.ini
Update tests to work with tox parallel testing
  • Loading branch information
yugokato committed Nov 8, 2024
1 parent 3ec740f commit 91850c4
Show file tree
Hide file tree
Showing 8 changed files with 113 additions and 29 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ["3.11", "3.12"]
python-version: ["3.11", "3.12", "3.13"]
steps:
- uses: actions/checkout@v4
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -22,7 +22,7 @@ jobs:
- name: Install dependencies
run: |
python -m pip install --upgrade pip
python -m pip install --force-reinstall -e .[test]
python -m pip install -e .[test]
- name: Run pytest
run: |
pytest -v
pytest tests -v
1 change: 0 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
default_language_version:
python: python3.11
ci:
autofix_prs: false
autoupdate_schedule: quarterly
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
Expand Down
50 changes: 32 additions & 18 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,28 @@
[build-system]
requires = ["setuptools >= 64.0", "setuptools-scm>=8.0"]
build-backend = "setuptools.build_meta"


[project]
name = "openapi-test-client"
version = "1.0"
description = "Generate/update API test clients from any OpenAPI 3.x specifications"
readme = "README.md"
license = {file="LICENSE"}
authors = [
{ name = "Yugo Kato", email = "[email protected]" },
]
requires-python = ">=3.11"
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Topic :: Software Development :: Quality Assurance",
"Topic :: Software Development :: Testing",
]
dependencies = [
"autoflake==2.3.1",
"black==23.12.1",
Expand All @@ -13,33 +34,29 @@ dependencies = [
"pydantic[email]==2.9.2",
"PyYAML==6.0.1",
]
readme = "README.md"
dynamic = ["version"]


[project.optional-dependencies]
dev = ["pre-commit==3.7.1", "ruff==0.7.1"]
dev = ["common-libs[dev]"]
app = [
"common-libs[dev]",
"Quart==0.19.4",
"quart-auth==0.9.0",
"quart-schema[pydantic]==0.19.1",

]
test = [
"common-libs[dev]",
"common-libs[test]",
"openapi-test-client[app]",
"pytest==8.3.2",
"pytest-lazy-fixtures==1.1.1",
"pytest-mock==3.14.0",
"pytest-subtests==0.11.0",
]

[build-system]
requires = ["setuptools >= 61.0", "setuptools-scm>=8.0"]
build-backend = "setuptools.build_meta"

[tool.setuptools.packages.find]
where = ["src"]

[tool.setuptools_scm]
local_scheme = "no-local-version"

[project.scripts]
openapi-client = "openapi_test_client.scripts.generate_client:main"

Expand All @@ -58,12 +75,9 @@ indent-width = 4

[tool.ruff.lint]
select = [
# pycodestyle
"E",
# Pyflakes
"F",
# pyupgrade
"UP",
"E", # pycodestyle
"F", # Pyflakes
"UP", # pyupgrade
]
ignore = ["E731", "E741", "F403"]

Expand Down
14 changes: 13 additions & 1 deletion src/demo_app/main.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import argparse

from demo_app import app

DEFAULT_PORT = 5000


def parse_pargs():
parser = argparse.ArgumentParser()
parser.add_argument("-p", "--port", dest="port", type=int, default=DEFAULT_PORT)
return parser.parse_args()


if __name__ == "__main__":
app.run(debug=True)
args = parse_pargs()
app.run(debug=True, port=args.port)
7 changes: 7 additions & 0 deletions src/openapi_test_client/__init__.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import glob
import os
import sys
from importlib.metadata import PackageNotFoundError, version
from pathlib import Path

from common_libs.logging import get_logger, setup_logging
from common_libs.utils import list_items

try:
__version__ = version("openapi-test-client")
except PackageNotFoundError:
pass


# For internal use only
_PROJECT_ROOT_DIR = Path(__file__).parent.parent.parent.resolve()
_PACKAGE_DIR = Path(__file__).parent.resolve()
Expand Down
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@

import pytest
from common_libs.utils import clean_obj_name
from pytest import Config, Item, TempPathFactory
from pytest import Item, TempPathFactory
from pytest_mock import MockerFixture


def pytest_make_parametrize_id(config: Config, val: Any, argname: str):
return f"{argname}={val}"
def pytest_make_parametrize_id(val: Any, argname: str):
return f"{argname}={repr(val)}"


def pytest_runtest_setup(item: Item):
Expand Down
32 changes: 29 additions & 3 deletions tests/integration/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from _pytest.fixtures import SubRequest
from pytest_mock import MockerFixture

from demo_app.main import DEFAULT_PORT
from openapi_test_client import _CONFIG_DIR, _PACKAGE_DIR, ENV_VAR_PACKAGE_DIR, logger
from openapi_test_client.clients import OpenAPIClient
from openapi_test_client.clients.demo_app import DemoAppAPIClient
Expand All @@ -19,11 +20,20 @@
from tests.integration import helper


@pytest.fixture(scope="session")
def app_port():
if os.environ.get("IS_TOX"):
return int(os.environ["APP_PORT"])
else:
return DEFAULT_PORT


@pytest.fixture(scope="session", autouse=True)
def demo_app_server():
def demo_app_server(app_port):
script_path = _PACKAGE_DIR.parent / "demo_app" / "main.py"
args = ["python", str(script_path), "-p", str(app_port)]
proc = subprocess.Popen(
["python", str(script_path)],
args,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
encoding="utf-8",
Expand All @@ -32,6 +42,15 @@ def demo_app_server():
if proc.poll():
logger.error(proc.stderr.read())
assert not proc.poll(), proc.stdout.read()

if os.environ.get("IS_TOX"):
# For tox parallel testing, modify the original URL config for demo_app to match with the actual app port
url_cfg = json.loads((_CONFIG_DIR / "urls.json").read_text())
url = url_cfg["dev"]["demo_app"]
if not url.endswith(f":{app_port}"):
url_cfg["dev"]["demo_app"] = url.replace(f":{DEFAULT_PORT}", f":{app_port}")
(_CONFIG_DIR / "urls.json").write_text(json.dumps(url_cfg))

yield
proc.terminate()
stdout, stderr = proc.communicate()
Expand Down Expand Up @@ -76,7 +95,14 @@ def petstore_openapi_spec_url() -> str:
return url


@pytest.fixture(params=[False, True])
@pytest.fixture(
params=[
pytest.param(
False, marks=pytest.mark.skipif(bool(os.environ.get("IS_TOX")), reason="Not supported in tox env")
),
True,
]
)
def external_dir(request: SubRequest, random_app_name: str) -> Path | None:
temp_dir_: Path | None = None
if request.param:
Expand Down
26 changes: 26 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[tox]
env_list = py{311,312,313}

[testenv]
set_env =
IS_TOX = true
APP_PORT = 5000
parallel_show_output = true
deps = .[test]
commands = pytest tests -v -x

# Use a different app port per env for parallel testing
[testenv:py311]
set_env =
IS_TOX = true
APP_PORT = 5001

[testenv:py312]
set_env =
IS_TOX = true
APP_PORT = 5002

[testenv:py313]
set_env =
IS_TOX = true
APP_PORT = 5003

0 comments on commit 91850c4

Please sign in to comment.