diff --git a/README.md b/README.md index 494a8522..b6cfe2dc 100644 --- a/README.md +++ b/README.md @@ -443,7 +443,9 @@ OpenAPI-only options: OpenAPI) --use-operation-id-as-name use operation id of OpenAPI as class names of models - --validation Enable validation (Only OpenAPI) + --validation Deprecated: Enable validation (Only OpenAPI). this + option is deprecated. it will be removed in future + releases General options: --debug show debug message (require "debug". `$ pip install 'datamodel-code-generator[debug]'`) diff --git a/datamodel_code_generator/__init__.py b/datamodel_code_generator/__init__.py index 068405dc..7f65acd6 100644 --- a/datamodel_code_generator/__init__.py +++ b/datamodel_code_generator/__init__.py @@ -79,7 +79,7 @@ else: def enable_debug_message() -> None: # pragma: no cover if not pysnooper: raise Exception( - "Please run $pip install 'datamodel-code-generator[debug]' to use debug option" + "Please run `$pip install 'datamodel-code-generator[debug]'` to use debug option" ) pysnooper.tracer.DISABLED = False diff --git a/datamodel_code_generator/arguments.py b/datamodel_code_generator/arguments.py index e78ea4f0..95136326 100644 --- a/datamodel_code_generator/arguments.py +++ b/datamodel_code_generator/arguments.py @@ -410,7 +410,8 @@ openapi_options.add_argument( ) openapi_options.add_argument( '--validation', - help='Enable validation (Only OpenAPI)', + help='Deprecated: Enable validation (Only OpenAPI). this option is deprecated. it will be removed in future ' + 'releases', action='store_true', default=None, ) diff --git a/datamodel_code_generator/http.py b/datamodel_code_generator/http.py index 82a5b259..a992a189 100644 --- a/datamodel_code_generator/http.py +++ b/datamodel_code_generator/http.py @@ -6,7 +6,7 @@ try: import httpx except ImportError: # pragma: no cover raise Exception( - "Please run $pip install 'datamodel-code-generator[http]' to resolve URL Reference" + "Please run `$pip install 'datamodel-code-generator[http]`' to resolve URL Reference" ) diff --git a/datamodel_code_generator/parser/openapi.py b/datamodel_code_generator/parser/openapi.py index 8f99df9b..279f6fa6 100644 --- a/datamodel_code_generator/parser/openapi.py +++ b/datamodel_code_generator/parser/openapi.py @@ -23,6 +23,7 @@ from typing import ( Union, ) from urllib.parse import ParseResult +from warnings import warn from pydantic import Field @@ -550,13 +551,27 @@ class OpenAPIParser(JsonSchemaParser): def parse_raw(self) -> None: for source, path_parts in self._get_context_source_path_parts(): if self.validation: - from prance import BaseParser - - BaseParser( - spec_string=source.text, - backend='openapi-spec-validator', - encoding=self.encoding, + warn( + 'Deprecated: `--validation` option is deprecated. the option will be removed in a future ' + 'release. please use another tool to validate OpenAPI.\n' ) + + try: + from prance import BaseParser + + BaseParser( + spec_string=source.text, + backend='openapi-spec-validator', + encoding=self.encoding, + ) + except ImportError: # pragma: no cover + warn( + "Warning: Validation was skipped for OpenAPI. `prance` or `openapi-spec-validator` are not " + "installed.\n" + "To use --validation option after datamodel-code-generator 0.24.0, Please run `$pip install " + "'datamodel-code-generator[validation]'`.\n" + ) + specification: Dict[str, Any] = load_yaml(source.text) self.raw_obj = specification schemas: Dict[Any, Any] = specification.get('components', {}).get( diff --git a/docs/index.md b/docs/index.md index fea31185..b4b3d34f 100644 --- a/docs/index.md +++ b/docs/index.md @@ -440,7 +440,9 @@ OpenAPI-only options: OpenAPI) --use-operation-id-as-name use operation id of OpenAPI as class names of models - --validation Enable validation (Only OpenAPI) + --validation Deprecated: Enable validation (Only OpenAPI). this + option is deprecated. it will be removed in future + releases General options: --debug show debug message (require "debug". `$ pip install 'datamodel-code-generator[debug]'`) diff --git a/poetry.lock b/poetry.lock index 66bc6992..94bbf4cb 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1663,8 +1663,9 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [extras] debug = ["PySnooper"] http = ["httpx"] +validation = ["openapi-spec-validator", "prance"] [metadata] lock-version = "2.0" python-versions = "^3.7" -content-hash = "a80ca8adc2c59d0b7c127b468c9190d34fb68b747e004c9f1f30798fa70de6d2" +content-hash = "3e92c6177b16601bf25bbcdd7a7292fe9e7a8102051cc70acb9e2e7726377cef" diff --git a/pyproject.toml b/pyproject.toml index 29acd502..379741cc 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,17 +49,17 @@ pydantic = [ {extras = ["email"], version = ">=1.10.0,!=2.0.0,!=2.0.1,<3.0,!=2.4.0", python = "^3.12"} ] argcomplete = ">=1.10,<4.0" -prance = ">=0.18.2" -openapi-spec-validator = ">=0.2.8,<0.7.0" jinja2 = ">=2.10.1,<4.0" inflect = ">=4.1.0,<6.0" black = ">=19.10b0" isort = ">=4.3.21,<6.0" -PySnooper = { version = ">=0.4.1,<2.0.0", optional = true } -toml = { version = ">=0.10.0,<1.0.0", python = "<3.11" } genson = ">=1.2.1,<2.0" -httpx = { version = "*", optional = true } packaging = "*" +prance = { version = ">=0.18.2", optional = true } +openapi-spec-validator = { version = ">=0.2.8,<0.7.0", optional = true } +toml = { version = ">=0.10.0,<1.0.0", python = "<3.11" } +PySnooper = { version = ">=0.4.1,<2.0.0", optional = true } +httpx = { version = "*", optional = true } [tool.poetry.group.dev.dependencies] pytest = ">6.0" @@ -80,10 +80,13 @@ ruff = ">=0.0.290,<0.1.6" ruff-lsp = ">=0.0.39,<0.0.41" pre-commit = "*" pytest-xdist = "^3.3.1" +prance = "*" +openapi-spec-validator = "*" [tool.poetry.extras] http = ["httpx"] debug = ["PySnooper"] +validation = ["prance", "openapi-spec-validator"] [tool.ruff] line-length = 88 diff --git a/tests/test_main.py b/tests/test_main.py index 04524b76..8988ce91 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -801,7 +801,9 @@ def test_show_help_when_no_input(mocker): @freeze_time('2019-07-26') -def test_validation(): +def test_validation(mocker): + mock_prance = mocker.patch('prance.BaseParser') + with TemporaryDirectory() as output_dir: output_file: Path = Path(output_dir) / 'output.py' return_code: Exit = main( @@ -818,10 +820,12 @@ def test_validation(): output_file.read_text() == (EXPECTED_MAIN_PATH / 'validation' / 'output.py').read_text() ) + mock_prance.assert_called_once() @freeze_time('2019-07-26') -def test_validation_failed(): +def test_validation_failed(mocker): + mock_prance = mocker.patch('prance.BaseParser', side_effect=Exception('error')) with TemporaryDirectory() as output_dir: output_file: Path = Path(output_dir) / 'output.py' assert ( @@ -838,6 +842,7 @@ def test_validation_failed(): ) == Exit.ERROR ) + mock_prance.assert_called_once() @pytest.mark.parametrize( @@ -4238,7 +4243,9 @@ def test_main_jsonschema_has_default_value(): @freeze_time('2019-07-26') -def test_openapi_special_yaml_keywords(): +def test_openapi_special_yaml_keywords(mocker): + mock_prance = mocker.patch('prance.BaseParser') + with TemporaryDirectory() as output_dir: output_file: Path = Path(output_dir) / 'output.py' return_code: Exit = main( @@ -4257,6 +4264,7 @@ def test_openapi_special_yaml_keywords(): EXPECTED_MAIN_PATH / 'main_special_yaml_keywords' / 'output.py' ).read_text() ) + mock_prance.assert_called_once() @freeze_time('2019-07-26')