From 7f38693992ee82a43ed50b1faca6a2248a687508 Mon Sep 17 00:00:00 2001 From: Dane Hillard Date: Wed, 9 Oct 2024 17:27:50 -0400 Subject: [PATCH 1/2] Convert setup.cfg to pyproject.toml --- pyproject.toml | 133 +++++++++++++++++++++++++++++++++++++++++++++++++ setup.cfg | 124 --------------------------------------------- setup.py | 3 -- 3 files changed, 133 insertions(+), 127 deletions(-) delete mode 100644 setup.cfg delete mode 100644 setup.py diff --git a/pyproject.toml b/pyproject.toml index 3a0154a..9b446a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,9 +2,142 @@ requires = ["setuptools", "wheel"] build-backend = "setuptools.build_meta" +[project] +name = "apiron" +version = "8.0.0" +description = "apiron helps you cook a tasty client for RESTful APIs. Just don't wash it with SOAP." +authors = [ + { name = "Ithaka Harbors, Inc.", email = "opensource@ithaka.org" }, +] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Software Development :: Libraries :: Python Modules", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3 :: Only", + "License :: OSI Approved :: MIT License", +] +license = { file = "LICENSE" } +dynamic = ["readme"] +dependencies = [ + "requests>=2.11.1", + "urllib3>=1.26.13", +] + +[project.optional-dependencies] +docs = [ + "sphinx>=7.2.2", + "sphinx-autobuild>=2021.3.14", +] + +[project.urls] +Repository = "https://github.com/ithaka/apiron" +Changelog = "https://github.com/ithaka/apiron/blob/main/CHANGELOG.md" +Documentation = "https://apiron.readthedocs.io" +Issues = "https://github.com/ithaka/apiron/issues" + +[tool.setuptools.dynamic] +readme = { file = "README.md", content-type = "text/markdown" } + +[tool.setuptools.packages.find] +where = ["src"] +exclude = ["tests*"] + +###################### +# Tool configuration # +###################### + [tool.black] line-length = 120 target-version = ['py39', 'py310', 'py311', 'py312', 'py313'] [tool.isort] profile = "black" + +[tool.mypy] +python_version = "3.9" +warn_unused_configs = true +show_error_context = true +pretty = true +namespace_packages = true +check_untyped_defs = true + +[tool.coverage.run] +branch = true +source = ["apiron"] +omit = [ + "tests/*", +] + +[tool.coverage.report] +precision = 2 +show_missing = true +skip_covered = true + +[tool.coverage.paths] +source = [ + "src", + ".tox/**/site-packages", +] + +[tool.pytest.ini_options] +testpaths = ["tests"] +addopts = ["-ra", "--strict-markers", "--cov"] +xfail_strict = true + +[tool.tox] +envlist = ["py39", "py310", "py311", "py312", "py313"] +isolated_build = true + +[tool.tox.env_run_base] +package = "wheel" +wheel_build_env = ".pkg" +deps = [ + "pytest>=7.0.0", + "pytest-cov>=4.1.0", + "pytest-randomly>=3.15.0", +] +commands = [ + ["pytest", { replace = "posargs", default = [], extend = true }], +] + +[tool.tox.env.docs] +extras = [ + "docs", +] +commands = [ + ["sphinx-build", "-b", "html", "docs", "{envtmpdir}/docs"] +] + +[tool.tox.env.lint] +skip_install = true +deps = [ + "black", + "isort", + "ruff", +] +commands = [ + ["ruff", "check", { replace = "posargs", default = ["src", "tests"], extend = true }], + ["black", { replace = "posargs", default = ["--check", "--diff", "src", "tests"], extend = true }], + ["isort", { replace = "posargs", default = ["--check", "--diff", "src", "tests"], extend = true }], +] + +[tool.tox.env.typecheck] +deps = [ + { replace = "ref", of = ["tool", "tox", "env_run_base", "deps"], extend = true }, + "mypy", + "typing_extensions", + "types-requests", + "types-urllib3", +] +commands = [ + ["mypy", { replace = "posargs", default = ["src", "tests"], extend = true }], +] +passenv = ["TERM"] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 5c31117..0000000 --- a/setup.cfg +++ /dev/null @@ -1,124 +0,0 @@ -[metadata] -name = apiron -version = 8.0.0 -description = apiron helps you cook a tasty client for RESTful APIs. Just don't wash it with SOAP. -author = Ithaka Harbors, Inc. -author_email = opensource@ithaka.org -url = https://github.com/ithaka/apiron -license = MIT -license_files = LICENSE -long_description = file: README.md -long_description_content_type = text/markdown -project_urls = - Documentation=https://apiron.readthedocs.io - Source=https://github.com/ithaka/apiron - Tracker=https://github.com/ithaka/apiron/issues -classifiers = - Development Status :: 5 - Production/Stable - Intended Audience :: Developers - Topic :: Internet :: WWW/HTTP - Topic :: Software Development :: Libraries :: Python Modules - Programming Language :: Python - Programming Language :: Python :: 3.9 - Programming Language :: Python :: 3.10 - Programming Language :: Python :: 3.11 - Programming Language :: Python :: 3.12 - Programming Language :: Python :: 3.13 - Programming Language :: Python :: 3 - Programming Language :: Python :: 3 :: Only - License :: OSI Approved :: MIT License - -[options] -package_dir = =src -packages = find: -include_package_data = True -install_requires = - requests>=2.11.1 - urllib3>=1.26.13 - -[options.packages.find] -where = src -exclude = - tests* - -[options.extras_require] -docs = - sphinx>=7.2.2 - sphinx-autobuild>=2021.3.14 - -###################### -# Tool configuration # -###################### - -[mypy] -python_version = 3.9 -warn_unused_configs = True -show_error_context = True -pretty = True -namespace_packages = True -check_untyped_defs = True - -[coverage:run] -branch = True -source = apiron -omit = - tests/* - setup.py - -[coverage:report] -precision = 2 -show_missing = True -skip_covered = True - -[coverage:paths] -source = - src - .tox/**/site-packages - -[tool:pytest] -testpaths = tests -addopts = -ra --strict-markers --cov -xfail_strict = True - -[tox:tox] -envlist = py39,py310,py311,py312,py313 -isolated_build = True - -[testenv] -package = wheel -wheel_build_env = .pkg -deps = - pytest>=7.0.0 - pytest-cov>=4.1.0 - pytest-randomly>=3.15.0 -commands = - pytest {posargs} - -[testenv:docs] -extras = - docs -commands = - sphinx-build -b html docs {envtmpdir}/docs - -[testenv:lint] -skip_install = True -deps = - black - isort - ruff -commands = - ruff check {posargs:src tests} - black {posargs:--check --diff src tests} - isort {posargs:--check --diff src tests} - -[testenv:typecheck] -deps = - {[testenv]deps} - mypy - typing_extensions - types-requests - types-urllib3 -commands = - mypy {posargs:src tests} -passenv = - TERM diff --git a/setup.py b/setup.py deleted file mode 100644 index 6068493..0000000 --- a/setup.py +++ /dev/null @@ -1,3 +0,0 @@ -from setuptools import setup - -setup() From d5baeab70709051fa398ede3d958cd810b480e3b Mon Sep 17 00:00:00 2001 From: Dane Hillard Date: Wed, 9 Oct 2024 17:42:19 -0400 Subject: [PATCH 2/2] Add network hobbling during testing and fix test --- tests/conftest.py | 15 +++++++++++++++ tests/test_endpoint.py | 5 ++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 0000000..a0ef4b2 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,15 @@ +import pytest +import requests + + +@pytest.fixture(autouse=True) +def hobble_network(monkeypatch, request): + """Hobble all network calls made through the requests library""" + + if "no_hobble_network" in request.keywords: + return + + def hobbled_send(session, request_object, **kwargs): + raise RuntimeError(f"requests hobbled for testing: tried calling {request_object.url}") + + monkeypatch.setattr(requests.Session, "send", hobbled_send) diff --git a/tests/test_endpoint.py b/tests/test_endpoint.py index f5ec476..d944c3b 100644 --- a/tests/test_endpoint.py +++ b/tests/test_endpoint.py @@ -26,7 +26,10 @@ def stub_response(**kwargs): class TestEndpoint: - def test_call(self, service): + @mock.patch("requests.Session", autospec=True) + def test_call(self, MockSession, service): + mock_session = MockSession() + mock_session.proxies = {} service.foo = apiron.Endpoint() service.foo()