33
44from sqlalchemy_bigquery ._types import _get_transitive_schema_fields , STRUCT_FIELD_TYPES
55
6+
67def create_fut (name , field_type , mode = "NULLABLE" , sub_fields = None ):
78 """
89 Helper function to create a SchemaField object for testing.
@@ -21,77 +22,115 @@ def create_fut(name, field_type, mode="NULLABLE", sub_fields=None):
2122 (
2223 "STRUCT field, not REPEATED, with sub-fields, should recurse" ,
2324 [
24- create_fut ("s1" , "STRUCT" , "NULLABLE" , sub_fields = [
25- create_fut ("child1" , "STRING" , "NULLABLE" )
26- ])
25+ create_fut (
26+ "s1" ,
27+ "STRUCT" ,
28+ "NULLABLE" ,
29+ sub_fields = [create_fut ("child1" , "STRING" , "NULLABLE" )],
30+ )
2731 ],
2832 ["s1" , "s1.child1" ],
2933 ),
3034 (
3135 "RECORD field (alias for STRUCT), not REPEATED, with sub-fields, should recurse" ,
3236 [
33- create_fut ("r1" , "RECORD" , "NULLABLE" , sub_fields = [
34- create_fut ("child_r1" , "INTEGER" , "NULLABLE" )
35- ])
37+ create_fut (
38+ "r1" ,
39+ "RECORD" ,
40+ "NULLABLE" ,
41+ sub_fields = [create_fut ("child_r1" , "INTEGER" , "NULLABLE" )],
42+ )
3643 ],
3744 ["r1" , "r1.child_r1" ],
3845 ),
3946 (
4047 "STRUCT field, REPEATED, with sub-fields, should NOT recurse" ,
4148 [
42- create_fut ("s2" , "STRUCT" , "REPEATED" , sub_fields = [
43- create_fut ("child2" , "STRING" , "NULLABLE" )
44- ])
49+ create_fut (
50+ "s2" ,
51+ "STRUCT" ,
52+ "REPEATED" ,
53+ sub_fields = [create_fut ("child2" , "STRING" , "NULLABLE" )],
54+ )
4555 ],
4656 ["s2" ],
4757 ),
4858 (
4959 "Non-STRUCT field (STRING), not REPEATED, should NOT recurse" ,
50- [
51- create_fut ("f1" , "STRING" , "NULLABLE" )
52- ],
60+ [create_fut ("f1" , "STRING" , "NULLABLE" )],
5361 ["f1" ],
5462 ),
5563 (
5664 "Non-STRUCT field (INTEGER), REPEATED, should NOT recurse" ,
57- [
58- create_fut ("f2" , "INTEGER" , "REPEATED" )
59- ],
65+ [create_fut ("f2" , "INTEGER" , "REPEATED" )],
6066 ["f2" ],
6167 ),
6268 (
6369 "Deeply nested STRUCT, not REPEATED, should recurse fully" ,
6470 [
65- create_fut ("s_outer" , "STRUCT" , "NULLABLE" , sub_fields = [
66- create_fut ("s_inner1" , "STRUCT" , "NULLABLE" , sub_fields = [
67- create_fut ("s_leaf1" , "STRING" , "NULLABLE" )
68- ]),
69- create_fut ("s_sibling" , "INTEGER" , "NULLABLE" ),
70- create_fut ("s_inner2_repeated_struct" , "STRUCT" , "REPEATED" , sub_fields = [
71- create_fut ("s_leaf2_ignored" , "BOOLEAN" , "NULLABLE" ) # This sub-field should be ignored
72- ]),
73- ])
71+ create_fut (
72+ "s_outer" ,
73+ "STRUCT" ,
74+ "NULLABLE" ,
75+ sub_fields = [
76+ create_fut (
77+ "s_inner1" ,
78+ "STRUCT" ,
79+ "NULLABLE" ,
80+ sub_fields = [create_fut ("s_leaf1" , "STRING" , "NULLABLE" )],
81+ ),
82+ create_fut ("s_sibling" , "INTEGER" , "NULLABLE" ),
83+ create_fut (
84+ "s_inner2_repeated_struct" ,
85+ "STRUCT" ,
86+ "REPEATED" ,
87+ sub_fields = [
88+ create_fut (
89+ "s_leaf2_ignored" , "BOOLEAN" , "NULLABLE"
90+ ) # This sub-field should be ignored
91+ ],
92+ ),
93+ ],
94+ )
95+ ],
96+ [
97+ "s_outer" ,
98+ "s_outer.s_inner1" ,
99+ "s_outer.s_inner1.s_leaf1" ,
100+ "s_outer.s_sibling" ,
101+ "s_outer.s_inner2_repeated_struct" ,
74102 ],
75- ["s_outer" , "s_outer.s_inner1" , "s_outer.s_inner1.s_leaf1" , "s_outer.s_sibling" , "s_outer.s_inner2_repeated_struct" ],
76103 ),
77104 (
78105 "STRUCT field, not REPEATED, but no sub-fields, should not error and not recurse further" ,
79- [
80- create_fut ("s3" , "STRUCT" , "NULLABLE" , sub_fields = [])
81- ],
106+ [create_fut ("s3" , "STRUCT" , "NULLABLE" , sub_fields = [])],
82107 ["s3" ],
83108 ),
84109 (
85110 "Multiple top-level fields with mixed conditions" ,
86111 [
87112 create_fut ("id" , "INTEGER" , "REQUIRED" ),
88- create_fut ("user_profile" , "STRUCT" , "NULLABLE" , sub_fields = [
89- create_fut ("name" , "STRING" , "NULLABLE" ),
90- create_fut ("addresses" , "RECORD" , "REPEATED" , sub_fields = [ # addresses is REPEATED STRUCT
91- create_fut ("street" , "STRING" , "NULLABLE" ), # This sub-field should be ignored
92- create_fut ("city" , "STRING" , "NULLABLE" ) # This sub-field should be ignored
93- ])
94- ]),
113+ create_fut (
114+ "user_profile" ,
115+ "STRUCT" ,
116+ "NULLABLE" ,
117+ sub_fields = [
118+ create_fut ("name" , "STRING" , "NULLABLE" ),
119+ create_fut (
120+ "addresses" ,
121+ "RECORD" ,
122+ "REPEATED" ,
123+ sub_fields = [ # addresses is REPEATED STRUCT
124+ create_fut (
125+ "street" , "STRING" , "NULLABLE"
126+ ), # This sub-field should be ignored
127+ create_fut (
128+ "city" , "STRING" , "NULLABLE"
129+ ), # This sub-field should be ignored
130+ ],
131+ ),
132+ ],
133+ ),
95134 create_fut ("tags" , "STRING" , "REPEATED" ),
96135 ],
97136 ["id" , "user_profile" , "user_profile.name" , "user_profile.addresses" , "tags" ],
@@ -103,26 +142,23 @@ def create_fut(name, field_type, mode="NULLABLE", sub_fields=None):
103142 ),
104143 (
105144 "Field type not in STRUCT_FIELD_TYPES and mode is REPEATED" ,
106- [
107- create_fut ("f_arr" , "FLOAT" , "REPEATED" )
108- ],
109- ["f_arr" ]
145+ [create_fut ("f_arr" , "FLOAT" , "REPEATED" )],
146+ ["f_arr" ],
110147 ),
111148 (
112149 "Field type not in STRUCT_FIELD_TYPES and mode is not REPEATED" ,
113- [
114- create_fut ("f_single" , "DATE" , "NULLABLE" )
115- ],
116- ["f_single" ]
117- )
150+ [create_fut ("f_single" , "DATE" , "NULLABLE" )],
151+ ["f_single" ],
152+ ),
118153]
119154
120155
121156@pytest .mark .parametrize (
122- "description, input_fields_list, expected_field_names" ,
123- test_cases
157+ "description, input_fields_list, expected_field_names" , test_cases
124158)
125- def test_get_transitive_schema_fields_conditions (description , input_fields_list , expected_field_names ):
159+ def test_get_transitive_schema_fields_conditions (
160+ description , input_fields_list , expected_field_names
161+ ):
126162 """
127163 Tests the _get_transitive_schema_fields function, focusing on the conditional logic
128164 `if field.field_type in STRUCT_FIELD_TYPES and field.mode != "REPEATED":`.
0 commit comments