Skip to content
This repository was archived by the owner on Oct 3, 2020. It is now read-only.

Commit efad2a8

Browse files
hjacobsjbw
andauthored
Join URL path components without os.path/posixpath (#59)
* use posixpath for url * remove unused import * join URL path without os.path/posixpath Co-authored-by: jbw <[email protected]>
1 parent 2ad94b3 commit efad2a8

File tree

4 files changed

+47
-10
lines changed

4 files changed

+47
-10
lines changed

pykube/http.py

+5-6
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import datetime
55
import json
66
import os
7-
import posixpath
87
import shlex
98
import subprocess
109
from typing import Optional
@@ -23,7 +22,7 @@
2322
from urllib.parse import urlparse
2423

2524
from .exceptions import HTTPError
26-
from .utils import jsonpath_installed, jsonpath_parse
25+
from .utils import jsonpath_installed, jsonpath_parse, join_url_path
2726
from .config import KubeConfig
2827

2928
from . import __version__
@@ -139,7 +138,9 @@ def _setup_request_auth(self, config, request, kwargs):
139138
parsed_out = json.loads(output)
140139
token = parsed_out["status"]["token"]
141140
else:
142-
raise NotImplementedError(f'auth exec api version {api_version} not implemented')
141+
raise NotImplementedError(
142+
f"auth exec api version {api_version} not implemented"
143+
)
143144

144145
request.headers["Authorization"] = "Bearer {}".format(token)
145146
return None
@@ -286,10 +287,8 @@ def get_kwargs(self, **kwargs) -> dict:
286287
if namespace:
287288
bits.extend(["namespaces", namespace])
288289
url = kwargs.get("url", "")
289-
if url.startswith("/"):
290-
url = url[1:]
291290
bits.append(url)
292-
kwargs["url"] = self.url + posixpath.join(*bits)
291+
kwargs["url"] = self.url + join_url_path(*bits, join_empty=True)
293292
if "timeout" not in kwargs:
294293
# apply default HTTP timeout
295294
kwargs["timeout"] = self.timeout

pykube/objects.py

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import copy
22
import json
3-
import os.path as op
43
from inspect import getmro
54
from typing import Optional
65
from typing import Type
@@ -11,6 +10,7 @@
1110
from .mixins import ReplicatedMixin
1211
from .mixins import ScalableMixin
1312
from .query import Query
13+
from .utils import join_url_path
1414
from .utils import obj_merge
1515

1616

@@ -96,9 +96,8 @@ def api_kwargs(self, **kwargs):
9696
else:
9797
subresource = kwargs.pop("subresource", None) or ""
9898
operation = kwargs.pop("operation", "")
99-
kw["url"] = op.normpath(
100-
op.join(self.endpoint, self.name, subresource, operation)
101-
)
99+
kw["url"] = join_url_path(self.endpoint, self.name, subresource, operation)
100+
102101
params = kwargs.pop("params", None)
103102
if params is not None:
104103
query_string = urlencode(params)

pykube/utils.py

+25
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import re
2+
from typing import List
23

34
try:
45
from jsonpath_ng import parse as jsonpath
@@ -62,3 +63,27 @@ def repl(m):
6263
return jsonpath(path).find(obj)[0].value
6364

6465
return re.sub(r"(\{([^\}]*)\})", repl, template)
66+
67+
68+
def join_url_path(*components, join_empty: bool = False) -> str:
69+
"""Join given URL path components and return absolute path starting with '/'."""
70+
new_comps: List[str] = []
71+
for comp in components:
72+
comp = comp.strip("/")
73+
if comp in ("", "."):
74+
continue
75+
else:
76+
new_comps.append(comp)
77+
78+
if components and components[-1] == "" and join_empty:
79+
trailing_slash = True
80+
elif components and components[-1] == "/":
81+
trailing_slash = True
82+
else:
83+
trailing_slash = False
84+
85+
if trailing_slash:
86+
new_comps.append("")
87+
88+
path = "/".join(new_comps)
89+
return "/" + path

tests/test_utils.py

+14
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from pykube.utils import join_url_path
12
from pykube.utils import obj_merge
23

34

@@ -28,3 +29,16 @@ def test_obj_merge():
2829
assert obj_merge(
2930
{"a": {"b": [1, 2]}}, {"a": {"b": [3, 4, 5], "c": [1, 2]}}, is_strategic=False
3031
) == {"a": {"b": [1, 2]}}
32+
33+
34+
def test_join_url_path():
35+
assert join_url_path() == "/"
36+
assert join_url_path("") == "/"
37+
assert join_url_path("", "/") == "/"
38+
assert join_url_path("first", "") == "/first"
39+
assert join_url_path("first", "/") == "/first/"
40+
assert join_url_path("first", "second") == "/first/second"
41+
assert join_url_path("/first", "second/") == "/first/second"
42+
assert join_url_path("first", "second", "") == "/first/second"
43+
assert join_url_path("first", "/", "second", "", "") == "/first/second"
44+
assert join_url_path("/first", "second", "", join_empty=True) == "/first/second/"

0 commit comments

Comments
 (0)