Skip to content

Commit

Permalink
Fix the detection logic of the reservation words for the file name on…
Browse files Browse the repository at this point in the history
… Windows: #57

Signed-off-by: Tsuyoshi Hombashi <tsuyoshi.hombashi@gmail.com>
  • Loading branch information
thombashi committed Jan 1, 2025
1 parent 62dc222 commit d94185a
Show file tree
Hide file tree
Showing 4 changed files with 43 additions and 7 deletions.
15 changes: 11 additions & 4 deletions pathvalidate/_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@

import abc
import os
import re
import sys
from collections.abc import Sequence
from typing import ClassVar, Optional
from typing import ClassVar, Final, Optional

from ._common import normalize_platform, unprintable_ascii_chars
from ._const import DEFAULT_MIN_LEN, Platform
Expand Down Expand Up @@ -181,6 +182,8 @@ def sanitize(self, value: PathType, replacement_text: str = "") -> PathType: #


class BaseValidator(AbstractValidator):
__RE_ROOT_NAME: Final = re.compile(r"([^\.]+)")

@property
def min_len(self) -> int:
return self._min_len
Expand Down Expand Up @@ -234,6 +237,10 @@ def _validate_max_len(self) -> None:
if self.min_len > self.max_len:
raise ValueError("min_len must be lower than max_len")

@staticmethod
def __extract_root_name(path: str) -> str:
return os.path.splitext(os.path.basename(path))[0]
@classmethod
def __extract_root_name(cls, path: str) -> str:
match = cls.__RE_ROOT_NAME.match(os.path.basename(path))
if match is None:
return ""

return match.group(1)
12 changes: 10 additions & 2 deletions pathvalidate/_filename.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,16 @@ def _get_sanitize_regexp(self) -> Pattern[str]:


class FileNameValidator(BaseValidator):
_WINDOWS_RESERVED_FILE_NAMES = ("CON", "PRN", "AUX", "CLOCK$", "NUL") + tuple(
f"{name:s}{num:d}" for name, num in itertools.product(("COM", "LPT"), range(1, 10))
_WINDOWS_RESERVED_FILE_NAMES = (
("CON", "PRN", "AUX", "CLOCK$", "NUL")
+ tuple(f"{name:s}{num:d}" for name, num in itertools.product(("COM", "LPT"), range(0, 10)))
+ tuple(
f"{name:s}{ssd:s}"
for name, ssd in itertools.product(
("COM", "LPT"),
("\N{SUPERSCRIPT ONE}", "\N{SUPERSCRIPT TWO}", "\N{SUPERSCRIPT THREE}"),
)
)
)
_MACOS_RESERVED_FILE_NAMES = (":",)

Expand Down
9 changes: 8 additions & 1 deletion test/_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,14 @@
"clock$",
"NUL",
"nul",
] + [f"{name:s}{num:d}" for name, num in product(["COM", "com", "LPT", "lpt"], range(1, 10))]
] + [
f"{name:s}{num}"
for name, num in product(
["COM", "com", "LPT", "lpt"],
list(range(0, 10))
+ ["\N{SUPERSCRIPT ONE}", "\N{SUPERSCRIPT TWO}", "\N{SUPERSCRIPT THREE}"],
)
]
NTFS_RESERVED_FILE_NAMES = [
"$Mft",
"$MftMirr",
Expand Down
14 changes: 14 additions & 0 deletions test/test_filename.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class Test_FileNameValidator:
(
"AUX",
"CLOCK$",
"COM0",
"COM1",
"COM2",
"COM3",
Expand All @@ -97,7 +98,11 @@ class Test_FileNameValidator:
"COM7",
"COM8",
"COM9",
"COM²",
"COM³",
"COM¹",
"CON",
"LPT0",
"LPT1",
"LPT2",
"LPT3",
Expand All @@ -107,6 +112,9 @@ class Test_FileNameValidator:
"LPT7",
"LPT8",
"LPT9",
"LPT²",
"LPT³",
"LPT¹",
"NUL",
"PRN",
),
Expand Down Expand Up @@ -362,6 +370,12 @@ def test_exception_win_invalid_char(self, value, platform):
WIN_RESERVED_FILE_NAMES, ["windows", "universal"]
)
]
+ [
[f"{reserved_keyword}.tar.gz", platform, ValidationError]
for reserved_keyword, platform in product(
WIN_RESERVED_FILE_NAMES, ["windows", "universal"]
)
]
+ [
[reserved_keyword, platform, None]
for reserved_keyword, platform in product([".", ".."], ["posix", "linux", "macos"])
Expand Down

0 comments on commit d94185a

Please sign in to comment.