Skip to content

Commit 82dc9a5

Browse files
committed
resovler / models refator (sqm)
1 parent 64ba075 commit 82dc9a5

File tree

3 files changed

+84
-38
lines changed

3 files changed

+84
-38
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
import urllib.parse
2+
from typing import List, Union
3+
4+
5+
class Pointer:
6+
""" https://tools.ietf.org/html/rfc6901 """
7+
8+
def __init__(self, pointer: str) -> None:
9+
if pointer is None or pointer != "" and not pointer.startswith("/"):
10+
raise ValueError(f'Invalid pointer value {pointer}, it must match: *( "/" reference-token )')
11+
12+
self._pointer = pointer
13+
14+
@property
15+
def value(self) -> str:
16+
return self._pointer
17+
18+
@property
19+
def parent(self) -> Union["Pointer", None]:
20+
tokens = self.tokens(False)
21+
22+
if len(tokens) > 1:
23+
tokens.pop()
24+
return Pointer("/".join(tokens))
25+
else:
26+
assert tokens[-1] == ""
27+
return None
28+
29+
def tokens(self, unescape: bool = True) -> List[str]:
30+
tokens = []
31+
32+
if unescape:
33+
for token in self._pointer.split("/"):
34+
tokens.append(self._unescape(token))
35+
else:
36+
tokens = self._pointer.split("/")
37+
38+
return tokens
39+
40+
@property
41+
def unescapated_value(self) -> str:
42+
return self._unescape(self._pointer)
43+
44+
def _unescape(self, data: str) -> str:
45+
data = urllib.parse.unquote(data)
46+
data = data.replace("~1", "/")
47+
data = data.replace("~0", "~")
48+
return data
Lines changed: 25 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,59 +1,51 @@
1-
# import urllib
2-
from pathlib import PosixPath
3-
from typing import Union
1+
import urllib.parse
2+
3+
from .pointer import Pointer
44

55

66
class Reference:
7+
""" https://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03 """
8+
79
def __init__(self, reference: str):
810
self._ref = reference
9-
10-
@property
11-
def remote_path(self) -> Union[str, None]:
12-
if self.is_remote():
13-
return self._ref.split("#")[0]
14-
return None
15-
16-
@property
17-
def path_parent(self) -> str:
18-
path = PosixPath(self.path)
19-
return str(path.parent)
11+
self._parsed_ref = urllib.parse.urlparse(reference)
2012

2113
@property
2214
def path(self) -> str:
23-
path = "/"
15+
return urllib.parse.urldefrag(self._parsed_ref.geturl()).url
2416

25-
if not self.is_full_document():
26-
parts = self._ref.split("#")
27-
path = parts[-1]
28-
if not path.startswith("/") and not path.startswith("."):
29-
path = f"/{path}"
30-
31-
return path
32-
# d = urllib.parse.unquote(d)
33-
# d = d.replace("~1", "/")
34-
# return d
17+
@property
18+
def pointer(self) -> Pointer:
19+
frag = self._parsed_ref.fragment
20+
if self.is_url() and frag != "" and not frag.startswith("/"):
21+
frag = f"/{frag}"
3522

36-
def is_full_document(self) -> bool:
37-
return "#" not in self._ref
23+
return Pointer(frag)
3824

3925
def is_relative(self) -> bool:
26+
""" return True if reference path is a relative path """
4027
return not self.is_absolute()
4128

4229
def is_absolute(self) -> bool:
43-
remote_path = self.remote_path
44-
if remote_path:
45-
return not remote_path.startswith("..") and (remote_path.startswith("/") or remote_path.startswith("http"))
46-
return True
30+
""" return True is reference path is an absolute path """
31+
return self._parsed_ref.netloc != ""
4732

4833
@property
4934
def value(self) -> str:
5035
return self._ref
5136

5237
def is_url(self) -> bool:
53-
return self.is_remote() and (self._ref.startswith("//", 0) or self._ref.startswith("http", 0))
38+
""" return True if the reference path is pointing to an external url location """
39+
return self.is_remote() and self._parsed_ref.netloc != ""
5440

5541
def is_remote(self) -> bool:
42+
""" return True if the reference pointer is pointing to a remote document """
5643
return not self.is_local()
5744

5845
def is_local(self) -> bool:
59-
return self._ref.startswith("#", 0)
46+
""" return True if the reference pointer is pointing to the current document """
47+
return self._parsed_ref.path == ""
48+
49+
def is_full_document(self) -> bool:
50+
""" return True if the reference pointer is pointing to the whole document content """
51+
return self.pointer.parent is None

openapi_python_client/resolver/resolved_schema.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def _process_remote_paths(self) -> None:
3737
if ref.is_local():
3838
continue
3939

40-
remote_path = ref.remote_path
40+
remote_path = ref.pointer.value
4141
path = ref.path
4242

4343
if remote_path not in self._refs:
@@ -67,7 +67,7 @@ def _process_remote_components(
6767
if depth > 0:
6868
self._transform_to_local_components(owner, ref)
6969
else:
70-
remote_path = ref.remote_path
70+
remote_path = ref.pointer.value
7171
if remote_path not in self._refs:
7272
self._errors.append("Failed to resolve remote reference > {0}".format(remote_path))
7373
else:
@@ -80,8 +80,11 @@ def _transform_to_local_components(self, owner: SchemaData, ref: Reference) -> N
8080

8181
# print('Processing remote component > {0}'.format(ref.value))
8282
remote_component = self._lookup_dict(owner, ref.path)
83-
root_components_dir = self._lookup_dict(self._resolved_remotes_components, ref.path_parent)
84-
component_name = ref.path.split("/")[-1]
83+
pointer_parent = ref.pointer.parent
84+
85+
if pointer_parent is not None:
86+
root_components_dir = self._lookup_dict(self._resolved_remotes_components, pointer_parent.value)
87+
component_name = ref.path.split("/")[-1]
8588

8689
if component_name == "SorTransparentContainer" or component_name == "sorTransparentContainer":
8790
print(ref.value)
@@ -118,7 +121,10 @@ def _transform_to_local_components(self, owner: SchemaData, ref: Reference) -> N
118121

119122
def _ensure_components_dir_exists(self, ref: Reference) -> None:
120123
cursor = self._resolved_remotes_components
121-
for key in ref.path_parent.split("/"):
124+
pointer_dir = ref.pointer.parent
125+
assert pointer_dir is not None
126+
127+
for key in pointer_dir.value.split("/"): # noqa
122128
if key == "":
123129
continue
124130

0 commit comments

Comments
 (0)