Skip to content

Commit 591be1d

Browse files
committed
Change constructor arguments of FileNameSanitizer and FilePathSanitizer classes
1 parent b069dea commit 591be1d

File tree

4 files changed

+86
-50
lines changed

4 files changed

+86
-50
lines changed

pathvalidate/_base.py

Lines changed: 42 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,12 @@ def platform(self) -> Platform:
3030
def reserved_keywords(self) -> Tuple[str, ...]:
3131
return tuple()
3232

33-
@property
34-
def min_len(self) -> int:
35-
return self._min_len
36-
3733
@property
3834
def max_len(self) -> int:
3935
return self._max_len
4036

4137
def __init__(
4238
self,
43-
min_len: int,
4439
max_len: int,
4540
fs_encoding: Optional[str],
4641
check_reserved: bool,
@@ -50,10 +45,6 @@ def __init__(
5045
self.__platform = normalize_platform(platform)
5146
self._check_reserved = check_reserved
5247

53-
if min_len <= 0:
54-
min_len = DEFAULT_MIN_LEN
55-
self._min_len = max(min_len, 1)
56-
5748
if platform_max_len is None:
5849
platform_max_len = self._get_default_max_path_len()
5950

@@ -69,8 +60,6 @@ def __init__(
6960
else:
7061
self._fs_encoding = sys.getfilesystemencoding()
7162

72-
self._validate_max_len()
73-
7463
def _is_posix(self) -> bool:
7564
return self.platform == Platform.POSIX
7665

@@ -95,13 +84,6 @@ def _is_macos(self, include_universal: bool = False) -> bool:
9584

9685
return self.platform == Platform.MACOS
9786

98-
def _validate_max_len(self) -> None:
99-
if self.max_len < 1:
100-
raise ValueError("max_len must be greater or equal to one")
101-
102-
if self.min_len > self.max_len:
103-
raise ValueError("min_len must be lower than max_len")
104-
10587
def _get_default_max_path_len(self) -> int:
10688
if self._is_linux():
10789
return 4096
@@ -116,6 +98,10 @@ def _get_default_max_path_len(self) -> int:
11698

11799

118100
class AbstractValidator(BaseFile, metaclass=abc.ABCMeta):
101+
@abc.abstractproperty
102+
def min_len(self) -> int: # pragma: no cover
103+
pass
104+
119105
@abc.abstractmethod
120106
def validate(self, value: PathType) -> None: # pragma: no cover
121107
pass
@@ -135,17 +121,16 @@ def _is_reserved_keyword(self, value: str) -> bool:
135121
class AbstractSanitizer(BaseFile, metaclass=abc.ABCMeta):
136122
def __init__(
137123
self,
138-
min_len: int,
124+
validator: AbstractValidator,
139125
max_len: int,
140126
fs_encoding: Optional[str],
141127
check_reserved: bool,
128+
validate_after_sanitize: bool,
142129
null_value_handler: Optional[NullValueHandler] = None,
143130
platform_max_len: Optional[int] = None,
144131
platform: Optional[PlatformType] = None,
145-
validate_after_sanitize: bool = False,
146132
) -> None:
147133
super().__init__(
148-
min_len=min_len,
149134
max_len=max_len,
150135
fs_encoding=fs_encoding,
151136
check_reserved=check_reserved,
@@ -159,12 +144,41 @@ def __init__(
159144

160145
self._validate_after_sanitize = validate_after_sanitize
161146

147+
self._validator = validator
148+
162149
@abc.abstractmethod
163150
def sanitize(self, value: PathType, replacement_text: str = "") -> PathType: # pragma: no cover
164151
pass
165152

166153

167154
class BaseValidator(AbstractValidator):
155+
@property
156+
def min_len(self) -> int:
157+
return self._min_len
158+
159+
def __init__(
160+
self,
161+
min_len: int,
162+
max_len: int,
163+
fs_encoding: Optional[str],
164+
check_reserved: bool,
165+
platform_max_len: Optional[int] = None,
166+
platform: Optional[PlatformType] = None,
167+
) -> None:
168+
if min_len <= 0:
169+
min_len = DEFAULT_MIN_LEN
170+
self._min_len = max(min_len, 1)
171+
172+
super().__init__(
173+
max_len=max_len,
174+
fs_encoding=fs_encoding,
175+
check_reserved=check_reserved,
176+
platform_max_len=platform_max_len,
177+
platform=platform,
178+
)
179+
180+
self._validate_max_len()
181+
168182
def _validate_reserved_keywords(self, name: str) -> None:
169183
if not self._check_reserved:
170184
return
@@ -178,6 +192,13 @@ def _validate_reserved_keywords(self, name: str) -> None:
178192
platform=self.platform,
179193
)
180194

195+
def _validate_max_len(self) -> None:
196+
if self.max_len < 1:
197+
raise ValueError("max_len must be greater or equal to one")
198+
199+
if self.min_len > self.max_len:
200+
raise ValueError("min_len must be lower than max_len")
201+
181202
@staticmethod
182203
def __extract_root_name(path: str) -> str:
183204
return os.path.splitext(os.path.basename(path))[0]

pathvalidate/_filename.py

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pathlib import Path
1010
from typing import Optional, Pattern, Tuple
1111

12-
from ._base import AbstractSanitizer, BaseFile, BaseValidator
12+
from ._base import AbstractSanitizer, AbstractValidator, BaseFile, BaseValidator
1313
from ._common import findall_to_str, to_str, validate_pathtype
1414
from ._const import DEFAULT_MIN_LEN, INVALID_CHAR_ERR_MSG_TMPL, Platform
1515
from ._types import PathType, PlatformType
@@ -27,32 +27,37 @@
2727
class FileNameSanitizer(AbstractSanitizer):
2828
def __init__(
2929
self,
30-
min_len: int = DEFAULT_MIN_LEN,
3130
max_len: int = _DEFAULT_MAX_FILENAME_LEN,
3231
fs_encoding: Optional[str] = None,
3332
platform: Optional[PlatformType] = None,
3433
check_reserved: bool = True,
3534
null_value_handler: Optional[NullValueHandler] = None,
3635
validate_after_sanitize: bool = False,
36+
validator: Optional[AbstractValidator] = None,
3737
) -> None:
38+
if validator:
39+
fname_validator = validator
40+
else:
41+
fname_validator = FileNameValidator(
42+
min_len=DEFAULT_MIN_LEN,
43+
max_len=max_len,
44+
fs_encoding=fs_encoding,
45+
check_reserved=check_reserved,
46+
platform=platform,
47+
)
48+
3849
super().__init__(
39-
min_len=min_len,
4050
max_len=max_len,
4151
fs_encoding=fs_encoding,
4252
check_reserved=check_reserved,
4353
null_value_handler=null_value_handler,
4454
platform_max_len=_DEFAULT_MAX_FILENAME_LEN,
4555
platform=platform,
4656
validate_after_sanitize=validate_after_sanitize,
57+
validator=fname_validator,
4758
)
4859

4960
self._sanitize_regexp = self._get_sanitize_regexp()
50-
self.__validator = FileNameValidator(
51-
min_len=self.min_len,
52-
max_len=self.max_len,
53-
check_reserved=check_reserved,
54-
platform=self.platform,
55-
)
5661

5762
def sanitize(self, value: PathType, replacement_text: str = "") -> PathType:
5863
try:
@@ -69,7 +74,7 @@ def sanitize(self, value: PathType, replacement_text: str = "") -> PathType:
6974
sanitized_filename = sanitized_filename[: self.max_len]
7075

7176
try:
72-
self.__validator.validate(sanitized_filename)
77+
self._validator.validate(sanitized_filename)
7378
except ValidationError as e:
7479
if e.reason == ErrorReason.RESERVED_NAME and e.reusable_name is False:
7580
sanitized_filename = re.sub(
@@ -90,7 +95,7 @@ def sanitize(self, value: PathType, replacement_text: str = "") -> PathType:
9095

9196
if self._validate_after_sanitize:
9297
try:
93-
self.__validator.validate(sanitized_filename)
98+
self._validator.validate(sanitized_filename)
9499
except ValidationError as e:
95100
raise ValidationError(
96101
description=str(e),

pathvalidate/_filepath.py

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
from pathlib import Path
1010
from typing import List, Optional, Pattern, Tuple
1111

12-
from ._base import AbstractSanitizer, BaseFile, BaseValidator
12+
from ._base import AbstractSanitizer, AbstractValidator, BaseFile, BaseValidator
1313
from ._common import findall_to_str, to_str, validate_pathtype
1414
from ._const import _NTFS_RESERVED_FILE_NAMES, DEFAULT_MIN_LEN, INVALID_CHAR_ERR_MSG_TMPL, Platform
1515
from ._filename import FileNameSanitizer, FileNameValidator
@@ -25,36 +25,41 @@
2525
class FilePathSanitizer(AbstractSanitizer):
2626
def __init__(
2727
self,
28-
min_len: int = DEFAULT_MIN_LEN,
2928
max_len: int = -1,
3029
fs_encoding: Optional[str] = None,
3130
platform: Optional[PlatformType] = None,
3231
check_reserved: bool = True,
3332
null_value_handler: Optional[NullValueHandler] = None,
3433
normalize: bool = True,
3534
validate_after_sanitize: bool = False,
35+
validator: Optional[AbstractValidator] = None,
3636
) -> None:
37+
if validator:
38+
fpath_validator = validator
39+
else:
40+
fpath_validator = FilePathValidator(
41+
min_len=DEFAULT_MIN_LEN,
42+
max_len=max_len,
43+
fs_encoding=fs_encoding,
44+
check_reserved=check_reserved,
45+
platform=platform,
46+
)
3747
super().__init__(
38-
min_len=min_len,
3948
max_len=max_len,
4049
fs_encoding=fs_encoding,
4150
check_reserved=check_reserved,
51+
validator=fpath_validator,
4252
null_value_handler=null_value_handler,
4353
platform=platform,
4454
validate_after_sanitize=validate_after_sanitize,
4555
)
4656

4757
self._sanitize_regexp = self._get_sanitize_regexp()
48-
self.__fpath_validator = FilePathValidator(
49-
min_len=self.min_len,
50-
max_len=self.max_len,
51-
check_reserved=check_reserved,
52-
platform=self.platform,
53-
)
5458
self.__fname_sanitizer = FileNameSanitizer(
55-
min_len=self.min_len,
5659
max_len=self.max_len,
60+
fs_encoding=fs_encoding,
5761
check_reserved=check_reserved,
62+
null_value_handler=null_value_handler,
5863
platform=self.platform,
5964
validate_after_sanitize=validate_after_sanitize,
6065
)
@@ -76,8 +81,6 @@ def sanitize(self, value: PathType, replacement_text: str = "") -> PathType:
7681
return self._null_value_handler(e)
7782
raise
7883

79-
self.__fpath_validator.validate_abspath(value)
80-
8184
unicode_filepath = to_str(value)
8285

8386
drive, unicode_filepath = self.__split_drive(unicode_filepath)
@@ -106,13 +109,13 @@ def sanitize(self, value: PathType, replacement_text: str = "") -> PathType:
106109

107110
sanitized_path = self.__get_path_separator().join(sanitized_entries)
108111
try:
109-
self.__fpath_validator.validate(sanitized_path)
112+
self._validator.validate(sanitized_path)
110113
except ValidationError as e:
111114
if e.reason == ErrorReason.NULL_NAME:
112115
sanitized_path = self._null_value_handler(e)
113116

114117
if self._validate_after_sanitize:
115-
self.__fpath_validator.validate(sanitized_path)
118+
self._validator.validate(sanitized_path)
116119

117120
if isinstance(value, Path):
118121
return Path(sanitized_path)

test/test_filepath.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -794,12 +794,19 @@ def test_auto_platform_win(self, value, expected):
794794
],
795795
)
796796
def test_auto_platform_linux(self, value, expected):
797+
kwargs = {
798+
"platform": "auto",
799+
"validate_after_sanitize": True,
800+
}
801+
797802
if isinstance(expected, str):
798-
sanitized = sanitize_filepath(value, platform="auto")
803+
sanitized = sanitize_filepath(value, **kwargs)
799804
assert is_valid_filepath(sanitized, platform="auto")
800-
else:
801-
with pytest.raises(expected):
802-
sanitize_filepath(value, platform="auto")
805+
return
806+
807+
with pytest.raises(expected) as e:
808+
sanitize_filepath(value, **kwargs)
809+
assert e.value.reason == ErrorReason.MALFORMED_ABS_PATH
803810

804811
@pytest.mark.parametrize(
805812
["platform", "value"],

0 commit comments

Comments
 (0)