Skip to content

Commit

Permalink
fixes for case-insensitive file systems
Browse files Browse the repository at this point in the history
  • Loading branch information
berquist committed Jun 9, 2024
1 parent c040b6e commit bd2d43a
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 20 deletions.
14 changes: 12 additions & 2 deletions exdir/core/exdir_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,14 +115,24 @@ def __init__(self, directory, mode=None, allow_remove=False,
else:
self.io_mode = OpenMode.READ_WRITE

parent_path = pathlib.PurePosixPath("")
super().__init__(
root_directory=directory,
parent_path=pathlib.PurePosixPath(""),
parent_path=parent_path,
object_name="",
file=self
)

already_exists = directory.exists()
# If we have name validation, we need to check for uniqueness. The
# directory may exist but with a different case, in which case we
# don't want to say that is already exists so that it matches the
# correct checks for the requested mode.
if name_validation != validation.none:
already_exists = validation.path_already_exists_case_insensitive(
directory.parent, directory.name.lower()
)
else:
already_exists = directory.exists()
if already_exists:
if not exob.is_nonraw_object_directory(directory):
raise RuntimeError(
Expand Down
33 changes: 15 additions & 18 deletions exdir/core/validation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from enum import Enum
import os
import os.path
import sys
from pathlib import Path, WindowsPath
from tempfile import NamedTemporaryFile
from unicodedata import category
from . import constants as exob

Expand Down Expand Up @@ -36,13 +36,14 @@ def _contains_control_character(s):

def _assert_unique(parent_path, name):
try:
name_str = str(name)
name = str(name)
except UnicodeEncodeError:
name = name.encode('utf8')

if (parent_path / name).exists():
if path_already_exists_case_insensitive(parent_path, name.lower()):
raise RuntimeError(
"'{}' already exists in '{}'".format(name, parent_path)
"A directory with name (case independent) '{}' already exists "
" and cannot be made according to the naming rule 'thorough'.".format(name)
)


Expand Down Expand Up @@ -108,6 +109,7 @@ def strict(parent_path, name):
_assert_unique(parent_path, name)
_assert_valid_characters(name)


def thorough(parent_path, name):
_assert_nonempty(parent_path, name)
_assert_nonreserved(name)
Expand All @@ -117,21 +119,16 @@ def thorough(parent_path, name):
name_str = name.encode('utf8')
name_lower = name_str.lower()
_assert_valid_characters(name_lower)
_assert_unique(parent_path, name)


def none(parent_path, name):
pass

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)
return

def path_already_exists_case_insensitive(parent_path, name_lower):
# os.listdir is much faster here than os.walk or parent_path.iterdir
for item in os.listdir(str(parent_path)):
if name_lower == item.lower():
raise RuntimeError(
"A directory with name (case independent) '{}' already exists "
" and cannot be made according to the naming rule 'thorough'.".format(name)
)


def none(parent_path, name):
pass
return True
return False
1 change: 1 addition & 0 deletions tests/test_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ def test_validate_name_thorough(setup_teardown_folder):
f.close()

with pytest.raises(RuntimeError):
# breakpoint()
File(setup_teardown_folder[0] / "Test.exdir", name_validation=fv.thorough)
with pytest.raises(NameError):
File(setup_teardown_folder[0] / "tes#.exdir", name_validation=fv.thorough)
Expand Down

0 comments on commit bd2d43a

Please sign in to comment.