|
25 | 25 | DEFAULT_CHUNK_SIZE, |
26 | 26 | struct_type_to_result_template, |
27 | 27 | schema_string_to_result_dict_and_struct_type, |
| 28 | + _escape_colons_in_quotes, |
| 29 | + _restore_colons_in_template, |
| 30 | + _COLON_PLACEHOLDER, |
28 | 31 | ) |
29 | 32 | from snowflake.snowpark.types import ( |
30 | 33 | StructType, |
@@ -991,3 +994,85 @@ def test_user_schema_value_tag(): |
991 | 994 | res = element_to_dict_or_str(element, result_template=result_template) |
992 | 995 | assert result_template == {"NUM": None, "STR1": None, "STR2": None, "STR3": None} |
993 | 996 | assert res == {"NUM": "1", "STR1": "NULL", "STR2": None, "STR3": "xxx"} |
| 997 | + |
| 998 | + |
| 999 | +def test_escape_colons_in_quotes(): |
| 1000 | + s = '"px:name": string' |
| 1001 | + escaped = _escape_colons_in_quotes(s) |
| 1002 | + assert escaped.count(":") == 1 |
| 1003 | + assert _COLON_PLACEHOLDER in escaped |
| 1004 | + |
| 1005 | + s = '"px:name": string, "px:value": string' |
| 1006 | + escaped = _escape_colons_in_quotes(s) |
| 1007 | + assert escaped.count(":") == 2 |
| 1008 | + assert escaped.count(_COLON_PLACEHOLDER) == 2 |
| 1009 | + |
| 1010 | + s = 'struct<"px:name": string, "detail": struct<"px:sub": string>>' |
| 1011 | + escaped = _escape_colons_in_quotes(s) |
| 1012 | + assert escaped.count(_COLON_PLACEHOLDER) == 2 |
| 1013 | + assert escaped.count(":") == 3 |
| 1014 | + |
| 1015 | + s = '"Author": string, "Title": string' |
| 1016 | + assert _escape_colons_in_quotes(s) == s |
| 1017 | + assert _escape_colons_in_quotes("") == "" |
| 1018 | + assert _escape_colons_in_quotes("a: int, b: string") == "a: int, b: string" |
| 1019 | + |
| 1020 | + |
| 1021 | +def test_restore_colons_in_template(): |
| 1022 | + assert _restore_colons_in_template(None) is None |
| 1023 | + assert _restore_colons_in_template({"Author": None}) == {"Author": None} |
| 1024 | + |
| 1025 | + # Flat |
| 1026 | + template = { |
| 1027 | + f"px{_COLON_PLACEHOLDER}name": None, |
| 1028 | + f"px{_COLON_PLACEHOLDER}value": None, |
| 1029 | + } |
| 1030 | + assert _restore_colons_in_template(template) == { |
| 1031 | + "px:name": None, |
| 1032 | + "px:value": None, |
| 1033 | + } |
| 1034 | + |
| 1035 | + # Nested |
| 1036 | + template = { |
| 1037 | + f"eq{_COLON_PLACEHOLDER}event": { |
| 1038 | + f"eq{_COLON_PLACEHOLDER}sub-id": None, |
| 1039 | + }, |
| 1040 | + "plain": None, |
| 1041 | + } |
| 1042 | + assert _restore_colons_in_template(template) == { |
| 1043 | + "eq:event": {"eq:sub-id": None}, |
| 1044 | + "plain": None, |
| 1045 | + } |
| 1046 | + |
| 1047 | + |
| 1048 | +def test_schema_string_round_trip_with_colons(): |
| 1049 | + # Flat |
| 1050 | + schema_str = 'struct<"px:name": string, "px:value": string>' |
| 1051 | + assert schema_string_to_result_dict_and_struct_type(schema_str) == { |
| 1052 | + "px:name": None, |
| 1053 | + "px:value": None, |
| 1054 | + } |
| 1055 | + |
| 1056 | + # Nested |
| 1057 | + schema_str = ( |
| 1058 | + 'struct<"eq:event-id": string,' '"eq:detail": struct<"eq:sub-id": string>>' |
| 1059 | + ) |
| 1060 | + assert schema_string_to_result_dict_and_struct_type(schema_str) == { |
| 1061 | + "eq:event-id": None, |
| 1062 | + "eq:detail": {"eq:sub-id": None}, |
| 1063 | + } |
| 1064 | + |
| 1065 | + # Mixed |
| 1066 | + schema_str = 'struct<"px:name": string, "Title": string, price: double>' |
| 1067 | + assert schema_string_to_result_dict_and_struct_type(schema_str) == { |
| 1068 | + "px:name": None, |
| 1069 | + "Title": None, |
| 1070 | + "PRICE": None, |
| 1071 | + } |
| 1072 | + |
| 1073 | + # No colon fields |
| 1074 | + schema_str = 'struct<"Author": string, "TITLE": string>' |
| 1075 | + assert schema_string_to_result_dict_and_struct_type(schema_str) == { |
| 1076 | + "Author": None, |
| 1077 | + "TITLE": None, |
| 1078 | + } |
0 commit comments