From 63a8247bd867070fb696632081f5e46889a6f9b4 Mon Sep 17 00:00:00 2001 From: Stephen Finucane Date: Mon, 9 May 2022 11:12:49 +0100 Subject: [PATCH] Remove use of distutils Distutils is going away in Python 3.12. Running tests on a project that uses openapi-core with Python 3.10 yields the following warning: .../openapi_core/unmarshalling/schemas/util.py:5: DeprecationWarning: The distutils package is deprecated and slated for removal in Python 3.12. Use setuptools or check PEP 632 for potential alternatives from distutils.util import strtobool The offending API is really simple. Just vendor the code. Signed-off-by: Stephen Finucane --- openapi_core/casting/schemas/factories.py | 2 +- openapi_core/casting/schemas/util.py | 9 -------- .../unmarshalling/schemas/unmarshallers.py | 2 +- openapi_core/unmarshalling/schemas/util.py | 8 ------- openapi_core/util.py | 14 ++++++++++++ .../{test_util.py => test_templating_util.py} | 0 tests/unit/test_util.py | 22 +++++++++++++++++++ 7 files changed, 38 insertions(+), 19 deletions(-) delete mode 100644 openapi_core/casting/schemas/util.py create mode 100644 openapi_core/util.py rename tests/unit/templating/{test_util.py => test_templating_util.py} (100%) create mode 100644 tests/unit/test_util.py diff --git a/openapi_core/casting/schemas/factories.py b/openapi_core/casting/schemas/factories.py index 7240fcc5..3c9b0f21 100644 --- a/openapi_core/casting/schemas/factories.py +++ b/openapi_core/casting/schemas/factories.py @@ -1,7 +1,7 @@ from openapi_core.casting.schemas.casters import ArrayCaster from openapi_core.casting.schemas.casters import CallableSchemaCaster from openapi_core.casting.schemas.casters import DummyCaster -from openapi_core.casting.schemas.util import forcebool +from openapi_core.util import forcebool class SchemaCastersFactory: diff --git a/openapi_core/casting/schemas/util.py b/openapi_core/casting/schemas/util.py deleted file mode 100644 index 16a1d42c..00000000 --- a/openapi_core/casting/schemas/util.py +++ /dev/null @@ -1,9 +0,0 @@ -"""OpenAPI core casting schemas util module""" -from distutils.util import strtobool - - -def forcebool(val): - if isinstance(val, str): - val = strtobool(val) - - return bool(val) diff --git a/openapi_core/unmarshalling/schemas/unmarshallers.py b/openapi_core/unmarshalling/schemas/unmarshallers.py index 64a473cf..bec882a4 100644 --- a/openapi_core/unmarshalling/schemas/unmarshallers.py +++ b/openapi_core/unmarshalling/schemas/unmarshallers.py @@ -21,11 +21,11 @@ from openapi_core.unmarshalling.schemas.exceptions import UnmarshalError from openapi_core.unmarshalling.schemas.exceptions import ValidateError from openapi_core.unmarshalling.schemas.formatters import Formatter -from openapi_core.unmarshalling.schemas.util import forcebool from openapi_core.unmarshalling.schemas.util import format_byte from openapi_core.unmarshalling.schemas.util import format_date from openapi_core.unmarshalling.schemas.util import format_number from openapi_core.unmarshalling.schemas.util import format_uuid +from openapi_core.util import forcebool log = logging.getLogger(__name__) diff --git a/openapi_core/unmarshalling/schemas/util.py b/openapi_core/unmarshalling/schemas/util.py index 58ce16d9..74b61e38 100644 --- a/openapi_core/unmarshalling/schemas/util.py +++ b/openapi_core/unmarshalling/schemas/util.py @@ -2,20 +2,12 @@ import datetime from base64 import b64decode from copy import copy -from distutils.util import strtobool from functools import lru_cache from uuid import UUID from openapi_schema_validator import oas30_format_checker -def forcebool(val): - if isinstance(val, str): - val = strtobool(val) - - return bool(val) - - def format_date(value): return datetime.datetime.strptime(value, "%Y-%m-%d").date() diff --git a/openapi_core/util.py b/openapi_core/util.py new file mode 100644 index 00000000..367736c6 --- /dev/null +++ b/openapi_core/util.py @@ -0,0 +1,14 @@ +"""OpenAPI core util module""" + + +def forcebool(val): + if isinstance(val, str): + val = val.lower() + if val in ("y", "yes", "t", "true", "on", "1"): + return True + elif val in ("n", "no", "f", "false", "off", "0"): + return False + else: + raise ValueError(f"invalid truth value {val!r}") + + return bool(val) diff --git a/tests/unit/templating/test_util.py b/tests/unit/templating/test_templating_util.py similarity index 100% rename from tests/unit/templating/test_util.py rename to tests/unit/templating/test_templating_util.py diff --git a/tests/unit/test_util.py b/tests/unit/test_util.py new file mode 100644 index 00000000..a262d0c4 --- /dev/null +++ b/tests/unit/test_util.py @@ -0,0 +1,22 @@ +import pytest + +from openapi_core.util import forcebool + + +class TestForcebool: + @pytest.mark.parametrize("val", ["y", "yes", "t", "true", "on", "1", True]) + def test_true(self, val): + result = forcebool(val) + assert result is True + + @pytest.mark.parametrize( + "val", ["n", "no", "f", "false", "off", "0", False] + ) + def test_false(self, val): + result = forcebool(val) + assert result is False + + @pytest.mark.parametrize("val", ["random", "idontknow", ""]) + def test_value_error(self, val): + with pytest.raises(ValueError): + forcebool(val)