Skip to content

Commit ee9bf84

Browse files
authored
Merge pull request #86 from JesseMckinzie/bracket_fix
Fix bug when using escaped charactersx in filepattern
2 parents 21e20d2 + 7110a56 commit ee9bf84

File tree

4 files changed

+74
-2
lines changed

4 files changed

+74
-2
lines changed

src/filepattern/cpp/internal/filepattern.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include "filepattern.hpp"
2+
#include "../util/util.hpp"
23
#include <chrono>
34

45
using namespace std;
@@ -25,7 +26,7 @@ FilePatternObject::FilePatternObject(const string& path, const string& file_patt
2526
this->recursive_ = recursive; // Iterate over subdirectories
2627

2728
// check if filepattern contains directory capturing
28-
if (file_pattern.find('/') != std::string::npos || file_pattern.find('\\') != std::string::npos) {
29+
if (s::isPath(file_pattern)) {
2930
this->setCaptureDirectoryNames(true);
3031
this->recursive_ = true; // need to be recursive to capture directory names
3132

@@ -76,6 +77,7 @@ void FilePatternObject::matchFilesOneDir(){
7677
auto length = end - start;
7778
throw invalid_argument("Invalid pattern found in bracket expressions in filepattern: \"" + this->getRegexFilePattern().substr(start, length+1) + "\"");
7879
}
80+
7981
regex pattern_regex = regex(this->getRegexFilePattern());
8082
smatch sm;
8183

@@ -115,7 +117,7 @@ void FilePatternObject::matchFilesMultDir(){
115117
}
116118

117119
if(regex_match(file, sm, pattern_regex)){
118-
120+
119121
if(this->getJustPath() || this->captureDirectoryNames()) {
120122
tup = getVariableMap(file_path, sm);
121123
} else {

src/filepattern/cpp/util/util.hpp

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,35 @@ static const std::string SLASH = "/";
5757
#endif
5858

5959

60+
61+
6062
/**
6163
* @brief Functions for std::strings and Types.
6264
*
6365
*/
6466
namespace s {
6567

68+
inline bool isPath(const std::string& str) {
69+
70+
if (str.find('/') != std::string::npos) {
71+
return true;
72+
}
73+
74+
// regex characters to escape
75+
const std::unordered_set<char> escape_chars = {'*', '?', '^', '$', '(', ')', '[', ']', '|'};
76+
77+
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)
80+
) {
81+
return true; // Contains a slash that is not proceeded by a character being escaped
82+
}
83+
}
84+
85+
// no slashes were found that are not used for escaping characters
86+
return false;
87+
}
88+
6689
inline std::string escapeForwardSlashes(const std::string& input) {
6790
std::string result;
6891

tests/test_filepattern.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,6 +290,7 @@ class TestFilePattern():
290290
test_generate_filepattern_data.generate_data()
291291
test_generate_filepattern_data.generate_channel_data()
292292
test_generate_filepattern_data.generate_sorted_data()
293+
test_generate_filepattern_data.generate_bracket_data()
293294

294295
def test_file_pattern(self):
295296

@@ -636,6 +637,25 @@ def test_file_pattern_sorting(self):
636637

637638
assert sorted(indices) == indices
638639

640+
def test_file_pattern_brackets(self):
641+
642+
bracket_path = self.root_directory + '/test_data/bracket_data/'
643+
644+
pattern = "x\\(0-31\\)_y\\(01-48\\)_c{c:d}.ome.tif"
645+
646+
files = fp.FilePattern(bracket_path, pattern)
647+
648+
result = []
649+
650+
for file in files: # test iterator without call
651+
result.append(file)
652+
653+
print(result)
654+
655+
for i in range(len(result)):
656+
result[i][0]['c'] == i
657+
os.path.basename(result[i][1][0]) == f'x(0-31)_y(01-48)_c{i}.ome.tif'
658+
639659

640660
# Todo: These tests need new data to be added after replacing the old version of filepattern.
641661
"""

tests/test_generate_filepattern_data.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,12 +138,39 @@ def generate_text_data():
138138
filename = f"img_r{r:03}_c{c:03}.tif"
139139
file.write(filename + "\n")
140140

141+
def generate_bracket_data():
142+
directory = 'test_data'
143+
root_directory = os.path.dirname(os.path.realpath(__file__))
144+
path = os.path.join(root_directory, directory)
145+
data_path = path + '/bracket_data'
146+
147+
try:
148+
os.mkdir(path)
149+
print('Data directory created at ' + path)
150+
except FileExistsError:
151+
print("Data directory already exists")
152+
153+
try:
154+
os.mkdir(data_path)
155+
print('Data directory created at ' + data_path)
156+
except FileExistsError:
157+
print("Data directory already exists")
158+
159+
for i in range(0, MAX):
160+
data1 = 'x(0-31)_y(01-48)_c0.ome.tif'
161+
data2 = 'x(0-31)_y(01-48)_c1.ome.tif'
162+
f1 = open(data_path + '/' + data1, 'w+')
163+
f1.close()
164+
f2 = open(data_path + '/' + data2, 'w+')
165+
f2.close()
166+
141167

142168
if __name__ == '__main__':
143169
generate_data()
144170
generate_channel_data()
145171
generate_sorted_data()
146172
generate_text_data()
173+
generate_bracket_data()
147174

148175

149176
MAX = 3

0 commit comments

Comments
 (0)