diff --git a/codegen/adr_utils.txt b/codegen/adr_utils.txt index e7f18db81..4290c2aaf 100644 --- a/codegen/adr_utils.txt +++ b/codegen/adr_utils.txt @@ -73,3 +73,58 @@ def get_logger(logfile=None): ch.setFormatter(formatter) logger.addHandler(ch) return logger + + +def check_filter(filter: str = ""): + """ + Verify validity of the query string for filtering. + + Parameters + ---------- + filter : str, optional + Query string for filtering. The default is ``""``. The syntax corresponds + to the syntax for Ansys Dynamic Reporting. For more information, see + _Query Expressions in the documentation for Ansys Dynamic Reporting. + + Returns + ------- + bool + ``True`` if the query string is valid, ``False`` otherwise. + """ + for query_stanza in filter.split(";"): + if len(query_stanza) > 0: + if len(query_stanza.split("|")) != 4: + return False + if query_stanza.split("|")[0] not in ["A", "O"]: + return False + if query_stanza.split("|")[1][0:2] not in ["i_", "s_", "d_", "t_"]: + return False + return True + + +def build_query_url(logger = None, filter: str = "") -> str: + """ + Build the query section of report url. + + Parameters + ---------- + logger: logging.logger + The logger object. + + filter : str, optional + Query string for filtering. The default is ``""``. The syntax corresponds + to the syntax for Ansys Dynamic Reporting. For more information, see + _Query Expressions in the documentation for Ansys Dynamic Reporting. + + Returns + ------- + str + query section of the report url corresponding to the query string. + """ + valid = check_filter(filter) + if valid is False: + logger.warning("Warning: filter string is not valid. Will be ignored.") + return "" + else: + query_str = "&query={}".format(filter.replace("|", "%7C").replace(";", "%3B").replace("&", "%2C")) + return query_str diff --git a/src/ansys/dynamicreporting/core/adr_report.py b/src/ansys/dynamicreporting/core/adr_report.py index f2c0e032e..c1bb94298 100644 --- a/src/ansys/dynamicreporting/core/adr_report.py +++ b/src/ansys/dynamicreporting/core/adr_report.py @@ -21,7 +21,7 @@ from typing import Optional import webbrowser -from ansys.dynamicreporting.core.adr_utils import in_ipynb +from ansys.dynamicreporting.core.adr_utils import build_query_url, in_ipynb from ansys.dynamicreporting.core.utils import report_objects try: @@ -75,7 +75,7 @@ def __find_report_obj__(self) -> bool: success = True return success - def visualize(self, new_tab: bool = False) -> None: + def visualize(self, new_tab: bool = False, filter: str = "") -> None: """ Render the report. @@ -86,6 +86,10 @@ def visualize(self, new_tab: bool = False) -> None: is a Jupyter notebook. The default is ``False``, in which case the report is rendered in the current location. If the environment is not a Jupyter notebook, the report is always rendered in a new tab. + filter : str, optional + Query string for filtering. The default is ``""``. The syntax corresponds + to the syntax for Ansys Dynamic Reporting. For more information, see + _Query Expressions in the documentation for Ansys Dynamic Reporting. Returns ------- @@ -110,16 +114,23 @@ def visualize(self, new_tab: bool = False) -> None: else: display(iframe) else: - url = self.get_url() + url = self.get_url(filter=filter) if url == "": # pragma: no cover self.service.logger.error("Error: could not obtain url for report") else: webbrowser.open_new(url) - def get_url(self) -> str: + def get_url(self, filter: str = "") -> str: """ Get the URL corresponding to the report. + Parameters + ---------- + filter : str, optional + Query string for filtering. The default is ``""``. The syntax corresponds + to the syntax for Ansys Dynamic Reporting. For more information, see + _Query Expressions in the documentation for Ansys Dynamic Reporting. + Returns ------- str @@ -157,9 +168,10 @@ def get_url(self) -> str: ) return "" url += "usemenus=off" + url += build_query_url(self.service.logger, filter) return url - def get_iframe(self, width: int = 1000, height: int = 800): + def get_iframe(self, width: int = 1000, height: int = 800, filter: str = ""): """ Get the iframe object corresponding to the report. @@ -169,6 +181,10 @@ def get_iframe(self, width: int = 1000, height: int = 800): Width of the iframe object. The default is ``1000``. height : int, optional Height of the iframe object. The default is ``800``. + filter : str, optional + Query string for filtering. The default is ``""``. The syntax corresponds + to the syntax for Ansys Dynamic Reporting. For more information, see + _Query Expressions in the documentation for Ansys Dynamic Reporting. Returns ------- @@ -187,7 +203,7 @@ def get_iframe(self, width: int = 1000, height: int = 800): report_iframe = my_report.get_iframe() """ if "IPython.display" in sys.modules: - url = self.get_url() + url = self.get_url(filter=filter) iframe = IFrame(src=url, width=width, height=height) else: iframe = None diff --git a/src/ansys/dynamicreporting/core/adr_service.py b/src/ansys/dynamicreporting/core/adr_service.py index 1341f1786..6dc36d90d 100755 --- a/src/ansys/dynamicreporting/core/adr_service.py +++ b/src/ansys/dynamicreporting/core/adr_service.py @@ -35,7 +35,7 @@ from .adr_item import Item from .adr_report import Report -from .adr_utils import dict_items, get_logger, in_ipynb, type_maps +from .adr_utils import build_query_url, check_filter, dict_items, get_logger, in_ipynb, type_maps from .constants import DOCKER_DEFAULT_PORT, DOCKER_REPO_URL from .docker_support import DockerLauncher from .exceptions import ( @@ -636,32 +636,6 @@ def stop(self) -> None: self.serverobj = None self._url = None - def __check_filter__(self, filter: str = ""): - """ - Verify validity of the query string for filtering. - - Parameters - ---------- - filter : str, optional - Query string for filtering. The default is ``""``. The syntax corresponds - to the syntax for Ansys Dynamic Reporting. For more information, see - _Query Expressions in the documentation for Ansys Dynamic Reporting. - - Returns - ------- - bool - ``True`` if the query string is valid, ``False`` otherwise. - """ - for query_stanza in filter.split(";"): - if len(query_stanza) > 0: - if len(query_stanza.split("|")) != 4: - return False - if query_stanza.split("|")[0] not in ["A", "O"]: - return False - if query_stanza.split("|")[1][0:2] not in ["i_", "s_", "d_", "t_"]: - return False - return True - def visualize_report( self, report_name: Optional[str] = "", @@ -724,17 +698,9 @@ def visualize_report( url += "usemenus=off" query_str = "" if filter: - valid = self.__check_filter__(filter) - if valid is False: - self.logger.warning("Warning: filter string is not valid. Will be ignored.") - else: - query_str = "&query=" - for q_stanza in filter.split(";"): - if len(q_stanza) > 1: - each_item = q_stanza.split("|") - query_str += each_item[-4] + "%7C" + each_item[-3] - query_str += "%7C" + each_item[-2] - query_str += "%7C" + each_item[-1] + query_str = build_query_url(self.logger, filter) + else: + query_str = "" url += query_str if in_ipynb() and not new_tab: display(IFrame(src=url, width=1000, height=800)) @@ -803,7 +769,7 @@ def query(self, query_type: str = "Item", filter: Optional[str] = "") -> list: imgs = adr_service.query(query_type='Item', filter='A|i_type|cont|image;') """ queried_items = [] - valid = self.__check_filter__(filter) + valid = check_filter(filter) if valid is False: self.logger.warning("Warning: filter string is not valid. Will be ignored.") filter = "" diff --git a/tests/test_report.py b/tests/test_report.py index 1471a3e65..380398c13 100755 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -14,6 +14,14 @@ def test_geturl_report(adr_service_query) -> bool: assert "http:" in url +@pytest.mark.ado_test +def test_geturl_report_with_filter(adr_service_query) -> bool: + my_report = adr_service_query.get_report(report_name="My Top Report") + url = my_report.get_url(filter='"A|b_type|cont|image;"') + adr_service_query.stop() + assert "http:" in url + + def test_visualize_report(adr_service_query) -> bool: success = False try: diff --git a/tests/test_service.py b/tests/test_service.py index 8b0525e18..8f46d3e6f 100755 --- a/tests/test_service.py +++ b/tests/test_service.py @@ -99,20 +99,6 @@ def test_unit_query() -> bool: assert query_list == [] -@pytest.mark.ado_test -def test_unit_invalidqueryone() -> bool: - a = Service() - valid = a.__check_filter__("F|i_type|cont|html;") - assert valid is False - - -@pytest.mark.ado_test -def test_unit_invalidquerytwo() -> bool: - a = Service() - valid = a.__check_filter__("A|b_type|cont|html;") - assert valid is False - - @pytest.mark.ado_test def test_unit_delete_invalid(request) -> bool: logfile = join(request.fspath.dirname, "outfile_4.txt")