Skip to content

Commit 4cad083

Browse files
committed
adjust glob handling to allow posix and OS separators
fixes #320
1 parent e26959d commit 4cad083

File tree

3 files changed

+34
-11
lines changed

3 files changed

+34
-11
lines changed

CHANGELOG.md

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

28+
- Patterns provided to `--exclude` allow NT-style paths on Windows. (#320)
29+
2830
### Removed
2931

3032
- Python 3.7 support.

rsconnect/models.py

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

5-
import os
5+
import pathlib
66
import re
77

88
import fnmatch
@@ -163,6 +163,7 @@ class GlobMatcher(object):
163163
"""
164164

165165
def __init__(self, pattern):
166+
pattern = pathlib.PurePath(pattern).as_posix()
166167
if pattern.endswith("/**/*"):
167168
# Note: the index used here makes sure the pattern has a trailing
168169
# slash. We want that.
@@ -185,7 +186,8 @@ def _to_parts_list(pattern):
185186
:return: a list of pattern pieces and the index of the special '**' pattern.
186187
The index will be None if `**` is never found.
187188
"""
188-
parts = pattern.split(os.path.sep)
189+
# Incoming pattern is ALWAYS a Posix-style path.
190+
parts = pattern.split("/")
189191
depth_wildcard_index = None
190192
for index, name in enumerate(parts):
191193
if name == "**":
@@ -197,10 +199,12 @@ def _to_parts_list(pattern):
197199
return parts, depth_wildcard_index
198200

199201
def _match_with_starts_with(self, path):
202+
path = pathlib.PurePath(path).as_posix()
200203
return path.startswith(self._pattern)
201204

202205
def _match_with_list_parts(self, path):
203-
parts = path.split(os.path.sep)
206+
path = pathlib.PurePath(path).as_posix()
207+
parts = path.split("/")
204208

205209
def items_match(i1, i2):
206210
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)