From 9b7c55e9cba043db295f80be4e65fa600af2770e Mon Sep 17 00:00:00 2001 From: Konrad Cempura Date: Sun, 15 Jul 2018 21:00:14 +0200 Subject: [PATCH 1/7] .pytest_cache added to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 93b26b8..89a475d 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ __pycache__/ *.py[cod] *$py.class +.pytest_cache/ # C extensions *.so From 64ac723e54acbbb93fa0fd834249cc8691f250b7 Mon Sep 17 00:00:00 2001 From: Konrad Cempura Date: Sun, 15 Jul 2018 23:06:40 +0200 Subject: [PATCH 2/7] Python 2.7: Declare UTF-8 in files with non-ascii characters --- openapi_core/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openapi_core/__init__.py b/openapi_core/__init__.py index d00e903..1811d2d 100644 --- a/openapi_core/__init__.py +++ b/openapi_core/__init__.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + """OpenAPI core module""" from openapi_core.shortcuts import ( create_spec, validate_parameters, validate_body, validate_data, From 1b9bb11114b92a024a9f91cbd477bd9fcaa1fcc1 Mon Sep 17 00:00:00 2001 From: Konrad Cempura Date: Sun, 15 Jul 2018 23:19:36 +0200 Subject: [PATCH 3/7] Python 2.7: Remove Yarl from requirements --- openapi_core/validation/util.py | 22 +++++++++++++++++++--- requirements.txt | 1 - 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/openapi_core/validation/util.py b/openapi_core/validation/util.py index bbe0811..62a3cb4 100644 --- a/openapi_core/validation/util.py +++ b/openapi_core/validation/util.py @@ -1,5 +1,21 @@ """OpenAPI core validation util module""" -from yarl import URL +try: + from urllib.parse import urlparse + +except ImportError: + from urlparse import urlparse + + +def is_absolute(url): + return url.startswith('//') or '://' in url + + +def path_qs(url): + pr = urlparse(url) + result = pr.path + if pr.query: + result += '?' + pr.query + return result def get_operation_pattern(server_url, request_url_pattern): @@ -7,6 +23,6 @@ def get_operation_pattern(server_url, request_url_pattern): if server_url[-1] == "/": # operations have to start with a slash, so do not remove it server_url = server_url[:-1] - if URL(server_url).is_absolute(): + if is_absolute(server_url): return request_url_pattern.replace(server_url, "", 1) - return URL(request_url_pattern).path_qs.replace(server_url, "", 1) + return path_qs(request_url_pattern).replace(server_url, "", 1) diff --git a/requirements.txt b/requirements.txt index 7b2dc82..b5a3675 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,2 @@ openapi-spec-validator six -yarl<1.2.0 From 88efa69cfd5171f2379de257e6885108d60e5ce5 Mon Sep 17 00:00:00 2001 From: Konrad Cempura Date: Sun, 15 Jul 2018 23:21:15 +0200 Subject: [PATCH 4/7] Python 2.7: Check instance on string_types from six instead of str --- openapi_core/schema/schemas/util.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openapi_core/schema/schemas/util.py b/openapi_core/schema/schemas/util.py index cf2c917..4a87f46 100644 --- a/openapi_core/schema/schemas/util.py +++ b/openapi_core/schema/schemas/util.py @@ -1,9 +1,10 @@ """OpenAPI core schemas util module""" from distutils.util import strtobool +from six import string_types def forcebool(val): - if isinstance(val, str): + if isinstance(val, string_types): val = strtobool(val) return bool(val) From b8c03d90f4df6a47a87ff0d6a2e3241029c9cd8a Mon Sep 17 00:00:00 2001 From: Konrad Cempura Date: Sun, 15 Jul 2018 23:22:44 +0200 Subject: [PATCH 5/7] Python 2.7: Copy list using slice --- openapi_core/schema/schemas/models.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openapi_core/schema/schemas/models.py b/openapi_core/schema/schemas/models.py index 4e37cde..b783cae 100644 --- a/openapi_core/schema/schemas/models.py +++ b/openapi_core/schema/schemas/models.py @@ -81,7 +81,7 @@ class Schema(object): ) def get_all_required_properties_names(self): - required = self.required.copy() + required = self.required[:] for subschema in self.all_of: subschema_req = subschema.get_all_required_properties() From e3dfee56cd9647d49317abc17030e371ee2f7a43 Mon Sep 17 00:00:00 2001 From: Konrad Cempura Date: Sun, 15 Jul 2018 23:26:20 +0200 Subject: [PATCH 6/7] Python 2.7: Requirements for older python and patches for imports --- openapi_core/__init__.py | 3 +++ openapi_core/_python27_patch.py | 14 ++++++++++++++ requirements_2.7.txt | 5 +++++ setup.py | 5 ++++- 4 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 openapi_core/_python27_patch.py create mode 100644 requirements_2.7.txt diff --git a/openapi_core/__init__.py b/openapi_core/__init__.py index 1811d2d..e8e7031 100644 --- a/openapi_core/__init__.py +++ b/openapi_core/__init__.py @@ -1,5 +1,8 @@ # -*- coding: utf-8 -*- +"""Python 2.7 backward compatibility""" +import openapi_core._python27_patch + """OpenAPI core module""" from openapi_core.shortcuts import ( create_spec, validate_parameters, validate_body, validate_data, diff --git a/openapi_core/_python27_patch.py b/openapi_core/_python27_patch.py new file mode 100644 index 0000000..81fc3df --- /dev/null +++ b/openapi_core/_python27_patch.py @@ -0,0 +1,14 @@ +import functools +try: + from functools import lru_cache + +except ImportError: + from backports.functools_lru_cache import lru_cache + functools.lru_cache = lru_cache + +try: + from functools import partialmethod + +except ImportError: + from backports.functools_partialmethod import partialmethod + functools.partialmethod = partialmethod diff --git a/requirements_2.7.txt b/requirements_2.7.txt new file mode 100644 index 0000000..624bfea --- /dev/null +++ b/requirements_2.7.txt @@ -0,0 +1,5 @@ +openapi-spec-validator +six +backports.functools-lru-cache +backports.functools-partialmethod +enum34 diff --git a/setup.py b/setup.py index 839ceae..3bb9b26 100644 --- a/setup.py +++ b/setup.py @@ -53,6 +53,8 @@ init_path = os.path.join('openapi_core', '__init__.py') init_py = read_file(init_path) metadata = get_metadata(init_py) +py27 = '_2.7' if sys.version_info < (3,) else '' + setup( name='openapi-core', @@ -69,11 +71,12 @@ setup( "Topic :: Software Development :: Libraries :: Python Modules", "Operating System :: OS Independent", 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Topic :: Software Development :: Libraries', ], - install_requires=read_requirements('requirements.txt'), + install_requires=read_requirements('requirements{}.txt'.format(py27)), tests_require=read_requirements('requirements_dev.txt'), extras_require={ 'flask': ["werkzeug"], From a9d858e940289d471ba84a95e5af29abfcafa5c3 Mon Sep 17 00:00:00 2001 From: p1c2u Date: Sat, 28 Jul 2018 23:51:36 +0100 Subject: [PATCH 7/7] Python2 compatibility module --- .travis.yml | 1 + openapi_core/__init__.py | 4 ---- openapi_core/{_python27_patch.py => compat.py} | 8 +++----- openapi_core/schema/components/factories.py | 3 +-- openapi_core/schema/operations/generators.py | 3 +-- openapi_core/schema/parameters/generators.py | 3 +-- openapi_core/schema/paths/generators.py | 3 +-- .../schema/request_bodies/factories.py | 3 +-- openapi_core/schema/responses/generators.py | 3 +-- openapi_core/schema/schemas/factories.py | 2 +- openapi_core/schema/servers/generators.py | 3 +-- openapi_core/schema/specs/factories.py | 2 +- openapi_core/schema/specs/models.py | 2 +- openapi_core/validation/util.py | 6 +----- requirements_2.7.txt | 1 + setup.py | 11 +++++++---- tests/unit/validation/test_util.py | 18 ++++++++++++++++++ 17 files changed, 41 insertions(+), 35 deletions(-) rename openapi_core/{_python27_patch.py => compat.py} (71%) create mode 100644 tests/unit/validation/test_util.py diff --git a/.travis.yml b/.travis.yml index 260054a..4d45da9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,6 +2,7 @@ language: python sudo: false matrix: include: + - python: 2.7 - python: 3.4 - python: 3.5 - python: 3.6 diff --git a/openapi_core/__init__.py b/openapi_core/__init__.py index e8e7031..90f9d02 100644 --- a/openapi_core/__init__.py +++ b/openapi_core/__init__.py @@ -1,8 +1,4 @@ # -*- coding: utf-8 -*- - -"""Python 2.7 backward compatibility""" -import openapi_core._python27_patch - """OpenAPI core module""" from openapi_core.shortcuts import ( create_spec, validate_parameters, validate_body, validate_data, diff --git a/openapi_core/_python27_patch.py b/openapi_core/compat.py similarity index 71% rename from openapi_core/_python27_patch.py rename to openapi_core/compat.py index 81fc3df..53eeadf 100644 --- a/openapi_core/_python27_patch.py +++ b/openapi_core/compat.py @@ -1,14 +1,12 @@ -import functools +"""OpenAPI core python 2.7 compatibility module""" try: from functools import lru_cache - except ImportError: from backports.functools_lru_cache import lru_cache - functools.lru_cache = lru_cache try: from functools import partialmethod - except ImportError: from backports.functools_partialmethod import partialmethod - functools.partialmethod = partialmethod + +__all__ = ['lru_cache', 'partialmethod'] diff --git a/openapi_core/schema/components/factories.py b/openapi_core/schema/components/factories.py index 8ee7ceb..d784d44 100644 --- a/openapi_core/schema/components/factories.py +++ b/openapi_core/schema/components/factories.py @@ -1,5 +1,4 @@ -from functools import lru_cache - +from openapi_core.compat import lru_cache from openapi_core.schema.components.models import Components from openapi_core.schema.schemas.generators import SchemasGenerator diff --git a/openapi_core/schema/operations/generators.py b/openapi_core/schema/operations/generators.py index 0f225cc..8afeb9b 100644 --- a/openapi_core/schema/operations/generators.py +++ b/openapi_core/schema/operations/generators.py @@ -1,10 +1,9 @@ # -*- coding: utf-8 -*- """OpenAPI core operations models module""" -from functools import lru_cache - from six import iteritems from openapi_spec_validator.validators import PathItemValidator +from openapi_core.compat import lru_cache from openapi_core.schema.operations.models import Operation from openapi_core.schema.parameters.generators import ParametersGenerator from openapi_core.schema.request_bodies.factories import RequestBodyFactory diff --git a/openapi_core/schema/parameters/generators.py b/openapi_core/schema/parameters/generators.py index bc7f0da..0f5d78e 100644 --- a/openapi_core/schema/parameters/generators.py +++ b/openapi_core/schema/parameters/generators.py @@ -1,8 +1,7 @@ """OpenAPI core parameters generators module""" -from functools import lru_cache - from six import iteritems +from openapi_core.compat import lru_cache from openapi_core.schema.parameters.factories import ParameterFactory diff --git a/openapi_core/schema/paths/generators.py b/openapi_core/schema/paths/generators.py index 71c83a2..9289124 100644 --- a/openapi_core/schema/paths/generators.py +++ b/openapi_core/schema/paths/generators.py @@ -1,8 +1,7 @@ """OpenAPI core paths generators module""" -from functools import lru_cache - from six import iteritems +from openapi_core.compat import lru_cache from openapi_core.schema.operations.generators import OperationsGenerator from openapi_core.schema.paths.models import Path diff --git a/openapi_core/schema/request_bodies/factories.py b/openapi_core/schema/request_bodies/factories.py index 63d387e..ba659a3 100644 --- a/openapi_core/schema/request_bodies/factories.py +++ b/openapi_core/schema/request_bodies/factories.py @@ -1,6 +1,5 @@ """OpenAPI core request bodies factories module""" -from functools import lru_cache - +from openapi_core.compat import lru_cache from openapi_core.schema.media_types.generators import MediaTypeGenerator from openapi_core.schema.request_bodies.models import RequestBody diff --git a/openapi_core/schema/responses/generators.py b/openapi_core/schema/responses/generators.py index b6a410f..5e99ab2 100644 --- a/openapi_core/schema/responses/generators.py +++ b/openapi_core/schema/responses/generators.py @@ -1,8 +1,7 @@ """OpenAPI core responses generators module""" -from functools import lru_cache - from six import iteritems +from openapi_core.compat import lru_cache from openapi_core.schema.media_types.generators import MediaTypeGenerator from openapi_core.schema.parameters.generators import ParametersGenerator from openapi_core.schema.responses.models import Response diff --git a/openapi_core/schema/schemas/factories.py b/openapi_core/schema/schemas/factories.py index adad164..4d1f07f 100644 --- a/openapi_core/schema/schemas/factories.py +++ b/openapi_core/schema/schemas/factories.py @@ -1,7 +1,7 @@ """OpenAPI core schemas factories module""" import logging -from functools import lru_cache +from openapi_core.compat import lru_cache from openapi_core.schema.properties.generators import PropertiesGenerator from openapi_core.schema.schemas.models import Schema diff --git a/openapi_core/schema/servers/generators.py b/openapi_core/schema/servers/generators.py index 86b079a..d05b589 100644 --- a/openapi_core/schema/servers/generators.py +++ b/openapi_core/schema/servers/generators.py @@ -1,8 +1,7 @@ """OpenAPI core servers generators module""" -from functools import lru_cache - from six import iteritems +from openapi_core.compat import lru_cache from openapi_core.schema.servers.models import Server, ServerVariable diff --git a/openapi_core/schema/specs/factories.py b/openapi_core/schema/specs/factories.py index 06868f6..16f736d 100644 --- a/openapi_core/schema/specs/factories.py +++ b/openapi_core/schema/specs/factories.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- """OpenAPI core specs factories module""" -from functools import lru_cache from openapi_spec_validator import openapi_v3_spec_validator +from openapi_core.compat import lru_cache from openapi_core.schema.components.factories import ComponentsFactory from openapi_core.schema.infos.factories import InfoFactory from openapi_core.schema.paths.generators import PathsGenerator diff --git a/openapi_core/schema/specs/models.py b/openapi_core/schema/specs/models.py index 79a27e8..629c24e 100644 --- a/openapi_core/schema/specs/models.py +++ b/openapi_core/schema/specs/models.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- """OpenAPI core specs models module""" import logging -from functools import partialmethod +from openapi_core.compat import partialmethod from openapi_core.schema.operations.exceptions import InvalidOperation from openapi_core.schema.servers.exceptions import InvalidServer diff --git a/openapi_core/validation/util.py b/openapi_core/validation/util.py index 62a3cb4..ace45e2 100644 --- a/openapi_core/validation/util.py +++ b/openapi_core/validation/util.py @@ -1,9 +1,5 @@ """OpenAPI core validation util module""" -try: - from urllib.parse import urlparse - -except ImportError: - from urlparse import urlparse +from six.moves.urllib.parse import urlparse def is_absolute(url): diff --git a/requirements_2.7.txt b/requirements_2.7.txt index 624bfea..19ba7bb 100644 --- a/requirements_2.7.txt +++ b/requirements_2.7.txt @@ -1,5 +1,6 @@ openapi-spec-validator six +lazy-object-proxy backports.functools-lru-cache backports.functools-partialmethod enum34 diff --git a/setup.py b/setup.py index 3bb9b26..8813608 100644 --- a/setup.py +++ b/setup.py @@ -25,6 +25,11 @@ def get_metadata(init_file): return dict(re.findall("__([a-z]+)__ = '([^']+)'", init_file)) +def install_requires(): + py27 = '_2.7' if sys.version_info < (3,) else '' + return read_requirements('requirements{}.txt'.format(py27)) + + class PyTest(TestCommand): """Command to run unit tests after in-place build.""" @@ -53,8 +58,6 @@ init_path = os.path.join('openapi_core', '__init__.py') init_py = read_file(init_path) metadata = get_metadata(init_py) -py27 = '_2.7' if sys.version_info < (3,) else '' - setup( name='openapi-core', @@ -70,13 +73,13 @@ setup( 'Intended Audience :: Developers', "Topic :: Software Development :: Libraries :: Python Modules", "Operating System :: OS Independent", - 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', 'Programming Language :: Python :: 3.6', 'Topic :: Software Development :: Libraries', ], - install_requires=read_requirements('requirements{}.txt'.format(py27)), + install_requires=install_requires(), tests_require=read_requirements('requirements_dev.txt'), extras_require={ 'flask': ["werkzeug"], diff --git a/tests/unit/validation/test_util.py b/tests/unit/validation/test_util.py new file mode 100644 index 0000000..8cf353c --- /dev/null +++ b/tests/unit/validation/test_util.py @@ -0,0 +1,18 @@ +from openapi_core.validation.util import path_qs + + +class TestPathQs(object): + + def test_path(self): + url = 'https://test.com:1234/path' + + result = path_qs(url) + + assert result == '/path' + + def test_query(self): + url = 'https://test.com:1234/path?query=1' + + result = path_qs(url) + + assert result == '/path?query=1'