fakesnow 0.4.1__py3-none-any.whl → 0.5.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- fakesnow/fakes.py +35 -4
- fakesnow/info_schema.py +10 -3
- fakesnow/transforms.py +1 -4
- {fakesnow-0.4.1.dist-info → fakesnow-0.5.1.dist-info}/METADATA +8 -6
- fakesnow-0.5.1.dist-info/RECORD +13 -0
- {fakesnow-0.4.1.dist-info → fakesnow-0.5.1.dist-info}/WHEEL +1 -1
- fakesnow-0.4.1.dist-info/RECORD +0 -13
- {fakesnow-0.4.1.dist-info → fakesnow-0.5.1.dist-info}/LICENSE +0 -0
- {fakesnow-0.4.1.dist-info → fakesnow-0.5.1.dist-info}/top_level.txt +0 -0
fakesnow/fakes.py
CHANGED
@@ -46,6 +46,7 @@ class FakeSnowflakeCursor:
|
|
46
46
|
self._use_dict_result = use_dict_result
|
47
47
|
self._last_sql = None
|
48
48
|
self._last_params = None
|
49
|
+
self._sqlstate = None
|
49
50
|
|
50
51
|
def __enter__(self) -> Self:
|
51
52
|
return self
|
@@ -76,7 +77,7 @@ class FakeSnowflakeCursor:
|
|
76
77
|
# use a cursor to avoid destroying an unfetched result on the main connection
|
77
78
|
with self._duck_conn.cursor() as cur:
|
78
79
|
assert self._conn.database, "Not implemented when database is None"
|
79
|
-
assert self._conn.schema, "Not implemented when
|
80
|
+
assert self._conn.schema, "Not implemented when schema is None"
|
80
81
|
|
81
82
|
# match database and schema used on the main connection
|
82
83
|
cur.execute(f"SET SCHEMA = '{self._conn.database}.{self._conn.schema}'")
|
@@ -91,6 +92,20 @@ class FakeSnowflakeCursor:
|
|
91
92
|
params: Sequence[Any] | dict[Any, Any] | None = None,
|
92
93
|
*args: Any,
|
93
94
|
**kwargs: Any,
|
95
|
+
) -> FakeSnowflakeCursor:
|
96
|
+
try:
|
97
|
+
self._sqlstate = None
|
98
|
+
return self._execute(command, params, *args, **kwargs)
|
99
|
+
except snowflake.connector.errors.ProgrammingError as e:
|
100
|
+
self._sqlstate = e.sqlstate
|
101
|
+
raise e
|
102
|
+
|
103
|
+
def _execute(
|
104
|
+
self,
|
105
|
+
command: str | exp.Expression,
|
106
|
+
params: Sequence[Any] | dict[Any, Any] | None = None,
|
107
|
+
*args: Any,
|
108
|
+
**kwargs: Any,
|
94
109
|
) -> FakeSnowflakeCursor:
|
95
110
|
self._arrow_table = None
|
96
111
|
|
@@ -108,13 +123,13 @@ class FakeSnowflakeCursor:
|
|
108
123
|
msg=f"Cannot perform {cmd}. This session does not have a current database. Call 'USE DATABASE', or use a qualified name.", # noqa: E501
|
109
124
|
errno=90105,
|
110
125
|
sqlstate="22000",
|
111
|
-
)
|
126
|
+
)
|
112
127
|
elif no_schema and not self._conn.schema_set:
|
113
128
|
raise snowflake.connector.errors.ProgrammingError(
|
114
129
|
msg=f"Cannot perform {cmd}. This session does not have a current schema. Call 'USE SCHEMA', or use a qualified name.", # noqa: E501
|
115
130
|
errno=90106,
|
116
131
|
sqlstate="22000",
|
117
|
-
)
|
132
|
+
)
|
118
133
|
|
119
134
|
transformed = (
|
120
135
|
expression.transform(transforms.upper_case_unquoted_identifiers)
|
@@ -247,13 +262,21 @@ class FakeSnowflakeCursor:
|
|
247
262
|
# TODO: return number of rows updated/inserted (using returning)
|
248
263
|
return None
|
249
264
|
|
265
|
+
@property
|
266
|
+
def sfqid(self) -> str | None:
|
267
|
+
return "fakesnow"
|
268
|
+
|
269
|
+
@property
|
270
|
+
def sqlstate(self) -> str | None:
|
271
|
+
return self._sqlstate
|
272
|
+
|
250
273
|
@staticmethod
|
251
274
|
def _describe_as_result_metadata(describe_results: list) -> list[ResultMetadata]:
|
252
275
|
# fmt: off
|
253
276
|
def as_result_metadata(column_name: str, column_type: str, _: str) -> ResultMetadata:
|
254
277
|
# see https://docs.snowflake.com/en/user-guide/python-connector-api.html#type-codes
|
255
278
|
# and https://arrow.apache.org/docs/python/api/datatypes.html#type-checking
|
256
|
-
if column_type
|
279
|
+
if column_type in {"BIGINT", "INTEGER"}:
|
257
280
|
return ResultMetadata(
|
258
281
|
name=column_name, type_code=0, display_size=None, internal_size=None, precision=38, scale=0, is_nullable=True # noqa: E501
|
259
282
|
)
|
@@ -288,6 +311,14 @@ class FakeSnowflakeCursor:
|
|
288
311
|
return ResultMetadata(
|
289
312
|
name=column_name, type_code=8, display_size=None, internal_size=None, precision=0, scale=9, is_nullable=True # noqa: E501
|
290
313
|
)
|
314
|
+
elif column_type == "BLOB":
|
315
|
+
return ResultMetadata(
|
316
|
+
name=column_name, type_code=11, display_size=None, internal_size=8388608, precision=None, scale=None, is_nullable=True # noqa: E501
|
317
|
+
)
|
318
|
+
elif column_type == "TIME":
|
319
|
+
return ResultMetadata(
|
320
|
+
name=column_name, type_code=12, display_size=None, internal_size=None, precision=0, scale=9, is_nullable=True # noqa: E501
|
321
|
+
)
|
291
322
|
else:
|
292
323
|
# TODO handle more types
|
293
324
|
raise NotImplementedError(f"for column type {column_type}")
|
fakesnow/info_schema.py
CHANGED
@@ -37,11 +37,18 @@ create view ${catalog}.information_schema.columns_snowflake AS
|
|
37
37
|
select table_catalog, table_schema, table_name, column_name, ordinal_position, column_default, is_nullable,
|
38
38
|
case when starts_with(data_type, 'DECIMAL') or data_type='BIGINT' then 'NUMBER'
|
39
39
|
when data_type='VARCHAR' then 'TEXT'
|
40
|
+
when data_type='DOUBLE' then 'FLOAT'
|
41
|
+
when data_type='BLOB' then 'BINARY'
|
42
|
+
when data_type='TIMESTAMP' then 'TIMESTAMP_NTZ'
|
40
43
|
else data_type end as data_type,
|
41
44
|
ext_character_maximum_length as character_maximum_length, ext_character_octet_length as character_octet_length,
|
42
|
-
case when data_type='BIGINT' then 38
|
43
|
-
|
44
|
-
|
45
|
+
case when data_type='BIGINT' then 38
|
46
|
+
when data_type='DOUBLE' then NULL
|
47
|
+
else numeric_precision end as numeric_precision,
|
48
|
+
case when data_type='BIGINT' then 10
|
49
|
+
when data_type='DOUBLE' then NULL
|
50
|
+
else numeric_precision_radix end as numeric_precision_radix,
|
51
|
+
case when data_type='DOUBLE' then NULL else numeric_scale end as numeric_scale,
|
45
52
|
collation_name, is_identity, identity_generation, identity_cycle
|
46
53
|
from ${catalog}.information_schema.columns
|
47
54
|
left join ${catalog}.information_schema.columns_ext ext
|
fakesnow/transforms.py
CHANGED
@@ -181,10 +181,7 @@ def float_to_double(expression: exp.Expression) -> exp.Expression:
|
|
181
181
|
"""
|
182
182
|
|
183
183
|
if isinstance(expression, exp.DataType) and expression.this == exp.DataType.Type.FLOAT:
|
184
|
-
|
185
|
-
new = expression.copy()
|
186
|
-
new.args["this"] = exp.DataType.Type.DOUBLE
|
187
|
-
return new
|
184
|
+
expression.args["this"] = exp.DataType.Type.DOUBLE
|
188
185
|
|
189
186
|
return expression
|
190
187
|
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: fakesnow
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.5.1
|
4
4
|
Summary: Fake Snowflake Connector for Python. Run Snowflake DB locally.
|
5
5
|
License: MIT License
|
6
6
|
|
@@ -124,12 +124,13 @@ def _fakesnow_session() -> Iterator[None]:
|
|
124
124
|
|
125
125
|
## Implementation coverage
|
126
126
|
|
127
|
-
- [x]
|
128
|
-
- [x] cursors
|
127
|
+
- [x] cursors and standard SQL
|
129
128
|
- [x] [get_result_batches()](https://docs.snowflake.com/en/user-guide/python-connector-api#get_result_batches)
|
130
|
-
- [x]
|
131
|
-
- [x]
|
129
|
+
- [x] information schema
|
130
|
+
- [x] multiple databases
|
132
131
|
- [x] [qmark binding](https://docs.snowflake.com/en/user-guide/python-connector-example#binding-data)
|
132
|
+
- [x] table comments
|
133
|
+
- [x] [write_pandas(..)](https://docs.snowflake.com/en/user-guide/python-connector-api#write_pandas)
|
133
134
|
- [ ] [access control](https://docs.snowflake.com/en/user-guide/security-access-control-overview)
|
134
135
|
- [ ] standalone/out of process api/support for faking non-python connectors
|
135
136
|
- [ ] [stored procedures](https://docs.snowflake.com/en/sql-reference/stored-procedures)
|
@@ -137,8 +138,9 @@ def _fakesnow_session() -> Iterator[None]:
|
|
137
138
|
Partial support
|
138
139
|
|
139
140
|
- [x] date functions
|
140
|
-
- [x]
|
141
|
+
- [x] regex functions
|
141
142
|
- [x] semi-structured data
|
143
|
+
- [x] tags
|
142
144
|
|
143
145
|
For more detail see [tests/test_fakes.py](tests/test_fakes.py)
|
144
146
|
|
@@ -0,0 +1,13 @@
|
|
1
|
+
fakesnow/__init__.py,sha256=ogZl2Z61FIiU2fg8WiM1FhXYLpG-Phvg855nmuMhdqQ,2992
|
2
|
+
fakesnow/checks.py,sha256=1qVLR0ZB3z3UPij3Hm8hqlkcNLH2QJnwe8OqkoFCwv8,2356
|
3
|
+
fakesnow/expr.py,sha256=CAxuYIUkwI339DQIBzvFF0F-m1tcVGKEPA5rDTzmH9A,892
|
4
|
+
fakesnow/fakes.py,sha256=v6t0sLy9KsiiUW-KyRggamt7K7ADEw8uSXdQt6HmQN4,20760
|
5
|
+
fakesnow/fixtures.py,sha256=LANb4LuiUjKbTZRHmgnAi50xC1rs1xF8SHLoBikB88c,509
|
6
|
+
fakesnow/info_schema.py,sha256=0eJgDJ0sbEUVNcfGBb5hdCR2SiKJYmO0MA-ZnnsUhbo,3781
|
7
|
+
fakesnow/py.typed,sha256=B-DLSjYBi7pkKjwxCSdpVj2J02wgfJr-E7B1wOUyxYU,80
|
8
|
+
fakesnow/transforms.py,sha256=PTK3RA1SEiCT9urw97tLyhzXZuWZx5hCUWcvPO2DIwI,22305
|
9
|
+
fakesnow-0.5.1.dist-info/LICENSE,sha256=BL6v_VTnU7xdsocviIQJMFr3stX_-uRfTyByo3gRu4M,1071
|
10
|
+
fakesnow-0.5.1.dist-info/METADATA,sha256=H2Lo5Okt1MPsbpBW2CfeDYX9Yti-d8sTUOWFNAaHW8k,5225
|
11
|
+
fakesnow-0.5.1.dist-info/WHEEL,sha256=AtBG6SXL3KF_v0NxLf0ehyVOh0cold-JbJYXNGorC6Q,92
|
12
|
+
fakesnow-0.5.1.dist-info/top_level.txt,sha256=x8S-sMmvfgNm2_1w0zlIF5YlDs2hR7eNQdVA6TgmPZE,14
|
13
|
+
fakesnow-0.5.1.dist-info/RECORD,,
|
fakesnow-0.4.1.dist-info/RECORD
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
fakesnow/__init__.py,sha256=ogZl2Z61FIiU2fg8WiM1FhXYLpG-Phvg855nmuMhdqQ,2992
|
2
|
-
fakesnow/checks.py,sha256=1qVLR0ZB3z3UPij3Hm8hqlkcNLH2QJnwe8OqkoFCwv8,2356
|
3
|
-
fakesnow/expr.py,sha256=CAxuYIUkwI339DQIBzvFF0F-m1tcVGKEPA5rDTzmH9A,892
|
4
|
-
fakesnow/fakes.py,sha256=6PYHwykRDXaHM1sET-A-ZGTrDrQ0DPyjsxWgpPW-mP0,19626
|
5
|
-
fakesnow/fixtures.py,sha256=LANb4LuiUjKbTZRHmgnAi50xC1rs1xF8SHLoBikB88c,509
|
6
|
-
fakesnow/info_schema.py,sha256=4GnYuAWsX9qfQKQyTd-GkI24DHAxHCmGCst6ohcQAXY,3495
|
7
|
-
fakesnow/py.typed,sha256=B-DLSjYBi7pkKjwxCSdpVj2J02wgfJr-E7B1wOUyxYU,80
|
8
|
-
fakesnow/transforms.py,sha256=VqkxxtDu8RbetcDMBm4nMCGyzuXwpU8-0WqXkmKSEhU,22376
|
9
|
-
fakesnow-0.4.1.dist-info/LICENSE,sha256=BL6v_VTnU7xdsocviIQJMFr3stX_-uRfTyByo3gRu4M,1071
|
10
|
-
fakesnow-0.4.1.dist-info/METADATA,sha256=5rRxOoTmT7yoJ75KJf211cXrey4LWrQ1wWvoyxCzhNo,5161
|
11
|
-
fakesnow-0.4.1.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
|
12
|
-
fakesnow-0.4.1.dist-info/top_level.txt,sha256=x8S-sMmvfgNm2_1w0zlIF5YlDs2hR7eNQdVA6TgmPZE,14
|
13
|
-
fakesnow-0.4.1.dist-info/RECORD,,
|
File without changes
|
File without changes
|