Skip to content

Commit 1a9ee0b

Browse files
[core] tests: add tests for base_query
* Ensure that pydantic initialization is supported * Update documentation to add pydantic initialization and remove old style initialization
1 parent edbf674 commit 1a9ee0b

File tree

2 files changed

+125
-22
lines changed

2 files changed

+125
-22
lines changed

docs/usage/queries.md

Lines changed: 54 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ WHERE
141141
segments.date BETWEEN "{start_date}" AND "{end_date}"
142142
```
143143

144-
When this query is executed it's expected that two macros `--macros.start_date=...` and `--macros.end_date=...` are supplied to `garf`.
144+
When this query is executed it's expected that two macros `--macro.start_date=...` and `--macro.end_date=...` are supplied to `garf`.
145145

146146
### Macros in virtual columns
147147

@@ -216,62 +216,94 @@ SELECT * FROM builtin.builtin_query_name
216216
217217
## Queries as Python objects
218218

219-
```python
220-
from garf_core.base_query import BaseQuery
221-
from garf_io import reader
219+
You can define queries in multiple ways.
222220

221+
### As strings
223222

224-
# 1. define query as a string an save in a variable
223+
```python
225224
query_string = "SELECT campaign.id FROM campaign"
225+
```
226+
### As files
227+
228+
#### Local
229+
```python
230+
from garf_io import reader
226231

227-
# 2. define path to a query file and read from it
228-
# path can be local
229232
query_path = "path/to/query.sql"
230-
# or remote
233+
234+
# Instantiate reader
235+
reader_client = reader.FileReader()
236+
# And read from the path
237+
query = reader_client.read(query_path)
238+
```
239+
#### Remote
240+
```python
241+
from garf_io import reader
242+
231243
query_path = "gs://PROJECT_ID/path/to/query.sql"
232244

233245
# Instantiate reader
234246
reader_client = reader.FileReader()
235247
# And read from the path
236248
query = reader_client.read(query_path)
249+
```
237250

238-
# 3. define query as a class
251+
### As dataclasses
252+
```python
253+
from dataclasses import dataclass
254+
255+
from garf_core.base_query import BaseQuery
239256

240-
# Native style
257+
@dataclass
241258
class Campaigns(BaseQuery):
242259
query_text = """
243260
SELECT
244261
campaign.id
245262
FROM campaign
246263
WHERE campaign.status = {status}
247264
"""
265+
status: str = "ENABLED"
248266

249-
def __init__(self, status: str = "ENABLED") -> None:
250-
self.status = status
267+
query = Campaigns(status='DISABLED')
268+
```
251269

252-
# Dataclass style
253-
from dataclasses import dataclass
254270

255-
@dataclass
256-
class Campaigns(BaseQuery):
257-
query_text = """
271+
### As Pydantic objects
272+
273+
```python
274+
from typing import ClassVar
275+
from pydantic import BaseModel
276+
277+
from garf_core.base_query import BaseQuery
278+
279+
class Campaigns(BaseModel, BaseQuery):
280+
query_text: ClassVar[str] = """
258281
SELECT
259282
campaign.id
260283
FROM campaign
261284
WHERE campaign.status = {status}
262285
"""
263286
status: str = "ENABLED"
264287

265-
# Old style
288+
query = Campaigns(status='DISABLED')
289+
```
290+
291+
### As plain python classes
292+
293+
```python
294+
from garf_core.base_query import BaseQuery
295+
from garf_io import reader
296+
266297
class Campaigns(BaseQuery):
267-
def __init__(self, status: str = "ENABLED"):
268-
self.query_text = f"""
298+
query_text = """
269299
SELECT
270300
campaign.id
271301
FROM campaign
272302
WHERE campaign.status = {status}
273303
"""
274304

275-
active_campaigns = report_fetcher.fetch(Campaigns())
276-
inactive_campaigns = report_fetcher.fetch(Campaigns("INACTIVE"))
305+
def __init__(self, status: str = "ENABLED") -> None:
306+
self.status = status
307+
308+
query = Campaigns(status='DISABLED')
277309
```
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# Copyright 2025 Google LLC
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# https://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
import dataclasses
16+
from typing import ClassVar
17+
18+
import pydantic
19+
from garf_core import base_query
20+
21+
22+
class TestBaseQuery:
23+
def test_native_initialization(self):
24+
class TestQuery(base_query.BaseQuery):
25+
query_text = 'SELECT metric FROM resource WHERE status = {status}'
26+
27+
def __init__(self, status: str = 'ENABLED'):
28+
self.status = status
29+
30+
test_query = TestQuery()
31+
32+
assert (
33+
str(test_query) == 'SELECT metric FROM resource WHERE status = ENABLED'
34+
)
35+
36+
def test_dataclass_initialization(self):
37+
@dataclasses.dataclass
38+
class TestQuery(base_query.BaseQuery):
39+
query_text = 'SELECT metric FROM resource WHERE status = {status}'
40+
status: str = 'ENABLED'
41+
42+
test_query = TestQuery()
43+
44+
assert (
45+
str(test_query) == 'SELECT metric FROM resource WHERE status = ENABLED'
46+
)
47+
48+
def test_old_initialization(self):
49+
class TestQuery(base_query.BaseQuery):
50+
def __init__(self, status: str = 'ENABLED'):
51+
self.query_text = 'SELECT metric FROM resource WHERE status = {status}'
52+
self.status = status
53+
54+
test_query = TestQuery()
55+
56+
assert (
57+
str(test_query) == 'SELECT metric FROM resource WHERE status = ENABLED'
58+
)
59+
60+
def test_pydantic_initialization(self):
61+
class TestQuery(base_query.BaseQuery, pydantic.BaseModel):
62+
query_text: ClassVar[str] = (
63+
'SELECT metric FROM resource WHERE status = {status}'
64+
)
65+
status: str = 'ENABLED'
66+
67+
test_query = TestQuery()
68+
69+
assert (
70+
str(test_query) == 'SELECT metric FROM resource WHERE status = ENABLED'
71+
)

0 commit comments

Comments
 (0)