Skip to content

Commit afd0eba

Browse files
committed
adjust glob handling to allow posix and OS separators
fixes #320
1 parent cdf80d3 commit afd0eba

File tree

3 files changed

+34
-10
lines changed

3 files changed

+34
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2121
- Quarto content automatically ignores `name.html` and `name_files` when
2222
`name.md`, `name.ipynb`, `name.Rmd`, or `name.qmd` is an input. (#553)
2323

24+
- Patterns provided to `--exclude` allow NT-style paths on Windows. (#320)
25+
2426
## [1.22.0] - 2024-01-23
2527

2628
### Added

rsconnect/models.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
"""
44

55
import os
6+
import pathlib
67
import re
78

89
import fnmatch
@@ -163,6 +164,7 @@ class GlobMatcher(object):
163164
"""
164165

165166
def __init__(self, pattern):
167+
pattern = pathlib.PurePath(pattern).as_posix()
166168
if pattern.endswith("/**/*"):
167169
# Note: the index used here makes sure the pattern has a trailing
168170
# slash. We want that.
@@ -185,7 +187,8 @@ def _to_parts_list(pattern):
185187
:return: a list of pattern pieces and the index of the special '**' pattern.
186188
The index will be None if `**` is never found.
187189
"""
188-
parts = pattern.split(os.path.sep)
190+
# Incoming pattern is ALWAYS a Posix-style path.
191+
parts = pattern.split("/")
189192
depth_wildcard_index = None
190193
for index, name in enumerate(parts):
191194
if name == "**":
@@ -197,10 +200,12 @@ def _to_parts_list(pattern):
197200
return parts, depth_wildcard_index
198201

199202
def _match_with_starts_with(self, path):
203+
path = pathlib.PurePath(path).as_posix()
200204
return path.startswith(self._pattern)
201205

202206
def _match_with_list_parts(self, path):
203-
parts = path.split(os.path.sep)
207+
path = pathlib.PurePath(path).as_posix()
208+
parts = path.split("/")
204209

205210
def items_match(i1, i2):
206211
if i2 >= len(parts):

tests/test_models.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,30 @@ def test_glob_matcher(self):
8888
cases = [
8989
("dir", "dir", True),
9090
("dir", "file", False),
91+
("*.txt", "file.txt", True),
92+
("*.txt", "file.csv", False),
93+
9194
("dir", "dir/file", False),
95+
("dir/*", "file", False),
96+
("dir/*", "dir/file", True),
97+
("dir/*", "dir/sub/file", False),
9298
("dir/*.txt", "file", False),
9399
("dir/*.txt", "dir/file", False),
94100
("dir/*.txt", "dir/file.txt", True),
95101
("dir/*.txt", "dir/.txt", True),
102+
103+
# recursive wildcard pattern using "/" (input paths using OS separator)
104+
("dir/**/*", "dirfile.txt", False),
105+
("dir/**/*", os.path.join("dirother", "a.txt"), False),
106+
("dir/**/*", os.path.join("dir", "a.txt"), True),
107+
("dir/**/*", os.path.join("dir", "sub", "a.txt"), True),
108+
("dir/**/*.txt", os.path.join("dirother", "a.txt"), False),
109+
("dir/**/*.txt", os.path.join("dir", "a.txt"), True),
110+
("dir/**/*.txt", os.path.join("dir", "a.csv"), False),
111+
("dir/**/*.txt", os.path.join("dir", "sub", "a.txt"), True),
112+
("dir/**/*.txt", os.path.join("dir", "sub", "a.csv"), False),
113+
114+
# recursive wildcards using OS path separator.
96115
(os.path.join("dir", "**", "*.txt"), os.path.join("dir", "a.txt"), True),
97116
(os.path.join("dir", "**", "*.txt"), os.path.join("dir", "sub", "a.txt"), True),
98117
(os.path.join("dir", "**", "*.txt"), os.path.join("dir", "sub", "sub", "a.txt"), True),
@@ -103,15 +122,13 @@ def test_glob_matcher(self):
103122
(os.path.join("dir", "**", "*"), os.path.join("dir", "abc"), True),
104123
]
105124

106-
for case in cases:
107-
matcher = GlobMatcher(case[0])
108-
msg = "Pattern: %s, Path: %s, expected: %s, got: %s" % (
109-
case[0],
110-
case[1],
111-
case[2],
112-
not case[2],
125+
for pattern, path, expected in cases:
126+
matcher = GlobMatcher(pattern)
127+
self.assertEqual(
128+
matcher.matches(path),
129+
expected,
130+
f"pattern: {pattern}; path: {path}; expected: {expected}",
113131
)
114-
self.assertEqual(matcher.matches(case[1]), case[2], msg)
115132

116133
with self.assertRaises(ValueError):
117134
GlobMatcher(os.path.join(".", "blah", "**", "blah", "**", "*.txt"))

0 commit comments

Comments
 (0)