77ResolvingParser that additionally resolves any $ref references.
88"""
99
10+ import sys
11+ from typing import Any , Dict , Optional , Union
12+ from urllib .parse import ParseResult
13+
14+ from packaging .version import Version # type: ignore[import-not-found]
15+
16+ from prance .util .path import JsonValue
17+
1018__author__ = "Jens Finkhaeuser"
1119__copyright__ = "Copyright (c) 2016-2021 Jens Finkhaeuser"
1220__license__ = "MIT"
1321__all__ = ("util" , "mixins" , "cli" , "convert" )
14- import sys
15-
16- from packaging .version import Version
1722
1823try :
19- from prance ._version import version as __version__
24+ from prance ._version import version as __version__ # type: ignore[import-not-found]
2025except ImportError :
2126 # todo: better gussing
2227 __version__ = "0.20.0+unknown"
@@ -55,7 +60,7 @@ class BaseParser(mixins.YAMLMixin, mixins.JSONMixin):
5560 SPEC_VERSION_2_PREFIX = "Swagger/OpenAPI"
5661 SPEC_VERSION_3_PREFIX = "OpenAPI"
5762
58- def __init__ (self , url = None , spec_string = None , lazy = False , ** kwargs ) :
63+ def __init__ (self , url : Optional [ str ] = None , spec_string : Optional [ str ] = None , lazy : bool = False , ** kwargs : Any ) -> None :
5964 """
6065 Load, parse and validate specs.
6166
@@ -82,32 +87,33 @@ def __init__(self, url=None, spec_string=None, lazy=False, **kwargs):
8287 )
8388
8489 # Keep the parameters around for later use
85- self .url = None
90+ self .url : ParseResult
8691 if url :
8792 from .util .url import absurl
8893 from .util .fs import abspath
8994 import os
9095
9196 self .url = absurl (url , abspath (os .getcwd ()))
9297 else :
93- self .url = _PLACEHOLDER_URL
98+ from urllib .parse import urlparse
99+ self .url = urlparse (_PLACEHOLDER_URL )
94100
95- self ._spec_string = spec_string
101+ self ._spec_string : Optional [ str ] = spec_string
96102
97103 # Initialize variables we're filling later
98- self .specification = None
99- self .version = None
100- self .version_name = None
101- self .version_parsed = ()
102- self .valid = False
104+ self .specification : Optional [ JsonValue ] = None
105+ self .version : Optional [ str ] = None
106+ self .version_name : Optional [ str ] = None
107+ self .version_parsed : tuple = ()
108+ self .valid : bool = False
103109
104110 # Add kw args as options
105- self .options = kwargs
111+ self .options : Dict [ str , Any ] = kwargs
106112
107113 # Verify backend
108114 from .util import default_validation_backend
109115
110- self .backend = self .options .get ("backend" , default_validation_backend ())
116+ self .backend : str = self .options .get ("backend" , default_validation_backend ())
111117 if self .backend not in BaseParser .BACKENDS .keys ():
112118 raise ValueError (
113119 f"Backend may only be one of { BaseParser .BACKENDS .keys ()} !"
@@ -117,7 +123,7 @@ def __init__(self, url=None, spec_string=None, lazy=False, **kwargs):
117123 if not lazy :
118124 self .parse ()
119125
120- def parse (self ): # noqa: F811
126+ def parse (self ) -> None : # noqa: F811
121127 """
122128 When the BaseParser was lazily created, load and parse now.
123129
@@ -128,7 +134,7 @@ def parse(self): # noqa: F811
128134 strict = self .options .get ("strict" , True )
129135
130136 # If we have a file name, we need to read that in.
131- if self .url and self .url != _PLACEHOLDER_URL :
137+ if self .url and self .url . geturl () != _PLACEHOLDER_URL :
132138 from .util .url import fetch_url
133139
134140 encoding = self .options .get ("encoding" , None )
@@ -138,7 +144,7 @@ def parse(self): # noqa: F811
138144 if self ._spec_string :
139145 from .util .formats import parse_spec
140146
141- self .specification = parse_spec (self ._spec_string , self .url )
147+ self .specification = parse_spec (self ._spec_string , self .url . path )
142148
143149 # If we have a parsed spec, convert it to JSON. Then we can validate
144150 # the JSON. At this point, we *require* a parsed specification to exist,
@@ -147,7 +153,7 @@ def parse(self): # noqa: F811
147153
148154 self ._validate ()
149155
150- def _validate (self ):
156+ def _validate (self ) -> None :
151157 # Ensure specification is a mapping
152158 from collections .abc import Mapping
153159
@@ -159,18 +165,22 @@ def _validate(self):
159165
160166 # Fetch the spec version. Note that this is the spec version the spec
161167 # *claims* to be; we later set the one we actually could validate as.
162- spec_version = None
168+ spec_version : Optional [ str ] = None
163169 if spec_version is None :
164- spec_version = self .specification .get ("openapi" , None )
170+ version_val = self .specification .get ("openapi" , None )
171+ if isinstance (version_val , str ):
172+ spec_version = version_val
165173 if spec_version is None :
166- spec_version = self .specification .get ("swagger" , None )
174+ version_val = self .specification .get ("swagger" , None )
175+ if isinstance (version_val , str ):
176+ spec_version = version_val
167177 if spec_version is None :
168178 raise ValidationError (
169179 "Could not determine specification schema " "version!"
170180 )
171181
172182 # Try parsing the spec version, examine the first component.
173- import packaging .version
183+ import packaging .version # type: ignore[import-not-found]
174184
175185 parsed = packaging .version .parse (spec_version )
176186 if parsed .major not in versions :
@@ -187,7 +197,7 @@ def _validate(self):
187197 validator (parsed )
188198 self .valid = True
189199
190- def __set_version (self , prefix , version : Version ):
200+ def __set_version (self , prefix : str , version : Version ) -> None :
191201 self .version_name = prefix
192202 self .version_parsed = version .release
193203
@@ -196,12 +206,12 @@ def __set_version(self, prefix, version: Version):
196206 stringified = "%d.%d" % (version .major , version .minor )
197207 self .version = f"{ self .version_name } { stringified } "
198208
199- def _validate_flex (self , spec_version : Version ): # pragma: nocover
209+ def _validate_flex (self , spec_version : Version ) -> None : # pragma: nocover
200210 # Set the version independently of whether validation succeeds
201211 self .__set_version (BaseParser .SPEC_VERSION_2_PREFIX , spec_version )
202212
203- from flex .exceptions import ValidationError as JSEValidationError
204- from flex .core import parse as validate
213+ from flex .exceptions import ValidationError as JSEValidationError # type: ignore[import-not-found]
214+ from flex .core import parse as validate # type: ignore[import-not-found]
205215
206216 try :
207217 validate (self .specification )
@@ -212,12 +222,12 @@ def _validate_flex(self, spec_version: Version): # pragma: nocover
212222
213223 def _validate_swagger_spec_validator (
214224 self , spec_version : Version
215- ): # pragma: nocover
225+ ) -> None : # pragma: nocover
216226 # Set the version independently of whether validation succeeds
217227 self .__set_version (BaseParser .SPEC_VERSION_2_PREFIX , spec_version )
218228
219- from swagger_spec_validator .common import SwaggerValidationError as SSVErr
220- from swagger_spec_validator .validator20 import validate_spec
229+ from swagger_spec_validator .common import SwaggerValidationError as SSVErr # type: ignore[import-not-found]
230+ from swagger_spec_validator .validator20 import validate_spec # type: ignore[import-not-found]
221231
222232 try :
223233 validate_spec (self .specification )
@@ -228,10 +238,10 @@ def _validate_swagger_spec_validator(
228238
229239 def _validate_openapi_spec_validator (
230240 self , spec_version : Version
231- ): # pragma: nocover
232- from openapi_spec_validator import validate
233- from jsonschema .exceptions import ValidationError as JSEValidationError
234- from referencing .exceptions import Unresolvable
241+ ) -> None : # pragma: nocover
242+ from openapi_spec_validator import validate # type: ignore[import-not-found]
243+ from jsonschema .exceptions import ValidationError as JSEValidationError # type: ignore[import-untyped]
244+ from referencing .exceptions import Unresolvable # type: ignore[import-not-found]
235245
236246 # Validate according to detected version. Unsupported versions are
237247 # already caught outside of this function.
@@ -253,7 +263,7 @@ def _validate_openapi_spec_validator(
253263 except Unresolvable as ref_unres :
254264 raise_from (ValidationError , ref_unres )
255265
256- def _strict_warning (self ):
266+ def _strict_warning (self ) -> str :
257267 """Return a warning if strict mode is off."""
258268 if self .options .get ("strict" , True ):
259269 return (
@@ -269,7 +279,7 @@ def _strict_warning(self):
269279class ResolvingParser (BaseParser ):
270280 """The ResolvingParser extends BaseParser with resolving references by inlining."""
271281
272- def __init__ (self , url = None , spec_string = None , lazy = False , ** kwargs ) :
282+ def __init__ (self , url : Optional [ str ] = None , spec_string : Optional [ str ] = None , lazy : bool = False , ** kwargs : Any ) -> None :
273283 """
274284 See :py:class:`BaseParser`.
275285
@@ -280,11 +290,11 @@ def __init__(self, url=None, spec_string=None, lazy=False, **kwargs):
280290 Additional parameters, see :py::class:`util.RefResolver`.
281291 """
282292 # Create a reference cache
283- self .__reference_cache = {}
293+ self .__reference_cache : Dict [ Union [ str , tuple ], JsonValue ] = {}
284294
285295 BaseParser .__init__ (self , url = url , spec_string = spec_string , lazy = lazy , ** kwargs )
286296
287- def _validate (self ):
297+ def _validate (self ) -> None :
288298 # We have a problem with the BaseParser's validate function: the
289299 # jsonschema implementation underlying it does not accept relative
290300 # path references, but the Swagger specs allow them:
@@ -300,7 +310,7 @@ def _validate(self):
300310 "resolve_method" ,
301311 "strict" ,
302312 )
303- forward_args = {
313+ forward_args : Dict [ str , Any ] = {
304314 k : v for (k , v ) in self .options .items () if k in forward_arg_names
305315 }
306316 resolver = RefResolver (
@@ -318,10 +328,10 @@ def _validate(self):
318328
319329# Underscored to allow some time for the public API to be stabilized.
320330class _TranslatingParser (BaseParser ):
321- def _validate (self ):
331+ def _validate (self ) -> None :
322332 from .util .translator import _RefTranslator
323333
324- translator = _RefTranslator (self .specification , self .url )
334+ translator = _RefTranslator (self .specification , self .url . geturl () )
325335 translator .translate_references ()
326336 self .specification = translator .specs
327337
0 commit comments