Skip to content

Commit

Permalink
Merge pull request #185 from berquist/python-3.13-reserved-paths
Browse files Browse the repository at this point in the history
Update reserved paths based on Python 3.13 Windows changes
  • Loading branch information
dragly authored Jun 19, 2024
2 parents 4828336 + 7dcbf4c commit e04600a
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 10 deletions.
34 changes: 25 additions & 9 deletions exdir/core/validation.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,25 @@
from enum import Enum
import os
try:
import pathlib
except ImportError as e:
try:
import pathlib2 as pathlib
except ImportError:
raise e
import sys
from pathlib import Path, WindowsPath
from unicodedata import category
from . import constants as exob

# `ntpath.isreserved` forbids ASCII control characters
# (https://github.com/python/cpython/blob/7c016deae62308dd1b4e2767fc6abf04857c7843/Lib/ntpath.py#L325)
# while `pathlib.PureWindowsPath.is_reserved` does not, so it is easiest to
# forbid all control characters.
if sys.version_info.minor < 13:
from pathlib import PureWindowsPath

def _is_reserved(path):
return PureWindowsPath(path).is_reserved() or _contains_control_character(path)
else:
from ntpath import isreserved

def _is_reserved(path):
return isreserved(path) or _contains_control_character(path)

VALID_CHARACTERS = ("abcdefghijklmnopqrstuvwxyz1234567890_-.")


Expand All @@ -18,6 +29,11 @@ class NamingRule(Enum):
THOROUGH = 3
NONE = 4


def _contains_control_character(s):
return any(ch for ch in s if category(ch)[0] == "C")


def _assert_unique(parent_path, name):
try:
name_str = str(name)
Expand Down Expand Up @@ -58,7 +74,7 @@ def _assert_nonreserved(name):
"Name cannot be '{}' because it is a reserved filename in Exdir.".format(name_str)
)

if pathlib.PureWindowsPath(name_str).is_reserved():
if _is_reserved(name_str):
raise NameError(
"Name cannot be '{}' because it is a reserved filename in Windows.".format(name_str)
)
Expand Down Expand Up @@ -102,7 +118,7 @@ def thorough(parent_path, name):
name_lower = name_str.lower()
_assert_valid_characters(name_lower)

if isinstance(pathlib.Path(parent_path), pathlib.WindowsPath):
if isinstance(Path(parent_path), WindowsPath):
# use _assert_unique if we're already on Windows, because it is much faster
# than the test below
_assert_unique(parent_path, name)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_help_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ def test_assert_valid_name_minimal(setup_teardown_folder):

exob._assert_valid_name("A", f)

exob._assert_valid_name("\n", f)
with pytest.raises(NameError):
exob._assert_valid_name("\n", f)

exob._assert_valid_name(six.unichr(0x4500), f)

Expand Down

0 comments on commit e04600a

Please sign in to comment.