Skip to content

Commit

Permalink
Merge pull request #166 from SethMMorton/fix-windows-os-sorted
Browse files Browse the repository at this point in the history
Disable extension splitting on Windows for os_sorted
  • Loading branch information
SethMMorton committed Jun 20, 2023
2 parents 51b2fd3 + b7ad1cb commit 9d2eba8
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 22 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,13 @@ Unreleased
- The changelog now only explictly exists in the repository
(issue [#162](https://github.com/SethMMorton/natsort/issues/162))

### Fixed

- Inputs with spaces near adjascent to the extension are now sorted
correctly for `os_sorted` on Windows (issues
[#165](https://github.com/SethMMorton/natsort/issues/165) and
[#166](https://github.com/SethMMorton/natsort/pull/166))

[8.3.1] - 2023-03-01
---

Expand Down
6 changes: 3 additions & 3 deletions natsort/natsort.py
Original file line number Diff line number Diff line change
Expand Up @@ -670,13 +670,13 @@ def numeric_regex_chooser(alg: NSType) -> str:


def _split_apply(
v: Any, key: Optional[Callable[[T], NatsortInType]] = None
v: Any, key: Optional[Callable[[T], NatsortInType]] = None, treat_base: bool = True
) -> Iterator[str]:
if key is not None:
v = key(v)
if not isinstance(v, (str, PurePath)):
v = str(v)
return utils.path_splitter(v)
return utils.path_splitter(v, treat_base=treat_base)


# Choose the implementation based on the host OS
Expand All @@ -694,7 +694,7 @@ def os_sort_keygen(
) -> Callable[[Any], NatsortOutType]:
return cast(
Callable[[Any], NatsortOutType],
lambda x: tuple(map(_winsort_key, _split_apply(x, key))),
lambda x: tuple(map(_winsort_key, _split_apply(x, key, treat_base=False))),
)

else:
Expand Down
27 changes: 16 additions & 11 deletions natsort/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -876,7 +876,7 @@ def do_decoding(s: Any, encoding: str) -> Any:

# noinspection PyIncorrectDocstring
def path_splitter(
s: PathArg, _d_match: MatchFn = re.compile(r"\.\d").match
s: PathArg, treat_base: bool = True, _d_match: MatchFn = re.compile(r"\.\d").match
) -> Iterator[str]:
"""
Split a string into its path components.
Expand All @@ -886,6 +886,10 @@ def path_splitter(
Parameters
----------
s : str | pathlib.Path
treat_base: bool, optional
If True, treat the base of component of the file path as
special and split off extensions. If False, do not do this.
The default is True.
Returns
-------
Expand All @@ -909,17 +913,18 @@ def path_splitter(
path_parts = []
base = str(s)

# Now, split off the file extensions until
# - we reach a decimal number at the beginning of the suffix
# - more than two suffixes have been seen
# - a suffix is more than five characters (including leading ".")
# - there are no more extensions
suffixes = []
for i, suffix in enumerate(reversed(PurePath(base).suffixes)):
if _d_match(suffix) or i > 1 or len(suffix) > 5:
break
suffixes.append(suffix)
suffixes.reverse()
if treat_base:
# Now, split off the file extensions until
# - we reach a decimal number at the beginning of the suffix
# - more than two suffixes have been seen
# - a suffix is more than five characters (including leading ".")
# - there are no more extensions
for i, suffix in enumerate(reversed(PurePath(base).suffixes)):
if _d_match(suffix) or i > 1 or len(suffix) > 5:
break
suffixes.append(suffix)
suffixes.reverse()

# Remove the suffixes from the base component
base = base.replace("".join(suffixes), "")
Expand Down
26 changes: 18 additions & 8 deletions tests/test_os_sorted.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,24 @@ def test_os_sorted_compound() -> None:
"/p/Folder (1)/file.tar.gz",
"/p/Folder/file.x1.10.tar.gz",
]
expected = [
"/p/Folder/file.x1.9.tar.gz",
"/p/Folder/file.x1.10.tar.gz",
"/p/Folder (1)/file.tar.gz",
"/p/Folder (1)/file (1).tar.gz",
"/p/Folder (2)/file.tar.gz",
"/p/Folder (10)/file.tar.gz",
]
if platform.system() == "Windows":
expected = [
"/p/Folder/file.x1.9.tar.gz",
"/p/Folder/file.x1.10.tar.gz",
"/p/Folder (1)/file (1).tar.gz",
"/p/Folder (1)/file.tar.gz",
"/p/Folder (2)/file.tar.gz",
"/p/Folder (10)/file.tar.gz",
]
else:
expected = [
"/p/Folder/file.x1.9.tar.gz",
"/p/Folder/file.x1.10.tar.gz",
"/p/Folder (1)/file.tar.gz",
"/p/Folder (1)/file (1).tar.gz",
"/p/Folder (2)/file.tar.gz",
"/p/Folder (10)/file.tar.gz",
]
result = natsort.os_sorted(given)
assert result == expected

Expand Down

0 comments on commit 9d2eba8

Please sign in to comment.