Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 15 additions & 6 deletions libs/garf_core/garf_core/query_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ class GarfResourceError(GarfQueryError):
"""Specifies incorrect resource name in the query."""


class GarfBuiltInQueryError(GarfQueryError):
"""Specifies non-existing builtin query."""


@dataclasses.dataclass
class ProcessedField:
"""Helper class to store fields with its customizers.
Expand Down Expand Up @@ -383,19 +387,24 @@ def macros(self) -> dict[str, str]:
return common_params

def generate(self) -> BaseQueryElements:
return (
self.remove_comments()
.expand()
.extract_resource_name()
.remove_trailing_comma()
self.remove_comments().expand().extract_resource_name()
if self.query.resource_name.startswith('builtin'):
return BaseQueryElements(
title=self.query.resource_name.replace('builtin.', ''),
text=self.query.text,
resource_name=self.query.resource_name,
is_builtin_query=True,
)
(
self.remove_trailing_comma()
.extract_fields()
.extract_filters()
.extract_sorts()
.extract_column_names()
.extract_virtual_columns()
.extract_customizers()
.query
)
return self.query

def expand(self) -> Self:
"""Applies necessary transformations to query."""
Expand Down
25 changes: 23 additions & 2 deletions libs/garf_core/garf_core/report_fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,19 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# pylint: disable=C0330, g-bad-import-order, g-multiple-import

"""Module for getting data from API based on a query.

ApiReportFetcher performs fetching data from API, parsing it
and returning GarfReport.
"""
# pylint: disable=C0330, g-bad-import-order, g-multiple-import

from __future__ import annotations

import logging
from typing import Any
from typing import Any, Callable

from garf_core import (
api_clients,
Expand Down Expand Up @@ -49,6 +51,8 @@ def __init__(
query_specification_builder: query_editor.QuerySpecification = (
query_editor.QuerySpecification
),
builtin_queries: dict[str, Callable[[ApiReportFetcher], report.GarfReport]]
| None = None,
**kwargs: str,
) -> None:
"""Instantiates ApiReportFetcher based on provided api client.
Expand All @@ -57,11 +61,21 @@ def __init__(
api_client: Instantiated api client.
parser: Type of parser to convert API response.
query_specification_builder: Class to perform query parsing.
builtin_queries:
Mapping between query name and function for generating GarfReport.
"""
self.api_client = api_client
self.parser = parser()
self.query_specification_builder = query_specification_builder
self.query_args = kwargs
self.builtin_queries = builtin_queries or {}

def add_builtin_queries(
self,
builtin_queries: dict[str, Callable[[ApiReportFetcher], report.GarfReport]],
) -> None:
"""Adds new built-in queries to the fetcher."""
self.builtin_queries.update(builtin_queries)

async def afetch(
self,
Expand Down Expand Up @@ -107,6 +121,13 @@ def fetch(
args=args,
)
query = query_specification.generate()
if query.is_builtin_query:
if not (builtin_report := self.builtin_queries.get(query.title)):
raise query_editor.GarfBuiltInQueryError(
f'Cannot find the built-in query "{query.title}"'
)
return builtin_report(self, **kwargs)

response = self.api_client.get_response(query, **kwargs)
parsed_response = self.parser.parse_response(response, query)
return report.GarfReport(
Expand Down
13 changes: 13 additions & 0 deletions libs/garf_core/tests/unit/test_query_editor.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,3 +90,16 @@ def test_generate_returns_correct(self, query):
)

assert test_query_spec.query == expected_query_elements

def test_generate_returns_builtin_query(self):
query = 'SELECT test FROM builtin.test'
test_query_spec = query_editor.QuerySpecification(text=query, title='test')
test_query_spec.generate()
expected_query_elements = query_editor.BaseQueryElements(
title='test',
text=query,
resource_name='builtin.test',
is_builtin_query=True,
)

assert test_query_spec.query == expected_query_elements
15 changes: 15 additions & 0 deletions libs/garf_core/tests/unit/test_report_fetcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,18 @@ def test_fetch_returns_correct_report_for_dict_parser(
)

assert test_report == expected_report

def test_fetch_builtin_query_returns_correct_builtin_report(
self, test_dict_report_fetcher
):
test_report = report.GarfReport(results=[[1]], column_names=['test'])

def test_builtin_query(report_fetcher):
return test_report

test_dict_report_fetcher.add_builtin_queries({'test': test_builtin_query})

query = 'SELECT test FROM builtin.test'
fetched_report = test_dict_report_fetcher.fetch(query, None)

assert fetched_report == test_report
Loading