[path] support multiple characters in path-restrict objects (#1707)

This commit is contained in:
Mike Fährmann
2025-06-12 12:40:21 +02:00
parent 16fc5e0d68
commit 5b60c66e0f
2 changed files with 23 additions and 5 deletions

View File

@@ -207,11 +207,12 @@ Default
``"auto"`` ``"auto"``
Example Example
* ``"/!? (){}"`` * ``"/!? (){}"``
* ``{" ": "_", "/": "-", "|": "-", ":": "_-_", "*": "_+_"}`` * ``{"/": "_", "+": "_+_", "({[": "(", "]})": ")", "a-z": "*"}``
Description Description
| A string of characters to be replaced with the value of | A ``string`` of characters to be replaced with the value of
`path-replace <extractor.*.path-replace_>`__ `path-replace <extractor.*.path-replace_>`__
| or an object mapping invalid/unwanted characters to their replacements | or an ``object`` mapping invalid/unwanted characters, character sets,
or character ranges to their replacements
| for generated path segment names. | for generated path segment names.
Special values: Special values:

View File

@@ -134,11 +134,14 @@ class PathFormat():
basedir = self.clean_path(basedir) basedir = self.clean_path(basedir)
self.basedirectory = basedir self.basedirectory = basedir
@staticmethod def _build_cleanfunc(self, chars, repl):
def _build_cleanfunc(chars, repl):
if not chars: if not chars:
return util.identity return util.identity
elif isinstance(chars, dict): elif isinstance(chars, dict):
if 0 not in chars:
chars = self._process_repl_dict(chars)
chars[0] = None
def func(x, table=str.maketrans(chars)): def func(x, table=str.maketrans(chars)):
return x.translate(table) return x.translate(table)
elif len(chars) == 1: elif len(chars) == 1:
@@ -149,6 +152,20 @@ class PathFormat():
re.compile("[" + chars + "]").sub, repl) re.compile("[" + chars + "]").sub, repl)
return func return func
def _process_repl_dict(self, chars):
# can't modify 'chars' while *directly* iterating over its keys
for char in [c for c in chars if len(c) > 1]:
if len(char) == 3 and char[1] == "-":
citer = range(ord(char[0]), ord(char[2])+1)
else:
citer = char
repl = chars.pop(char)
for c in citer:
chars[c] = repl
return chars
def open(self, mode="wb"): def open(self, mode="wb"):
"""Open file and return a corresponding file object""" """Open file and return a corresponding file object"""
try: try: