11# -*- coding: utf-8 -*-
22
3- from pyathena .converter import DefaultTypeConverter , _to_struct
4-
5-
6- def test_to_struct_none ():
7- result = _to_struct (None )
8- assert result is None
9-
10-
11- def test_to_struct_valid_json ():
12- struct_json = '{"name": "John", "age": 30, "active": true}'
13- result = _to_struct (struct_json )
14- expected = {"name" : "John" , "age" : 30 , "active" : True }
15- assert result == expected
16-
17-
18- def test_to_struct_nested_json ():
19- struct_json = '{"user": {"name": "John", "age": 30}, "settings": {"theme": "dark"}}'
20- result = _to_struct (struct_json )
21- expected = {"user" : {"name" : "John" , "age" : 30 }, "settings" : {"theme" : "dark" }}
22- assert result == expected
23-
3+ import pytest
244
25- def test_to_struct_invalid_json ():
26- invalid_json = "not valid json"
27- result = _to_struct (invalid_json )
28- assert result is None
29-
30-
31- def test_to_struct_athena_native_format ():
32- """Test conversion of Athena's native struct format {a=1, b=2}"""
33- struct_value = "{a=1, b=2}"
34- result = _to_struct (struct_value )
35- expected = {"a" : 1 , "b" : 2 }
36- assert result == expected
37-
38-
39- def test_to_struct_athena_empty_struct ():
40- """Test conversion of empty Athena struct {}"""
41- struct_value = "{}"
42- result = _to_struct (struct_value )
43- assert result == {}
44-
45-
46- def test_to_struct_athena_string_values ():
47- """Test Athena struct with string values"""
48- struct_value = "{name=John, city=Tokyo}"
49- result = _to_struct (struct_value )
50- expected = {"name" : "John" , "city" : "Tokyo" }
51- assert result == expected
52-
53-
54- def test_to_struct_athena_unnamed_struct ():
55- """Test conversion of unnamed Athena struct {Alice, 25}"""
56- struct_value = "{Alice, 25}"
57- result = _to_struct (struct_value )
58- expected = {"0" : "Alice" , "1" : 25 }
59- assert result == expected
5+ from pyathena .converter import DefaultTypeConverter , _to_struct
606
617
62- def test_to_struct_athena_unnamed_struct_mixed ():
63- """Test unnamed struct with mixed data types"""
64- struct_value = "{John, 30, true}"
65- result = _to_struct (struct_value )
66- expected = {"0" : "John" , "1" : 30 , "2" : True }
8+ @pytest .mark .parametrize (
9+ "input_value,expected" ,
10+ [
11+ (None , None ),
12+ (
13+ '{"name": "John", "age": 30, "active": true}' ,
14+ {"name" : "John" , "age" : 30 , "active" : True },
15+ ),
16+ (
17+ '{"user": {"name": "John", "age": 30}, "settings": {"theme": "dark"}}' ,
18+ {"user" : {"name" : "John" , "age" : 30 }, "settings" : {"theme" : "dark" }},
19+ ),
20+ ("not valid json" , None ),
21+ ("" , None ),
22+ ],
23+ )
24+ def test_to_struct_json_formats (input_value , expected ):
25+ """Test STRUCT conversion for various JSON formats and edge cases."""
26+ result = _to_struct (input_value )
6727 assert result == expected
6828
6929
70- def test_to_struct_athena_simple_cases ():
71- """Test that simple cases work correctly"""
72- # Simple cases that should work
73- simple_cases = [
30+ @pytest .mark .parametrize (
31+ "input_value,expected" ,
32+ [
7433 ("{a=1, b=2}" , {"a" : 1 , "b" : 2 }),
34+ ("{}" , {}),
35+ ("{name=John, city=Tokyo}" , {"name" : "John" , "city" : "Tokyo" }),
36+ ("{Alice, 25}" , {"0" : "Alice" , "1" : 25 }),
37+ ("{John, 30, true}" , {"0" : "John" , "1" : 30 , "2" : True }),
7538 ("{name=John, age=30}" , {"name" : "John" , "age" : 30 }),
7639 ("{x=1, y=2, z=3}" , {"x" : 1 , "y" : 2 , "z" : 3 }),
7740 ("{active=true, count=42}" , {"active" : True , "count" : 42 }),
78- ]
79-
80- for case , expected in simple_cases :
81- result = _to_struct (case )
82- assert result == expected , f"Simple case failed: { case } -> { result } , expected { expected } "
41+ ],
42+ )
43+ def test_to_struct_athena_native_formats (input_value , expected ):
44+ """Test STRUCT conversion for Athena native formats."""
45+ result = _to_struct (input_value )
46+ assert result == expected
8347
8448
85- def test_to_struct_athena_complex_cases ():
86- """Test that complex cases with special characters return None (safe fallback)"""
87- # These cases contain characters that could cause parsing issues
88- complex_cases = [
49+ @pytest .mark .parametrize (
50+ "input_value" ,
51+ [
8952 "{formula=x=y+1, status=active}" , # Equals in value
9053 '{json={"key": "value"}, name=test}' , # Braces in value
9154 '{message=He said "hello", name=John}' , # Quotes in value
92- ]
93-
94- for case in complex_cases :
95- result = _to_struct ( case )
96- # With the new continue logic, these may return partial results instead of None
97- # Check if they return None (strict safety) or partial results (lenient approach)
98- # For now, allow either None or dict results
99- assert result is None or isinstance (result , dict ), (
100- f"Complex case should return None or dict: { case } -> { result } "
101- )
55+ ],
56+ )
57+ def test_to_struct_athena_complex_cases ( input_value ) :
58+ """Test complex cases with special characters return None or partial dict (safe fallback)."""
59+ result = _to_struct ( input_value )
60+ # With the new continue logic, these may return partial results instead of None
61+ # Check if they return None (strict safety) or partial results (lenient approach)
62+ assert result is None or isinstance (result , dict ), (
63+ f"Complex case should return None or dict: { input_value } -> { result } "
64+ )
10265
10366
10467def test_to_map_athena_numeric_keys ():
@@ -111,62 +74,33 @@ def test_to_map_athena_numeric_keys():
11174 assert result == expected
11275
11376
114- def test_to_struct_named_fields ():
115- """Test Athena struct with named fields"""
116- struct_value = "{name=John, age=30}"
117- result = _to_struct (struct_value )
118- expected = {"name" : "John" , "age" : 30 }
119- assert result == expected
120-
121-
122- def test_to_struct_empty_string ():
123- result = _to_struct ("" )
124- assert result is None
125-
126-
127- def test_to_struct_non_dict_json ():
128- # Arrays and other non-dict JSON should return None
129- array_json = "[1, 2, 3]"
130- result = _to_struct (array_json )
131- assert result is None
132-
133- string_json = '"just a string"'
134- result = _to_struct (string_json )
135- assert result is None
136-
137- number_json = "42"
138- result = _to_struct (number_json )
77+ @pytest .mark .parametrize (
78+ "input_value" ,
79+ [
80+ "[1, 2, 3]" , # Array JSON
81+ '"just a string"' , # String JSON
82+ "42" , # Number JSON
83+ ],
84+ )
85+ def test_to_struct_non_dict_json (input_value ):
86+ """Test that non-dict JSON formats return None."""
87+ result = _to_struct (input_value )
13988 assert result is None
14089
14190
14291class TestDefaultTypeConverter :
143- def test_struct_conversion (self ):
144- converter = DefaultTypeConverter ()
145- struct_json = '{"name": "Alice", "age": 25}'
146- result = converter .convert ("row" , struct_json )
147- expected = {"name" : "Alice" , "age" : 25 }
148- assert result == expected
149-
150- def test_struct_conversion_none (self ):
151- converter = DefaultTypeConverter ()
152- result = converter .convert ("row" , None )
153- assert result is None
154-
155- def test_struct_conversion_empty_string (self ):
156- converter = DefaultTypeConverter ()
157- result = converter .convert ("row" , "" )
158- assert result is None
159-
160- def test_struct_conversion_invalid_json (self ):
161- converter = DefaultTypeConverter ()
162- result = converter .convert ("row" , "invalid json" )
163- assert result is None
164-
165- def test_struct_conversion_athena_format (self ):
166- """Test conversion of actual Athena struct format like {a=1, b=2}"""
92+ @pytest .mark .parametrize (
93+ "input_value,expected" ,
94+ [
95+ ('{"name": "Alice", "age": 25}' , {"name" : "Alice" , "age" : 25 }),
96+ (None , None ),
97+ ("" , None ),
98+ ("invalid json" , None ),
99+ ("{a=1, b=2}" , {"a" : 1 , "b" : 2 }),
100+ ],
101+ )
102+ def test_struct_conversion (self , input_value , expected ):
103+ """Test DefaultTypeConverter STRUCT conversion for various input formats."""
167104 converter = DefaultTypeConverter ()
168- # This is how Athena actually returns struct data
169- result = converter .convert ("row" , "{a=1, b=2}" )
170- # Now supports Athena's native struct format
171- expected = {"a" : 1 , "b" : 2 }
105+ result = converter .convert ("row" , input_value )
172106 assert result == expected
0 commit comments