fakesnow 0.9.42__py3-none-any.whl → 0.9.43__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/cursor.py CHANGED
@@ -10,7 +10,6 @@ from types import TracebackType
10
10
  from typing import TYPE_CHECKING, Any, cast
11
11
 
12
12
  import duckdb
13
- import pandas as pd
14
13
  import pyarrow # needed by fetch_arrow_table()
15
14
  import snowflake.connector.converter
16
15
  import snowflake.connector.errors
@@ -194,7 +193,7 @@ class FakeSnowflakeCursor:
194
193
 
195
194
  def _put_files(self, put_stage_data: stage.UploadCommandDict) -> None:
196
195
  results = stage.upload_files(put_stage_data)
197
- _df = pd.DataFrame.from_records(results)
196
+ _df = pyarrow.Table.from_pylist(results)
198
197
  self._duck_conn.execute("select * from _df")
199
198
  self._arrow_table = self._duck_conn.fetch_arrow_table()
200
199
  self._rowcount = self._arrow_table.num_rows
fakesnow/expr.py CHANGED
@@ -30,3 +30,14 @@ def key_command(expression: exp.Expression) -> str:
30
30
  key = expression.key.upper()
31
31
 
32
32
  return key
33
+
34
+
35
+ def normalise_ident(name: str) -> str:
36
+ """
37
+ Strip double quotes if present else return uppercased.
38
+ Snowflake treats quoted identifiers as case-sensitive and un-quoted identifiers as case-insensitive
39
+ """
40
+ if name.startswith('"') and name.endswith('"'):
41
+ return name[1:-1] # Strip quotes
42
+
43
+ return name.upper()
fakesnow/server.py CHANGED
@@ -18,6 +18,7 @@ from starlette.routing import Route
18
18
 
19
19
  from fakesnow.arrow import to_ipc, to_sf
20
20
  from fakesnow.converter import from_binding
21
+ from fakesnow.expr import normalise_ident
21
22
  from fakesnow.fakes import FakeSnowflakeConnection
22
23
  from fakesnow.instance import FakeSnow
23
24
  from fakesnow.rowtype import describe_as_rowtype
@@ -39,8 +40,8 @@ class ServerError(Exception):
39
40
 
40
41
 
41
42
  async def login_request(request: Request) -> JSONResponse:
42
- database = request.query_params.get("databaseName")
43
- schema = request.query_params.get("schemaName")
43
+ database = (d := request.query_params.get("databaseName")) and normalise_ident(d)
44
+ schema = (s := request.query_params.get("schemaName")) and normalise_ident(s)
44
45
  body = await request.body()
45
46
  if request.headers.get("Content-Encoding") == "gzip":
46
47
  body = gzip.decompress(body)
@@ -64,7 +65,10 @@ async def login_request(request: Request) -> JSONResponse:
64
65
  {"name": "AUTOCOMMIT", "value": True},
65
66
  {"name": "CLIENT_SESSION_KEEP_ALIVE_HEARTBEAT_FREQUENCY", "value": 3600},
66
67
  ],
67
- "sessionInfo": {},
68
+ "sessionInfo": {
69
+ "databaseName": database,
70
+ "schemaName": schema,
71
+ },
68
72
  },
69
73
  "success": True,
70
74
  }
@@ -147,6 +151,8 @@ async def query_request(request: Request) -> JSONResponse:
147
151
  "total": cur._rowcount, # noqa: SLF001
148
152
  "queryId": cur.sfqid,
149
153
  "queryResultFormat": "arrow",
154
+ "finalDatabaseName": conn.database,
155
+ "finalSchemaName": conn.schema,
150
156
  },
151
157
  "success": True,
152
158
  }
@@ -13,6 +13,7 @@ import sqlglot
13
13
  from snowflake.connector.file_util import SnowflakeFileUtil
14
14
  from sqlglot import exp
15
15
 
16
+ from fakesnow.expr import normalise_ident
16
17
  from fakesnow.params import MutableParams
17
18
 
18
19
  # TODO: clean up temp files on exit
@@ -198,17 +199,6 @@ def put_stage(
198
199
  return transformed
199
200
 
200
201
 
201
- def normalise_ident(name: str) -> str:
202
- """
203
- Strip double quotes if present else return uppercased.
204
- Snowflake treats quoted identifiers as case-sensitive and un-quoted identifiers as case-insensitive
205
- """
206
- if name.startswith('"') and name.endswith('"'):
207
- return name[1:-1] # Strip quotes
208
-
209
- return name.upper()
210
-
211
-
212
202
  def parts_from_var(var: str, current_database: str | None, current_schema: str | None) -> tuple[str, str, str]:
213
203
  parts = var.split(".")
214
204
  if len(parts) == 3:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fakesnow
3
- Version: 0.9.42
3
+ Version: 0.9.43
4
4
  Summary: Fake Snowflake Connector for Python. Run, mock and test Snowflake DB locally.
5
5
  License: Apache License
6
6
  Version 2.0, January 2004
@@ -420,7 +420,7 @@ Fully supported:
420
420
  - Multiple databases
421
421
  - [Parameter binding](https://docs.snowflake.com/en/user-guide/python-connector-example#binding-data) in queries
422
422
  - Table comments
423
- - Pandas integration including [write_pandas(..)](https://docs.snowflake.com/en/user-guide/python-connector-api#write_pandas) (not available via the server yet)
423
+ - Pandas integration including [write_pandas(..)](https://docs.snowflake.com/en/user-guide/python-connector-api#write_pandas)
424
424
  - Result batch retrieval via [get_result_batches()](https://docs.snowflake.com/en/user-guide/python-connector-api#get_result_batches)
425
425
  - HTTP server for non-Python connectors
426
426
 
@@ -431,7 +431,8 @@ Partially supported:
431
431
  - Semi-structured data operations
432
432
  - Tags
433
433
  - User management
434
- - `COPY INTO` from S3 sources, see [COPY INTO](#copy-into)
434
+ - Stages and PUT
435
+ - `COPY INTO` from S3 sources and stages, see [COPY INTO](#copy-into)
435
436
 
436
437
  Not yet implemented:
437
438
 
@@ -447,7 +448,7 @@ For more detail see the [test suite](tests/).
447
448
 
448
449
  ## COPY INTO
449
450
 
450
- `COPY INTO` can be used from S3 sources. By default the standard AWS credential chain will be used. If you are getting an HTTP 403 or need to provide alternative S3 credentials you can use the duckdb [CREATE SECRET](https://duckdb.org/docs/stable/extensions/httpfs/s3api) statement. For an example of creating a secret to use a moto S3 endpoint see `s3_client` in [conftest.py](tests/conftest.py#L80)
451
+ `COPY INTO` can be used from S3 sources and stages. By default the standard AWS credential chain will be used. If you are getting an HTTP 403 or need to provide alternative S3 credentials you can use the duckdb [CREATE SECRET](https://duckdb.org/docs/stable/extensions/httpfs/s3api) statement. For an example of creating a secret to use a moto S3 endpoint see `s3_client` in [conftest.py](tests/conftest.py#L80)
451
452
 
452
453
  ## Contributing
453
454
 
@@ -6,8 +6,8 @@ fakesnow/cli.py,sha256=9qfI-Ssr6mo8UmIlXkUAOz2z2YPBgDsrEVaZv9FjGFs,2201
6
6
  fakesnow/conn.py,sha256=diCwcjaCBrlCn9PyjbScfIQTNQjqiPTkQanUTqcvblE,6009
7
7
  fakesnow/converter.py,sha256=wPOfsFXIUJNJSx5oFNAxh13udxmAVIIHsLK8BiGkXGA,1635
8
8
  fakesnow/copy_into.py,sha256=utlV03RWHdWblIlKs92Q__9BWHi_gvqT76RV6tEMWTo,16006
9
- fakesnow/cursor.py,sha256=T0aI_AC8U7_mRMccGUIOs8WFby4-8O3ETHpcxJLtM38,25432
10
- fakesnow/expr.py,sha256=CAxuYIUkwI339DQIBzvFF0F-m1tcVGKEPA5rDTzmH9A,892
9
+ fakesnow/cursor.py,sha256=A1jWLGkXzHcYbM0wFrbh2PiewzFFS7ZlfOm-x3AGHgg,25412
10
+ fakesnow/expr.py,sha256=tLcHC-mx2O6-vCt77RVlRQa3CovqUdu4vc5WOSmuQdk,1231
11
11
  fakesnow/fakes.py,sha256=JQTiUkkwPeQrJ8FDWhPFPK6pGwd_aR2oiOrNzCWznlM,187
12
12
  fakesnow/fixtures.py,sha256=2rj0MTZlaZc4PNWhaqC5IiiLa7E9G0QZT3g45YawsL0,633
13
13
  fakesnow/info_schema.py,sha256=lqEYD5aWK2MamjALbj6ct7pz_1yyAq3tAk51kLa8NKk,9872
@@ -18,17 +18,17 @@ fakesnow/pandas_tools.py,sha256=wI203UQHC8JvDzxE_VjE1NeV4rThek2P-u52oTg2foo,3481
18
18
  fakesnow/params.py,sha256=Hp7tBiDycdOh8LuRoISsOZycD7DufDAMKyF_hqEjh6M,929
19
19
  fakesnow/py.typed,sha256=B-DLSjYBi7pkKjwxCSdpVj2J02wgfJr-E7B1wOUyxYU,80
20
20
  fakesnow/rowtype.py,sha256=QUp8EaXD5LT0Xv8BXk5ze4WseEn52xoJ6R05pJjs5mM,2729
21
- fakesnow/server.py,sha256=anlieEI2WO81rDv7h5-M10CetYL_HJFXWZO9wScr0Dw,7196
21
+ fakesnow/server.py,sha256=NzhpVM_3L9QeG84bhn0_It6ABM9ifs1CYWPgKhWaOeE,7511
22
22
  fakesnow/variables.py,sha256=BGnD4LAdVByfJ2GXL6qpGBaTF8ZJRjt3pdJsd9sIAcw,3134
23
23
  fakesnow/transforms/__init__.py,sha256=3dpcXjeLkfc4e9rO0G8Mnv9zZgmwsKSwQ7UJeyLYnOg,2837
24
24
  fakesnow/transforms/merge.py,sha256=H2yYyzGsxjpggS6PY91rAUtYCFuOkBm8uGi0EO0r6T0,8375
25
25
  fakesnow/transforms/show.py,sha256=NIJDkf4-ns4VTw0DQphEn2DnwxQjXyTU2wS9VSUh6Wc,19919
26
- fakesnow/transforms/stage.py,sha256=yBC0jMmUYhmHY5Of08lPxgH9R6arNUWAjL9M4ArDnjY,10344
26
+ fakesnow/transforms/stage.py,sha256=VRE122Twha1Dd7QC2rdAAWWG93OxIiJZv2DfvGSsMZ8,10047
27
27
  fakesnow/transforms/transforms.py,sha256=ykzay7J28MsifhRKhm5qJJd__hMcLNVZTT14MSdWcJs,49102
28
- fakesnow-0.9.42.dist-info/licenses/LICENSE,sha256=kW-7NWIyaRMQiDpryfSmF2DObDZHGR1cJZ39s6B1Svg,11344
28
+ fakesnow-0.9.43.dist-info/licenses/LICENSE,sha256=kW-7NWIyaRMQiDpryfSmF2DObDZHGR1cJZ39s6B1Svg,11344
29
29
  tools/decode.py,sha256=kC5kUvLQxdCkMRsnH6BqCajlKxKeN77w6rwCKsY6gqU,1781
30
- fakesnow-0.9.42.dist-info/METADATA,sha256=tYGXY_3aBbYYkLyFlajE1ebKbXT4xhyain0JLC9vfb0,20680
31
- fakesnow-0.9.42.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
- fakesnow-0.9.42.dist-info/entry_points.txt,sha256=2riAUgu928ZIHawtO8EsfrMEJhi-EH-z_Vq7Q44xKPM,47
33
- fakesnow-0.9.42.dist-info/top_level.txt,sha256=Yos7YveA3f03xVYuURqnBsfMV2DePXfu_yGcsj3pPzI,30
34
- fakesnow-0.9.42.dist-info/RECORD,,
30
+ fakesnow-0.9.43.dist-info/METADATA,sha256=tUAcWIfezqI1Lu64-sz8VToB4bFIyfaEFyOPCJpDREY,20684
31
+ fakesnow-0.9.43.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
32
+ fakesnow-0.9.43.dist-info/entry_points.txt,sha256=2riAUgu928ZIHawtO8EsfrMEJhi-EH-z_Vq7Q44xKPM,47
33
+ fakesnow-0.9.43.dist-info/top_level.txt,sha256=Yos7YveA3f03xVYuURqnBsfMV2DePXfu_yGcsj3pPzI,30
34
+ fakesnow-0.9.43.dist-info/RECORD,,