diff --git a/python/lsst/summit/utils/efdUtils.py b/python/lsst/summit/utils/efdUtils.py index 4aa3ef32..68148ec0 100644 --- a/python/lsst/summit/utils/efdUtils.py +++ b/python/lsst/summit/utils/efdUtils.py @@ -25,6 +25,7 @@ import datetime import logging import pandas as pd +import re from .utils import getSite @@ -46,7 +47,7 @@ 'getDayObsStartTime', 'getDayObsEndTime', 'getDayObsForTime', - 'getSubTopics', + 'getTopics', ] @@ -530,26 +531,40 @@ def getDayObsForTime(time): return int((time + offset).utc.isot[:10].replace('-', '')) -def getSubTopics(client, topic): - """Get all the sub topics within a given topic. +def getTopics(client, toFind, caseSensitive=False): + """Return all the strings in topics which match the topic query string. - Note that the topic need not be a complete one, for example, rather than - doing `getSubTopics(client, 'lsst.sal.ATMCS')` to get all the topics for - the AuxTel Mount Control System, you can do `getSubTopics(client, - 'lsst.sal.AT')` to get all which relate to the AuxTel in general. + Supports wildcards, which are denoted as `*``, as per shell globs. + + Example: + >>> # assume topics are ['apple', 'banana', 'grape'] + >>> getTopics(, 'a*p*') + ['apple', 'grape'] Parameters ---------- client : `lsst_efd_client.efd_helper.EfdClient` The EFD client to use. - topic : `str` - The topic to query. + toFind : `str` + The query string, with optional wildcards denoted as *. + caseSensitive : `bool`, optional + If ``True``, the query is case sensitive. Defaults to ``False``. Returns ------- - subTopics : `list` of `str` - The sub topics. + matches : `list` of `str` + The list of matching topics. """ loop = asyncio.get_event_loop() topics = loop.run_until_complete(client.get_topics()) - return sorted([t for t in topics if t.startswith(topic)]) + + # Replace wildcard with regex equivalent + pattern = toFind.replace('*', '.*') + flags = re.IGNORECASE if not caseSensitive else 0 + + matches = [] + for topic in topics: + if re.match(pattern, topic, flags): + matches.append(topic) + + return matches diff --git a/tests/data/cassettes/test_getSubTopics.yaml b/tests/data/cassettes/test_getTopics.yaml similarity index 100% rename from tests/data/cassettes/test_getSubTopics.yaml rename to tests/data/cassettes/test_getTopics.yaml diff --git a/tests/test_efdUtils.py b/tests/test_efdUtils.py index 1735939d..73ba3d71 100644 --- a/tests/test_efdUtils.py +++ b/tests/test_efdUtils.py @@ -41,7 +41,7 @@ getDayObsStartTime, getDayObsEndTime, getDayObsForTime, - getSubTopics, + getTopics, ) from utils import getVcr @@ -118,14 +118,24 @@ def test_getDayObsAsTimes(self): self.assertEqual(dayEnd.jd, dayStart.jd + 1) @vcr.use_cassette() - def test_getSubTopics(self): - subTopics = getSubTopics(self.client, 'lsst.sal.MTMount') - self.assertIsInstance(subTopics, list) - self.assertGreater(len(subTopics), 0) - - subTopics = getSubTopics(self.client, 'fake.topics.does.not.exist') - self.assertIsInstance(subTopics, list) - self.assertEqual(len(subTopics), 0) + def test_getTopics(self): + topics = getTopics(self.client, 'lsst.sal.MTMount*') + self.assertIsInstance(topics, list) + self.assertGreater(len(topics), 0) + + topics = getTopics(self.client, '*fake.topics.does.not.exist*') + self.assertIsInstance(topics, list) + self.assertEqual(len(topics), 0) + + # check we can find the mount with a preceding wildcard + topics = getTopics(self.client, '*mTmoUnt*') + self.assertIsInstance(topics, list) + self.assertGreater(len(topics), 0) + + # check it fails if we don't allow case insensitivity + topics = getTopics(self.client, '*mTmoUnt*', caseSensitive=True) + self.assertIsInstance(topics, list) + self.assertEqual(len(topics), 0) @vcr.use_cassette() def test_getEfdData(self):