Skip to content

Commit ac9cc36

Browse files
authored
Merge pull request #87 from JesseMckinzie/bug_fixes_1_10_24
bugfix: escaped parenthesis, space in directory name, and capturing directories with special characters
2 parents d7774d7 + e09b67e commit ac9cc36

File tree

5 files changed

+208
-10
lines changed

5 files changed

+208
-10
lines changed

src/filepattern/cpp/internal/filepattern.cpp

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ FilePatternObject::FilePatternObject(const string& path, const string& file_patt
1313
this->getPathFromPattern(path); // set path and file_pattern
1414

1515
try {
16-
this->recursive_iterator_ = fs::recursive_directory_iterator(this->getPath());
16+
this->recursive_iterator_ = fs::recursive_directory_iterator(fs::path(this->getPath()));
1717
this->recursive_ = true;
1818
this->setJustPath(true);
1919
} catch (const std::runtime_error& e) {
@@ -24,7 +24,8 @@ FilePatternObject::FilePatternObject(const string& path, const string& file_patt
2424
} else {
2525

2626
this->recursive_ = recursive; // Iterate over subdirectories
27-
27+
this->setCaptureDirectoryNames(false);
28+
2829
// check if filepattern contains directory capturing
2930
if (s::isPath(file_pattern)) {
3031
this->setCaptureDirectoryNames(true);
@@ -37,12 +38,12 @@ FilePatternObject::FilePatternObject(const string& path, const string& file_patt
3738

3839
this->setJustPath(false);
3940
this->setPath(path); // store path to target directory
40-
41+
4142
try {
42-
if(recursive){
43-
this->recursive_iterator_ = fs::recursive_directory_iterator(this->getPath());
43+
if(this->recursive_){
44+
this->recursive_iterator_ = fs::recursive_directory_iterator(fs::path(this->getPath()));
4445
} else{
45-
this->iterator_ = fs::directory_iterator(this->getPath()); // store iterator for target directory
46+
this->iterator_ = fs::directory_iterator(fs::path(this->getPath())); // store iterator for target directory
4647
}
4748
} catch (const std::runtime_error& e) {
4849
string error = "No directory found. Invalid path \"" + path + "\".";
@@ -115,9 +116,9 @@ void FilePatternObject::matchFilesMultDir(){
115116
} else {
116117
file = s::getBaseName(file_path);
117118
}
118-
119+
119120
if(regex_match(file, sm, pattern_regex)){
120-
121+
121122
if(this->getJustPath() || this->captureDirectoryNames()) {
122123
tup = getVariableMap(file_path, sm);
123124
} else {

src/filepattern/cpp/util/util.hpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,9 @@ namespace s {
7575
const std::unordered_set<char> escape_chars = {'*', '?', '^', '$', '(', ')', '[', ']', '|'};
7676

7777
for (auto i = 0; i < str.size()-1; ++i) {
78-
if (str[i] == '\\' &&
79-
std::find(std::begin(escape_chars), std::end(escape_chars), str[i+1]) == std::end(escape_chars)
78+
if ((str[i] == '\\' &&
79+
std::find(std::begin(escape_chars), std::end(escape_chars), str[i+1]) == std::end(escape_chars)) ||
80+
str[i] == '/'
8081
) {
8182
return true; // Contains a slash that is not proceeded by a character being escaped
8283
}

tests/test_filepattern.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ class TestFilePattern():
291291
test_generate_filepattern_data.generate_channel_data()
292292
test_generate_filepattern_data.generate_sorted_data()
293293
test_generate_filepattern_data.generate_bracket_data()
294+
test_generate_filepattern_data.generate_channel_data_sc()
295+
test_generate_filepattern_data.generate_channel_data_spaces()
294296

295297
def test_file_pattern(self):
296298

@@ -579,7 +581,54 @@ def test_recursive_directory_regex_fp(self):
579581
assert fp_data.test_recursive_directory_fp[i][0]["directory"] == result[i][0]["directory"]
580582
assert str(os.path.basename(fp_data.test_recursive_directory_fp[i][1][0])) == os.path.basename(result[i][1][0])
581583

584+
def test_recursive_directory_regex_special_character_fp(self):
585+
586+
path = self.root_directory + '/test_data/recursive_data_sc'
587+
588+
filepattern = '/(?P<directory>.*)/img_r{r:ddd}_c{c:ddd}.tif'
589+
590+
files = fp.FilePattern(path, filepattern, recursive=True)
591+
592+
result = []
593+
594+
for file in files():
595+
result.append(file)
582596

597+
# test that same number of files are returned
598+
assert len(result) == len(fp_data.test_recursive_directory_fp)
599+
600+
# test that each variable and path are equal for each file in list
601+
for i in range(len(fp_data.test_recursive_directory_fp)):
602+
print(result[i])
603+
assert fp_data.test_recursive_directory_fp[i][0]["r"] == result[i][0]["r"]
604+
assert fp_data.test_recursive_directory_fp[i][0]["c"] == result[i][0]["c"]
605+
assert fp_data.test_recursive_directory_fp[i][0]["directory"] + '_TEST' == result[i][0]["directory"]
606+
assert str(os.path.basename(fp_data.test_recursive_directory_fp[i][1][0])) == os.path.basename(result[i][1][0])
607+
608+
def test_recursive_directory_spaces_fp(self):
609+
610+
path = self.root_directory + '/test_data/recursive_data_spaces/'
611+
612+
filepattern = 'img_r{r:ddd}_c{c:ddd}.tif'
613+
614+
files = fp.FilePattern(path, filepattern, recursive=True)
615+
616+
result = []
617+
618+
for file in files():
619+
result.append(file)
620+
621+
print(result)
622+
623+
# test that same number of files are returned
624+
assert len(result) == len(fp_data.test_recursive_space)
625+
626+
# test that each variable and path are equal for each file in list
627+
for i in range(len(fp_data.test_recursive_space)):
628+
print(result[i])
629+
assert fp_data.test_recursive_space[i][0]["r"] == result[i][0]["r"]
630+
assert fp_data.test_recursive_space[i][0]["c"] == result[i][0]["c"]
631+
assert str(os.path.basename(fp_data.test_recursive_space[i][1][0])) == os.path.basename(result[i][1][0])
583632

584633
def test_recursive_multi_directory_regex_fp(self):
585634

tests/test_filepattern_data.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -647,3 +647,42 @@
647647
({'c': 1, 'directory': 'TXREAD', 'r': 2}, ['/Users/jmckinzie/Documents/GitHub/filepattern-1/tests/test_data/recursive_data/TXREAD/img_r002_c001.tif']),
648648
({'c': 2, 'directory': 'TXREAD', 'r': 2}, ['/Users/jmckinzie/Documents/GitHub/filepattern-1/tests/test_data/recursive_data/TXREAD/img_r002_c002.tif']),
649649
]
650+
651+
test_recursive_space = [
652+
(
653+
{'c': 0, 'r': 0},
654+
['img_r000_c000.tif', 'img_r000_c000.tif', 'img_r000_c000.tif']
655+
),
656+
(
657+
{'c': 1, 'r': 0},
658+
['img_r000_c001.tif', 'img_r000_c001.tif', 'img_r000_c001.tif']
659+
),
660+
(
661+
{'c': 2, 'r': 0},
662+
['img_r000_c002.tif', 'img_r000_c002.tif', 'img_r000_c002.tif']
663+
),
664+
(
665+
{'c': 0, 'r': 1},
666+
['img_r001_c000.tif', 'img_r001_c000.tif', 'img_r001_c000.tif']
667+
),
668+
(
669+
{'c': 1, 'r': 1},
670+
['img_r001_c001.tif', 'img_r001_c001.tif', 'img_r001_c001.tif']
671+
),
672+
(
673+
{'c': 2, 'r': 1},
674+
['img_r001_c002.tif', 'img_r001_c002.tif', 'img_r001_c002.tif']
675+
),
676+
(
677+
{'c': 0, 'r': 2},
678+
['img_r002_c000.tif', 'img_r002_c000.tif', 'img_r002_c000.tif']
679+
),
680+
(
681+
{'c': 1, 'r': 2},
682+
['img_r002_c001.tif', 'img_r002_c001.tif', 'img_r002_c001.tif']
683+
),
684+
(
685+
{'c': 2, 'r': 2},
686+
['img_r002_c002.tif', 'img_r002_c002.tif', 'img_r002_c002.tif']
687+
)
688+
]

tests/test_generate_filepattern_data.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,112 @@ def generate_channel_data():
100100

101101
print("Files generated.")
102102

103+
def generate_channel_data_sc():
104+
105+
MAX = 3
106+
107+
directory = 'test_data'
108+
root_directory = os.path.dirname(os.path.realpath(__file__))
109+
path = os.path.join(root_directory, directory)
110+
data_path = path + '/data'
111+
recursive_path = path + '/recursive_data_sc'
112+
113+
try:
114+
os.mkdir(path)
115+
os.mkdir(data_path)
116+
os.mkdir(recursive_path)
117+
print('Data directory created at ' + path)
118+
except FileExistsError:
119+
print("Data directory already exists")
120+
121+
try:
122+
os.mkdir(data_path)
123+
print('Data directory created at ' + path)
124+
except FileExistsError:
125+
print("Data directory already exists")
126+
127+
try:
128+
os.mkdir(recursive_path)
129+
print('Data directory created at ' + path)
130+
except FileExistsError:
131+
print("Data directory already exists")
132+
133+
channels = ['DAPI_TEST', 'TXREAD_TEST', 'GFP_TEST']
134+
135+
for channel in channels:
136+
current_path = recursive_path + '/' + channel
137+
try:
138+
os.mkdir(current_path)
139+
except FileExistsError:
140+
print("Channel directory already exists")
141+
142+
for i in range(0, MAX):
143+
144+
str_i = str(i).zfill(3)
145+
146+
for j in range(0, MAX):
147+
148+
str_j = str(j).zfill(3)
149+
150+
recursive_name = 'img_r{}_c{}.tif'.format(str_i, str_j)
151+
f = open(current_path + '/' + recursive_name, 'w+')
152+
f.close()
153+
154+
print("Files generated.")
155+
156+
def generate_channel_data_spaces():
157+
158+
MAX = 3
159+
160+
directory = 'test_data'
161+
root_directory = os.path.dirname(os.path.realpath(__file__))
162+
path = os.path.join(root_directory, directory)
163+
data_path = path + '/data'
164+
recursive_path = path + '/recursive_data_spaces'
165+
166+
try:
167+
os.mkdir(path)
168+
os.mkdir(data_path)
169+
os.mkdir(recursive_path)
170+
print('Data directory created at ' + path)
171+
except FileExistsError:
172+
print("Data directory already exists")
173+
174+
try:
175+
os.mkdir(data_path)
176+
print('Data directory created at ' + path)
177+
except FileExistsError:
178+
print("Data directory already exists")
179+
180+
try:
181+
os.mkdir(recursive_path)
182+
print('Data directory created at ' + path)
183+
except FileExistsError:
184+
print("Data directory already exists")
185+
186+
channels = ['DAPI TEST', 'TXREAD TEST', 'GFP TEST']
187+
188+
for channel in channels:
189+
current_path = recursive_path + '/' + channel
190+
try:
191+
os.mkdir(current_path)
192+
except FileExistsError:
193+
print("Channel directory already exists")
194+
195+
for i in range(0, MAX):
196+
197+
str_i = str(i).zfill(3)
198+
199+
for j in range(0, MAX):
200+
201+
str_j = str(j).zfill(3)
202+
203+
recursive_name = 'img_r{}_c{}.tif'.format(str_i, str_j)
204+
f = open(current_path + '/' + recursive_name, 'w+')
205+
f.close()
206+
207+
print("Files generated.")
208+
103209
def generate_sorted_data():
104210
MAX = 30
105211
length = 0
@@ -171,6 +277,8 @@ def generate_bracket_data():
171277
generate_sorted_data()
172278
generate_text_data()
173279
generate_bracket_data()
280+
generate_channel_data_sc
281+
generate_channel_data_spaces
174282

175283

176284
MAX = 3

0 commit comments

Comments
 (0)