diff --git a/.gitignore b/.gitignore index 478b4e2..c151cc7 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,8 @@ docs/_build/ docs/modules.rst docs/imagemuck*.rst +imagemuck/openapi.yaml + .vscode/ .idea/ diff --git a/Makefile b/Makefile index 2ace9ea..83e1878 100644 --- a/Makefile +++ b/Makefile @@ -15,6 +15,7 @@ clean-tox: rm --recursive --force ./.mypy_cache rm --recursive --force ./.tox rm --force .coverage + rm --force ./$(PROJECT)/openapi.yaml find ./tests -type d -name __pycache__ -prune -exec rm --recursive --force {} \; clean-py: @@ -31,13 +32,16 @@ clean-docs: clean: clean-tox clean-py clean-docs ## Clean temp build/cache files and directories rm --force ./*db* -wheel: ## Build Python binary distribution wheel package +prep: + cp ./openapi.yaml ./$(PROJECT)/openapi.yaml + +wheel: prep ## Build Python binary distribution wheel package poetry build --format wheel -source: ## Build Python source distribution package +source: prep ## Build Python source distribution package poetry build --format sdist -test: clean-tox ## Run the project testsuite(s) +test: clean-tox prep ## Run the project testsuite(s) poetry run tox publish: clean test wheel source ## Build and upload to pypi (requires $PYPI_API_KEY be set) diff --git a/imagemuck/resources/openapi.yaml b/imagemuck/resources/openapi.yaml deleted file mode 120000 index 0ec1ca4..0000000 --- a/imagemuck/resources/openapi.yaml +++ /dev/null @@ -1 +0,0 @@ -../../openapi.yaml \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index d286a40..b2f6ee7 100644 --- a/poetry.lock +++ b/poetry.lock @@ -505,6 +505,17 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "isodate" +version = "0.6.0" +description = "An ISO 8601 date/time/duration parser and formatter" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +six = "*" + [[package]] name = "isort" version = "5.8.0" @@ -566,6 +577,24 @@ MarkupSafe = ">=0.23" [package.extras] i18n = ["Babel (>=0.8)"] +[[package]] +name = "jsonschema" +version = "3.2.0" +description = "An implementation of JSON Schema validation for Python" +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +attrs = ">=17.4.0" +importlib-metadata = {version = "*", markers = "python_version < \"3.8\""} +pyrsistent = ">=0.14.0" +six = ">=1.11.0" + +[package.extras] +format = ["idna", "jsonpointer (>1.13)", "rfc3987", "strict-rfc3339", "webcolors"] +format_nongpl = ["idna", "jsonpointer (>1.13)", "webcolors", "rfc3986-validator (>0.1.0)", "rfc3339-validator"] + [[package]] name = "keyring" version = "21.8.0" @@ -750,6 +779,42 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "openapi-schema-validator" +version = "0.1.5" +description = "OpenAPI schema validation for Python" +category = "dev" +optional = false +python-versions = ">= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*, != 3.4.*" + +[package.dependencies] +isodate = "*" +jsonschema = ">=3.0.0" +six = "*" + +[package.extras] +isodate = ["isodate"] +rfc3339_validator = ["rfc3339-validator"] +strict_rfc3339 = ["strict-rfc3339"] + +[[package]] +name = "openapi-spec-validator" +version = "0.3.0" +description = "OpenAPI 2.0 (aka Swagger) and OpenAPI 3.0.0 spec validator" +category = "dev" +optional = false +python-versions = ">= 2.7, != 3.0.*, != 3.1.*, != 3.2.*, != 3.3.*, != 3.4.*" + +[package.dependencies] +jsonschema = "*" +openapi-schema-validator = "*" +PyYAML = ">=5.1" +six = "*" + +[package.extras] +dev = ["pre-commit"] +requests = ["requests"] + [[package]] name = "packaging" version = "20.9" @@ -990,6 +1055,14 @@ category = "dev" optional = false python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +[[package]] +name = "pyrsistent" +version = "0.17.3" +description = "Persistent/Functional/Immutable data structures" +category = "dev" +optional = false +python-versions = ">=3.5" + [[package]] name = "pytest" version = "5.4.3" @@ -1478,7 +1551,7 @@ testing = ["pytest (>=4.6)", "pytest-checkdocs (>=1.2.3)", "pytest-flake8", "pyt [metadata] lock-version = "1.1" python-versions = "^3.7" -content-hash = "1b8a69bd62b3c5bd96d2512ad70438c3aa19a5064ca8303d45aa968432197500" +content-hash = "56f756dae6d71779599a25bcffd28217e62adcc45bb8fd9a0485f80a77da69a5" [metadata.files] alabaster = [ @@ -1748,6 +1821,10 @@ ipython-genutils = [ {file = "ipython_genutils-0.2.0-py2.py3-none-any.whl", hash = "sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8"}, {file = "ipython_genutils-0.2.0.tar.gz", hash = "sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"}, ] +isodate = [ + {file = "isodate-0.6.0-py2.py3-none-any.whl", hash = "sha256:aa4d33c06640f5352aca96e4b81afd8ab3b47337cc12089822d6f322ac772c81"}, + {file = "isodate-0.6.0.tar.gz", hash = "sha256:2e364a3d5759479cdb2d37cce6b9376ea504db2ff90252a2e5b7cc89cc9ff2d8"}, +] isort = [ {file = "isort-5.8.0-py3-none-any.whl", hash = "sha256:2bb1680aad211e3c9944dbce1d4ba09a989f04e238296c87fe2139faa26d655d"}, {file = "isort-5.8.0.tar.gz", hash = "sha256:0a943902919f65c5684ac4e0154b1ad4fac6dcaa5d9f3426b732f1c8b5419be6"}, @@ -1768,6 +1845,10 @@ jinja2 = [ {file = "Jinja2-2.11.3-py2.py3-none-any.whl", hash = "sha256:03e47ad063331dd6a3f04a43eddca8a966a26ba0c5b7207a9a9e4e08f1b29419"}, {file = "Jinja2-2.11.3.tar.gz", hash = "sha256:a6d58433de0ae800347cab1fa3043cebbabe8baa9d29e668f1c768cb87a333c6"}, ] +jsonschema = [ + {file = "jsonschema-3.2.0-py2.py3-none-any.whl", hash = "sha256:4e5b3cf8216f577bee9ce139cbe72eca3ea4f292ec60928ff24758ce626cd163"}, + {file = "jsonschema-3.2.0.tar.gz", hash = "sha256:c8a85b28d377cc7737e46e2d9f2b4f44ee3c0e1deac6bf46ddefc7187d30797a"}, +] keyring = [ {file = "keyring-21.8.0-py3-none-any.whl", hash = "sha256:4be9cbaaaf83e61d6399f733d113ede7d1c73bc75cb6aeb64eee0f6ac39b30ea"}, {file = "keyring-21.8.0.tar.gz", hash = "sha256:1746d3ac913d449a090caf11e9e4af00e26c3f7f7e81027872192b2398b98675"}, @@ -1948,6 +2029,16 @@ nodeenv = [ {file = "nodeenv-1.6.0-py2.py3-none-any.whl", hash = "sha256:621e6b7076565ddcacd2db0294c0381e01fd28945ab36bcf00f41c5daf63bef7"}, {file = "nodeenv-1.6.0.tar.gz", hash = "sha256:3ef13ff90291ba2a4a7a4ff9a979b63ffdd00a464dbe04acf0ea6471517a4c2b"}, ] +openapi-schema-validator = [ + {file = "openapi-schema-validator-0.1.5.tar.gz", hash = "sha256:a4b2712020284cee880b4c55faa513fbc2f8f07f365deda6098f8ab943c9f0df"}, + {file = "openapi_schema_validator-0.1.5-py2-none-any.whl", hash = "sha256:215b516d0942f4e8e2446cf3f7d4ff2ed71d102ebddcc30526d8a3f706ab1df6"}, + {file = "openapi_schema_validator-0.1.5-py3-none-any.whl", hash = "sha256:b65d6c2242620bfe76d4c749b61cd9657e4528895a8f4fb6f916085b508ebd24"}, +] +openapi-spec-validator = [ + {file = "openapi-spec-validator-0.3.0.tar.gz", hash = "sha256:53ba3d884e98ff2062d5ada025aa590541dcd665b8f81067dc82dd61c0923759"}, + {file = "openapi_spec_validator-0.3.0-py2-none-any.whl", hash = "sha256:e11df7c559339027bd04f2399bc82474983129a6a7a6a0421eaa95e2c844d686"}, + {file = "openapi_spec_validator-0.3.0-py3-none-any.whl", hash = "sha256:4083fc5aac3e9f751c2a82d4ec5cf3adad5f967d0faf31495d8b56a0b0f9705c"}, +] packaging = [ {file = "packaging-20.9-py2.py3-none-any.whl", hash = "sha256:67714da7f7bc052e064859c05c595155bd1ee9f69f76557e21f051443c20947a"}, {file = "packaging-20.9.tar.gz", hash = "sha256:5b327ac1320dc863dca72f4514ecc086f31186744b84a230374cc1fd776feae5"}, @@ -2035,6 +2126,9 @@ pyparsing = [ {file = "pyparsing-2.4.7-py2.py3-none-any.whl", hash = "sha256:ef9d7589ef3c200abe66653d3f1ab1033c3c419ae9b9bdb1240a85b024efc88b"}, {file = "pyparsing-2.4.7.tar.gz", hash = "sha256:c203ec8783bf771a155b207279b9bccb8dea02d8f0c9e5f8ead507bc3246ecc1"}, ] +pyrsistent = [ + {file = "pyrsistent-0.17.3.tar.gz", hash = "sha256:2e636185d9eb976a18a8a8e96efce62f2905fea90041958d8cc2a189756ebf3e"}, +] pytest = [ {file = "pytest-5.4.3-py3-none-any.whl", hash = "sha256:5c0db86b698e8f170ba4582a492248919255fcd4c79b1ee64ace34301fb589a1"}, {file = "pytest-5.4.3.tar.gz", hash = "sha256:7979331bfcba207414f5e1263b5a0f8f521d0f457318836a7355531ed1a4c7d8"}, diff --git a/pyproject.toml b/pyproject.toml index 57ada26..73f396b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ packages = [ ] include = [ "imagemuck/py.typed", - "imagemuck/resources/openapi.yaml" + "imagemuck/openapi.yaml" ] keywords = ["flask", "image", "thumbnail", "hosting"] readme = "README.md" @@ -63,6 +63,7 @@ sphinx-autodoc-typehints = "^1.11.1" toml = "^0.10.1" tox = "^3.20.0" tox-poetry-installer = {extras = ["poetry"], version = "^0.8.0"} +openapi-spec-validator = "^0.3.0" [build-system] requires = ["poetry-core>=1.0.0"] diff --git a/tests/test_openapi.py b/tests/test_openapi.py new file mode 100644 index 0000000..501f046 --- /dev/null +++ b/tests/test_openapi.py @@ -0,0 +1,20 @@ +import importlib.resources + +import openapi_spec_validator +import ruamel.yaml + +from imagemuck import __about__ + + +yaml = ruamel.yaml.YAML(typ="safe") # pylint: disable=invalid-name + + +def test_openapi(): + openapi_spec_validator.validate_spec( + yaml.load(importlib.resources.read_text("imagemuck", "openapi.yaml")) + ) + + +def test_openapi_version(): + spec = yaml.load(importlib.resources.read_text("imagemuck", "openapi.yaml")) + assert spec["info"]["version"] == __about__.__version__ diff --git a/tox.ini b/tox.ini index 2214b1a..a672775 100644 --- a/tox.ini +++ b/tox.ini @@ -13,8 +13,10 @@ description = Run the tests require_locked_deps = true require_poetry = true locked_deps = + openapi-spec-validator pytest pytest-cov + ruamel.yaml toml commands = pytest --cov={envsitepackagesdir}/imagemuck --cov-config {toxinidir}/.coveragerc --cov-report term-missing {toxinidir}/tests/