This repository was archived by the owner on Sep 30, 2026. It is now read-only.
Repository navigation
Expand file tree
/
Copy pathtest_load_file.py
More file actions
224 lines (191 loc) · 7.38 KB
/
Copy pathtest_load_file.py
File metadata and controls
224 lines (191 loc) · 7.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
import os
import pathlib
import warnings
from unittest import mock
import pandas as pd
import pytest
from astro import sql as aql
from astro.airflow.datasets import DATASET_SUPPORT
from astro.constants import Database, FileType
from astro.dataframes.load_options import PandasCsvLoadOptions
from astro.files import File
from astro.sql.operators.load_file import LoadFileOperator, load_file
from astro.table import Metadata, Table
from tests.utils.airflow import create_context
from ..operators import utils as test_utils
OUTPUT_TABLE_NAME = test_utils.get_table_name("load_file_test_table")
CWD = pathlib.Path(__file__).parent
def test_unique_task_id_for_same_path(sample_dag):
tasks = []
with sample_dag:
for index in range(4):
params = {
"input_file": File(path=str(CWD) + "/../../data/homes.csv"),
"output_table": Table(conn_id="sqlite_default", metadata=Metadata(database="pagila")),
}
if index == 3:
params["task_id"] = "task_id"
task = load_file(**params)
tasks.append(task)
test_utils.run_dag(sample_dag)
assert tasks[0].operator.task_id != tasks[1].operator.task_id
assert tasks[1].operator.task_id == "load_file__1"
assert tasks[2].operator.task_id == "load_file__2"
assert tasks[3].operator.task_id == "task_id"
# TODO(kaxil): Change the following test to just check the rendered filename
@mock.patch.dict(os.environ, {"AIRFLOW_VAR_FOO": "templated_file_name"})
@pytest.mark.parametrize(
"database_table_fixture",
[
{
"database": Database.SQLITE,
},
],
indirect=True,
ids=["sqlite"],
)
def test_load_file_templated_filename(sample_dag, database_table_fixture):
db, test_table = database_table_fixture
with sample_dag:
load_file(
input_file=File(path=str(CWD) + "/../../data/{{ var.value.foo }}/example.csv"),
output_table=test_table,
)
test_utils.run_dag(sample_dag)
df = db.export_table_to_pandas_dataframe(test_table)
assert len(df) == 3
def is_dict_subset(superset: dict, subset: dict) -> bool:
"""
Compare superset and subset to check if the latter is a subset of former.
Note: dict1 <= dict2 was not working on multilevel nested dicts.
"""
for key, val in subset.items():
print(key, val)
if isinstance(val, dict):
if key not in superset:
return False
result = is_dict_subset(superset[key], subset[key])
if not result:
return False
elif superset[key] != val:
return False
return True
def test_aql_load_file_columns_names_capitalization_dataframe(sample_dag):
filename = str(CWD.parent) + "/../data/homes_pattern_1.csv"
from airflow.decorators import task
@task
def validate(input_df_1, input_df_2, input_df_3):
assert isinstance(input_df_1, pd.DataFrame)
assert isinstance(input_df_2, pd.DataFrame)
assert isinstance(input_df_3, pd.DataFrame)
assert all(x.isupper() for x in list(input_df_1.columns))
assert all(x.islower() for x in list(input_df_2.columns))
assert all(x.islower() for x in list(input_df_3.columns))
with sample_dag:
loaded_df_1 = load_file(
input_file=File(path=filename, filetype=FileType.CSV),
columns_names_capitalization="upper",
)
loaded_df_2 = load_file(
input_file=File(path=filename, filetype=FileType.CSV),
columns_names_capitalization="lower",
)
loaded_df_3 = load_file(
input_file=File(path=filename, filetype=FileType.CSV),
columns_names_capitalization="original",
)
validate(loaded_df_1, loaded_df_2, loaded_df_3)
test_utils.run_dag(sample_dag)
@pytest.mark.skipif(not DATASET_SUPPORT, reason="Inlets/Outlets will only be added for Airflow >= 2.4")
def test_inlets_outlets_supported_ds():
"""Test Datasets are set as inlets and outlets"""
input_file = File("gs://bucket/object.csv")
output_table = Table("test_name")
task = aql.load_file(
input_file=input_file,
output_table=output_table,
)
assert task.operator.inlets == [input_file]
assert task.operator.outlets == [output_table]
@pytest.mark.skipif(DATASET_SUPPORT, reason="Inlets/Outlets will only be added for Airflow >= 2.4")
def test_inlets_outlets_non_supported_ds():
"""Test inlets and outlets are not set if Datasets are not supported"""
input_file = File("gs://bucket/object.csv")
output_table = Table("test_name")
task = aql.load_file(
input_file=input_file,
output_table=output_table,
)
assert task.operator.inlets == []
assert task.operator.outlets == []
@pytest.mark.parametrize(
"database_table_fixture",
[
{
"database": Database.SQLITE,
},
],
indirect=True,
ids=["Sqlite"],
)
@pytest.mark.parametrize("if_exists", ["replace", "append"])
def test_tables_creation_if_they_dont_exist(database_table_fixture, if_exists):
"""
Verify creation of new tables in case we pass if_exists=replace/append if they don't exists.
"""
path = str(CWD) + "/../../data/homes_main.csv"
db, test_table = database_table_fixture
load_file_task = load_file(input_file=File(path), output_table=test_table, if_exists=if_exists)
load_file_task.operator.execute(context=create_context(load_file_task.operator))
database_df = db.export_table_to_pandas_dataframe(test_table)
assert database_df.shape == (3, 9)
# TODO: Remove this test in astro-sdk 2.0.0
@pytest.mark.parametrize(
"database_table_fixture",
[
{
"database": Database.SQLITE,
},
],
indirect=True,
ids=["Sqlite"],
)
@pytest.mark.parametrize("if_exists", ["append"])
def test_load_file_native_support_kwargs_warnings_message(database_table_fixture, if_exists):
"""Assert the warning log for load_options will be replacing native_support_kwargs parameter"""
path = str(CWD) + "/../../data/homes_main.csv"
_, test_table = database_table_fixture
with pytest.warns(
expected_warning=DeprecationWarning,
match=r"`load_options` will replace `native_support_kwargs`",
):
load_file(
input_file=File(path),
output_table=test_table,
if_exists=if_exists,
native_support_kwargs={"dummy": "dummy"},
)
with pytest.warns(
expected_warning=DeprecationWarning,
match=r"`load_options` will replace `native_support_kwargs`",
):
LoadFileOperator(
input_file=File(path),
output_table=test_table,
if_exists=if_exists,
native_support_kwargs={"dummy": "dummy"},
)
def test_deprecation_warning_for_loadoptions():
path = str(CWD) + "/../../data/homes_main.csv"
with warnings.catch_warnings(record=True) as warn:
load_file(
input_file=File(path),
output_table=Table(conn_id="sqlite_default"),
use_native_support=False,
load_options=PandasCsvLoadOptions(delimiter="$"),
)
assert (
"`PandasCsvLoadOptions` will be replaced by `astro.dataframes.load_options.PandasLoadOptions` in"
" astro-sdk-python>=2.0.0. Please use `astro.dataframes.load_options.PandasLoadOptions` class instead."
in [str(w.message) for w in warn]
)