From 9d427787c54bb8de6293d248d8305b7c12b0b988 Mon Sep 17 00:00:00 2001 From: Tom Titcombe <t.j.titcombe@gmail.com> Date: Fri, 4 Jan 2019 09:07:21 +0000 Subject: [PATCH] Accept optional vector of file extensions in findRuns Expose this argument to python Remove overload of findRun which accepts a set of extensions Add test to FileFinderTest.py to check can call findRuns with or without list of extensions as an argument Refs #21231 --- Framework/API/inc/MantidAPI/FileFinder.h | 5 ++- Framework/API/src/FileFinder.cpp | 33 +++---------------- Framework/API/test/FileFinderTest.h | 5 +++ .../mantid/api/src/Exports/FileFinder.cpp | 18 +++++++--- .../test/python/mantid/api/FileFinderTest.py | 19 +++++++++-- 5 files changed, 41 insertions(+), 39 deletions(-) diff --git a/Framework/API/inc/MantidAPI/FileFinder.h b/Framework/API/inc/MantidAPI/FileFinder.h index 7e12fc77af9..c0052258a21 100644 --- a/Framework/API/inc/MantidAPI/FileFinder.h +++ b/Framework/API/inc/MantidAPI/FileFinder.h @@ -48,12 +48,11 @@ public: bool getCaseSensitive() const; std::vector<IArchiveSearch_sptr> getArchiveSearch(const Kernel::FacilityInfo &facility) const; - std::string findRun(const std::string &hintstr, - const std::set<std::string> &exts) const; std::string findRun( const std::string &hintstr, const std::vector<std::string> &exts = std::vector<std::string>()) const; - std::vector<std::string> findRuns(const std::string &hintstr) const; + std::vector<std::string> findRuns(const std::string &hintstr, + const std::vector<std::string> &exts = std::vector<std::string>()) const; /// DO NOT USE! MADE PUBLIC FOR TESTING ONLY. const Kernel::InstrumentInfo getInstrument(const std::string &hint) const; /// DO NOT USE! MADE PUBLIC FOR TESTING ONLY. diff --git a/Framework/API/src/FileFinder.cpp b/Framework/API/src/FileFinder.cpp index 392db921a8d..7016ed7a2a2 100644 --- a/Framework/API/src/FileFinder.cpp +++ b/Framework/API/src/FileFinder.cpp @@ -308,32 +308,6 @@ FileFinderImpl::makeFileName(const std::string &hint, return filename; } -/** - * Find the file given a hint. If the name contains a dot(.) then it is assumed - * that it is already a file stem - * otherwise calls makeFileName internally. - * @param hintstr :: The name hint, format: [INSTR]1234[.ext] - * @param exts :: Optional list of allowed extensions. Only those extensions - * found in both - * facilities extension list and exts will be used in the search. If an - * extension is given in hint - * this argument is ignored. - * @return The full path to the file or empty string if not found - */ -std::string FileFinderImpl::findRun(const std::string &hintstr, - const std::set<std::string> &exts) const { - std::string hint = Kernel::Strings::strip(hintstr); - g_log.debug() << "set findRun(\'" << hintstr << "\', exts[" << exts.size() - << "])\n"; - if (hint.empty()) - return ""; - std::vector<std::string> exts_v; - if (!exts.empty()) - exts_v.assign(exts.begin(), exts.end()); - - return this->findRun(hint, exts_v); -} - /** * Determine the extension from a filename. * @@ -575,12 +549,13 @@ FileFinderImpl::findRun(const std::string &hintstr, * @param hintstr :: Comma separated list of hints to findRun method. * Can also include ranges of runs, e.g. 123-135 or equivalently 123-35. * Only the beginning of a range can contain an instrument name. + * @param exts :: Vector of allowed file extensions. * @return A vector of full paths or empty vector * @throw std::invalid_argument if the argument is malformed * @throw Exception::NotFoundError if a file could not be found */ std::vector<std::string> -FileFinderImpl::findRuns(const std::string &hintstr) const { +FileFinderImpl::findRuns(const std::string &hintstr, const std::vector<std::string> &exts) const { std::string hint = Kernel::Strings::strip(hintstr); g_log.debug() << "findRuns hint = " << hint << "\n"; std::vector<std::string> res; @@ -638,7 +613,7 @@ FileFinderImpl::findRuns(const std::string &hintstr) const { run = std::to_string(irun); while (run.size() < nZero) run.insert(0, "0"); - std::string path = findRun(p1.first + run); + std::string path = findRun(p1.first + run, exts); if (!path.empty()) { res.push_back(path); } else { @@ -646,7 +621,7 @@ FileFinderImpl::findRuns(const std::string &hintstr) const { } } } else { - std::string path = findRun(*h); + std::string path = findRun(*h, exts); if (!path.empty()) { res.push_back(path); } else { diff --git a/Framework/API/test/FileFinderTest.h b/Framework/API/test/FileFinderTest.h index 27005b36565..f95e396c15c 100644 --- a/Framework/API/test/FileFinderTest.h +++ b/Framework/API/test/FileFinderTest.h @@ -333,6 +333,11 @@ public: TS_ASSERT_DIFFERS(*it, *(it - 1)); } } + + const std::vector<std::string> incorrect_extension = {".txt"}; + TS_ASSERT_THROWS(files = FileFinder::Instance().findRuns( + "MUSR15189-15193", incorrect_extension), + Exception::NotFoundError); } void testFindAddFiles() { diff --git a/Framework/PythonInterface/mantid/api/src/Exports/FileFinder.cpp b/Framework/PythonInterface/mantid/api/src/Exports/FileFinder.cpp index 6a7eef7aa6c..797de937461 100644 --- a/Framework/PythonInterface/mantid/api/src/Exports/FileFinder.cpp +++ b/Framework/PythonInterface/mantid/api/src/Exports/FileFinder.cpp @@ -8,6 +8,7 @@ #include "MantidKernel/WarningSuppressions.h" #include "MantidPythonInterface/core/ReleaseGlobalInterpreterLock.h" #include <boost/python/class.hpp> +#include <boost/python/list.hpp> #include <boost/python/overloads.hpp> #include <boost/python/reference_existing_object.hpp> @@ -30,18 +31,24 @@ GNU_DIAG_ON("unused-local-typedef") /** * Runs FileFinder.findRuns after releasing the python GIL. * @param self :: A reference to the calling object - * @param hinstr :: A string containing the run number and possibly instrument + * @param hintstr :: A string containing the run number and possibly instrument * to search for + * @param exts_list :: A python list containing strings of file extensions to search */ std::vector<std::string> runFinderProxy(FileFinderImpl &self, - std::string hinstr) { + std::string hintstr, + list exts_list) { + std::vector<std::string> exts; // Convert python list to c++ vector + for (int i = 0; i < len(exts_list); ++i) + exts.push_back(extract<std::string>(exts_list[i])); + // Before calling the function we need to release the GIL, // drop the Python threadstate and reset anything installed // via PyEval_SetTrace while we execute the C++ code - // ReleaseGlobalInterpreter does this for us Mantid::PythonInterface::ReleaseGlobalInterpreterLock releaseGlobalInterpreterLock; - return self.findRuns(hinstr); + return self.findRuns(hintstr, exts); } void export_FileFinder() { @@ -52,11 +59,12 @@ void export_FileFinder() { "Return a full path to the given file if it can be found within " "datasearch.directories paths. Directories can be ignored with " "ignoreDirs=True. An empty string is returned otherwise.")) - .def("findRuns", &runFinderProxy, (arg("self"), arg("hintstr")), + .def("findRuns", &runFinderProxy, (arg("self"), arg("hintstr"), arg("exts_list")=list()), "Find a list of files file given a hint. " "The hint can be a comma separated list of run numbers and can also " "include ranges of runs, e.g. 123-135 or equivalently 123-35" - "If no instrument prefix is given then the current default is used.") + "If no instrument prefix is given then the current default is used." + "exts_list is an optional list containing strings of file extensions to search.") .def("getCaseSensitive", &FileFinderImpl::getCaseSensitive, (arg("self")), "Option to get if file finder should be case sensitive.") .def("setCaseSensitive", &FileFinderImpl::setCaseSensitive, diff --git a/Framework/PythonInterface/test/python/mantid/api/FileFinderTest.py b/Framework/PythonInterface/test/python/mantid/api/FileFinderTest.py index a5ae031553c..434b3d790c4 100644 --- a/Framework/PythonInterface/test/python/mantid/api/FileFinderTest.py +++ b/Framework/PythonInterface/test/python/mantid/api/FileFinderTest.py @@ -6,9 +6,11 @@ # SPDX - License - Identifier: GPL - 3.0 + from __future__ import (absolute_import, division, print_function) +import os import unittest + from mantid.api import FileFinder -import os + class FileFinderTest(unittest.TestCase): @@ -24,4 +26,17 @@ class FileFinderTest(unittest.TestCase): # We can't be sure what the full path is in general but it should certainly exist! self.assertTrue(os.path.exists(runs[0])) -if __name__ == '__main__': unittest.main() \ No newline at end of file + def test_that_find_runs_accepts_a_list_of_strings(self): + try: + runs = FileFinder.findRuns("CNCS7860", [".nxs", ".txt"]) + except Exception as e: + self.assertFalse(True, "Expected findRuns to accept list of strings as input. {} error was raised " + "with message {}".format(type(e).__name__, str(e))) + else: + # Confirm that it works as above + self.assertTrue(len(runs) == 1) + self.assertTrue(os.path.exists(runs[0])) + + +if __name__ == '__main__': + unittest.main() -- GitLab