Skip to content

Commit 1e5288b

Browse files
[core] feat: init parser with query specification
1 parent dc6ebda commit 1e5288b

File tree

3 files changed

+30
-49
lines changed

3 files changed

+30
-49
lines changed

libs/garf_core/garf_core/parsers.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,21 +32,26 @@
3232
class BaseParser(abc.ABC):
3333
"""An interface for all parsers to implement."""
3434

35+
def __init__(
36+
self, query_specification: query_editor.BaseQueryElements
37+
) -> None:
38+
"""Initializes BaseParser."""
39+
self.query_spec = query_specification
40+
3541
def parse_response(
3642
self,
3743
response: api_clients.GarfApiResponse,
38-
query_specification: query_editor.BaseQueryElements,
3944
) -> list[list[ApiRowElement]]:
4045
"""Parses response."""
4146
if not response.results:
4247
return [[]]
4348
results = []
4449
for result in response.results:
45-
results.append(self.parse_row(result, query_specification))
50+
results.append(self.parse_row(result))
4651
return results
4752

4853
@abc.abstractmethod
49-
def parse_row(self, row, query_specification):
54+
def parse_row(self, row):
5055
"""Parses single row from response."""
5156

5257

@@ -57,7 +62,6 @@ class ListParser(BaseParser):
5762
def parse_row(
5863
self,
5964
row: list,
60-
query_specification: query_editor.BaseQueryElements,
6165
) -> list[list[ApiRowElement]]:
6266
return row
6367

@@ -69,12 +73,11 @@ class DictParser(BaseParser):
6973
def parse_row(
7074
self,
7175
row: list,
72-
query_specification: query_editor.BaseQueryElements,
7376
) -> list[list[ApiRowElement]]:
7477
if not isinstance(row, Mapping):
7578
raise GarfParserError
7679
result = []
77-
for field in query_specification.fields:
80+
for field in self.query_spec.fields:
7881
result.append(self.get_nested_field(row, field))
7982
return result
8083

libs/garf_core/garf_core/report_fetcher.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ def __init__(
6969
Mapping between query name and function for generating GarfReport.
7070
"""
7171
self.api_client = api_client
72-
self.parser = parser()
72+
self.parser = parser
7373
self.query_specification_builder = query_specification_builder
7474
self.query_args = kwargs
7575
self.builtin_queries = builtin_queries or {}
@@ -135,7 +135,7 @@ def fetch(
135135
return builtin_report(self, **kwargs)
136136

137137
response = self.api_client.get_response(query, **kwargs)
138-
parsed_response = self.parser.parse_response(response, query)
138+
parsed_response = self.parser(query).parse_response(response)
139139
return report.GarfReport(
140140
results=parsed_response, column_names=query.column_names
141141
)

libs/garf_core/tests/unit/test_parsers.py

Lines changed: 19 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -16,79 +16,65 @@
1616

1717
from garf_core import api_clients, parsers, query_editor
1818

19+
test_specification = query_editor.QuerySpecification(
20+
'SELECT test_column_1 FROM test'
21+
).generate()
22+
1923

2024
class TestDictParser:
2125
@pytest.fixture
2226
def test_parser(self):
23-
return parsers.DictParser()
24-
25-
@pytest.fixture
26-
def test_specification(self):
27-
return query_editor.QuerySpecification(
28-
'SELECT test_column_1 FROM test'
29-
).generate()
27+
return parsers.DictParser(test_specification)
3028

31-
def test_parse_row_returns_correct_result(
32-
self, test_parser, test_specification
33-
):
29+
def test_parse_row_returns_correct_result(self, test_parser):
3430
test_row = {'test_column_1': '1', 'test_column_2': 2}
3531

36-
parsed_row = test_parser.parse_row(test_row, test_specification)
32+
parsed_row = test_parser.parse_row(test_row)
3733
expected_row = ['1']
3834

3935
assert parsed_row == expected_row
4036

41-
def test_parse_results_returns_correct_result(
42-
self, test_parser, test_specification
43-
):
37+
def test_parse_results_returns_correct_result(self, test_parser):
4438
test_response = api_clients.GarfApiResponse(
4539
results=[
4640
{'test_column_1': '1', 'test_column_2': 2},
4741
{'test_column_1': '11', 'test_column_2': 22},
4842
]
4943
)
5044

51-
parsed_row = test_parser.parse_response(test_response, test_specification)
45+
parsed_row = test_parser.parse_response(test_response)
5246
expected_row = [['1'], ['11']]
5347

5448
assert parsed_row == expected_row
5549

5650
def test_parse_results_returns_empty_list_on_missing_results(
57-
self, test_parser, test_specification
51+
self, test_parser
5852
):
5953
test_response = api_clients.GarfApiResponse(results=[])
6054

61-
parsed_row = test_parser.parse_response(test_response, test_specification)
55+
parsed_row = test_parser.parse_response(test_response)
6256
expected_row = [[]]
6357

6458
assert parsed_row == expected_row
6559

6660
def test_parse_results_raises_garf_parse_error_on_incorrect_items_in_response(
67-
self, test_parser, test_specification
61+
self, test_parser
6862
):
6963
test_response = api_clients.GarfApiResponse(results=[[1, 2]])
7064

7165
with pytest.raises(parsers.GarfParserError):
72-
test_parser.parse_response(test_response, test_specification)
66+
test_parser.parse_response(test_response)
7367

7468

7569
class TestNumericDictParser:
7670
@pytest.fixture
7771
def test_parser(self):
78-
return parsers.NumericConverterDictParser()
72+
return parsers.NumericConverterDictParser(test_specification)
7973

80-
@pytest.fixture
81-
def test_specification(self):
82-
return query_editor.QuerySpecification(
83-
'SELECT test_column_1 FROM test'
84-
).generate()
85-
86-
def test_parse_row_returns_converted_numeric_values(
87-
self, test_parser, test_specification
88-
):
74+
def test_parse_row_returns_converted_numeric_values(self, test_parser):
8975
test_row = {'test_column_1': '1', 'test_column_2': 2}
9076

91-
parsed_row = test_parser.parse_row(test_row, test_specification)
77+
parsed_row = test_parser.parse_row(test_row)
9278
expected_row = [1]
9379

9480
assert parsed_row == expected_row
@@ -97,19 +83,11 @@ def test_parse_row_returns_converted_numeric_values(
9783
class TestListParser:
9884
@pytest.fixture
9985
def test_parser(self):
100-
return parsers.ListParser()
86+
return parsers.ListParser(test_specification)
10187

102-
@pytest.fixture
103-
def test_specification(self):
104-
return query_editor.QuerySpecification(
105-
'SELECT test_column_1 FROM test'
106-
).generate()
107-
108-
def test_parse_row_returns_converted_numeric_values(
109-
self, test_parser, test_specification
110-
):
88+
def test_parse_row_returns_converted_numeric_values(self, test_parser):
11189
test_row = {'test_column_1': '1', 'test_column_2': 2}
11290

113-
parsed_row = test_parser.parse_row(test_row, test_specification)
91+
parsed_row = test_parser.parse_row(test_row)
11492

11593
assert parsed_row == test_row

0 commit comments

Comments
 (0)