Skip to content

Commit f166869

Browse files
committed
fixup! amend! fixup! ModuleRouter: support paths in BASE
1 parent f975308 commit f166869

File tree

2 files changed

+34
-29
lines changed

2 files changed

+34
-29
lines changed

src/satosa/util.py

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import logging
66
import random
77
import string
8+
import typing
89

910

1011
logger = logging.getLogger(__name__)
@@ -91,27 +92,23 @@ def rndstr(size=16, alphabet=""):
9192
return type(alphabet)().join(rng.choice(alphabet) for _ in range(size))
9293

9394

94-
def join_paths(base, *paths):
95+
def join_paths(*paths, sep: typing.Optional[str] = None) -> str:
9596
"""
96-
Joins strings with a "/" separator, like they were path components, but
97-
tries to avoid adding an unnecessary separator. Note that the contents of
98-
the strings are not sanitized in any way. If any of the components begins or
99-
ends with a "/", the separator is not inserted, and any number of empty
100-
strings at the beginning would not add a leading slash. Any number of empty
101-
strings at the end only add a single trailing slash.
102-
103-
Raises TypeError if any of the components are not strings.
97+
Joins strings with a separator like they were path components. The
98+
separator is stripped off from all path components, except for the
99+
beginning of the first component. Empty (or falsy) components are skipped.
100+
Note that the components are not sanitized in any other way.
101+
102+
Raises TypeError if any of the components are not strings (or empty).
104103
"""
105-
sep = "/"
104+
sep = sep or "/"
105+
leading = ""
106+
if paths and paths[0] and paths[0][0] == sep:
107+
leading = sep
106108

107-
path = base
108109
try:
109-
for p in paths:
110-
if not path or path.endswith(sep) or p.startswith(sep):
111-
path += p
112-
else:
113-
path += sep + p
110+
return leading + sep.join(
111+
[path.strip(sep) for path in filter(lambda p: p and p.strip(sep), paths)]
112+
)
114113
except (AttributeError, TypeError) as err:
115114
raise TypeError("Arguments must be strings") from err
116-
117-
return path

tests/satosa/test_util.py

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,27 @@
1212
(["foo", "/bar"], "foo/bar"),
1313
(["/foo", "baz", "/bar"], "/foo/baz/bar"),
1414
(["", "foo", "bar"], "foo/bar"),
15-
(["", "/foo", "bar"], "/foo/bar"),
16-
(["", "/foo/", "bar"], "/foo/bar"),
17-
(["", "", "", "/foo", "bar"], "/foo/bar"),
18-
(["", "", "/foo/", "", "bar"], "/foo/bar"),
19-
(["", "", "/foo/", "", "", "bar/"], "/foo/bar/"),
20-
(["/foo", ""], "/foo/"),
21-
(["/foo", "", "", ""], "/foo/"),
22-
(["/foo//", "bar"], "/foo//bar"),
15+
(["", "/foo", "bar"], "foo/bar"),
16+
(["", "/foo/", "bar"], "foo/bar"),
17+
(["", "", "", "/foo", "bar"], "foo/bar"),
18+
(["", "", "/foo/", "", "bar"], "foo/bar"),
19+
(["", "", "/foo/", "", "", "bar/"], "foo/bar"),
20+
(["/foo", ""], "/foo"),
21+
(["/foo", "", "", ""], "/foo"),
22+
(["/foo//", "bar"], "/foo/bar"),
2323
(["foo"], "foo"),
2424
([""], ""),
2525
(["", ""], ""),
2626
(["'not ", "sanitized'\0/; rm -rf *"], "'not /sanitized'\0/; rm -rf *"),
27-
(["foo/", "/bar"], "foo//bar"),
28-
(["foo", "", "/bar"], "foo//bar"),
27+
(["foo/", "/bar"], "foo/bar"),
28+
(["foo", "", "/bar"], "foo/bar"),
2929
([b"foo", "bar"], TypeError),
3030
(["foo", b"bar"], TypeError),
31-
([None, "foo"], TypeError),
31+
([None, "foo"], "foo"),
32+
(["foo", [], "bar"], "foo/bar"),
33+
(["foo", ["baz"], "bar"], TypeError),
34+
(["/", "foo", "bar"], "/foo/bar"),
35+
(["///foo", "bar"], "/foo/bar"),
3236
],
3337
)
3438
def test_join_paths(args, expected):
@@ -37,3 +41,7 @@ def test_join_paths(args, expected):
3741
else:
3842
with pytest.raises(expected):
3943
_ = join_paths(*args)
44+
45+
46+
def test_join_paths_with_separator():
47+
assert join_paths("this", "is", "not", "a", "path", sep="|") == "this|is|not|a|path"

0 commit comments

Comments
 (0)