quillsql 2.1.6__py3-none-any.whl → 2.2.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.
@@ -1,19 +1,20 @@
1
- import json
2
-
3
1
  def remove_fields(query_result, fields_to_remove):
4
- fields = [
5
- {"name": field['name'], "dataTypeID": field['dataTypeID']}
6
- for field in query_result['fields']
7
- if field['name'] not in fields_to_remove
8
- ]
9
- rows = [row for row in query_result['rows']]
10
- for row in rows:
11
- for field in fields_to_remove:
12
- if field in row:
13
- del row[field]
14
- return {"fields": fields, "rows": rows}
2
+ fields = [
3
+ {"name": field["name"], "dataTypeID": field["dataTypeID"]}
4
+ for field in query_result["fields"]
5
+ if field["name"] not in fields_to_remove
6
+ ]
7
+ rows = [row for row in query_result["rows"]]
8
+ for row in rows:
9
+ for field in fields_to_remove:
10
+ if field in row:
11
+ del row[field]
12
+ return {"fields": fields, "rows": rows}
13
+
15
14
 
16
15
  def array_to_map(queries, array_to_map, metadata, target_pool):
17
- for i in range(len(queries)):
18
- query_result = target_pool.query(queries[i])
19
- metadata[array_to_map.get("arrayName")][i][array_to_map.get("field")] = query_result.get("rows")
16
+ mapped_array = []
17
+ for i in range(len(queries)):
18
+ query_result = target_pool.query(queries[i])
19
+ mapped_array.append(query_result.get("rows"))
20
+ return mapped_array
@@ -1,6 +1,9 @@
1
1
  from quillsql.assets.pgtypes import PG_TYPES
2
2
 
3
+
3
4
  def convert_type_to_postgres(data_type_id):
4
- # find the object in PG_TYPES that matches the type
5
- pg_type = next((pg_type for pg_type in PG_TYPES if pg_type['oid'] == data_type_id), None)
6
- return pg_type['typname'] if pg_type else data_type_id
5
+ # find the object in PG_TYPES that matches the type
6
+ pg_type = next(
7
+ (pg_type for pg_type in PG_TYPES if pg_type["oid"] == data_type_id), None
8
+ )
9
+ return pg_type["typname"] if pg_type else data_type_id
@@ -0,0 +1,60 @@
1
+ from typing import Union, List, Dict
2
+
3
+ # Type aliases for clarity
4
+ TenantId = Union[str, int]
5
+ TenantInfo = Dict[str, Union[str, List[TenantId]]]
6
+ Tenants = Union[List[TenantId], List[TenantInfo]]
7
+
8
+ def extract_tenant_ids(tenants: Tenants) -> List[TenantId]:
9
+ """
10
+ Extract tenant IDs from the tenants parameter, which can be either a list of IDs
11
+ or a list of tenant info dictionaries.
12
+
13
+ Args:
14
+ tenants: Either a list of tenant IDs (strings/integers) or a list of tenant info dictionaries
15
+
16
+ Returns:
17
+ List of tenant IDs
18
+
19
+ Raises:
20
+ ValueError: If the tenants parameter format is invalid
21
+ """
22
+ if not tenants:
23
+ raise ValueError("Invalid format for tenants: empty list")
24
+
25
+ first_tenant = tenants[0]
26
+
27
+ if isinstance(first_tenant, (str, int)):
28
+ return tenants # type: ignore
29
+ elif isinstance(first_tenant, dict) and "tenantIds" in first_tenant:
30
+ # TODO: support multiple tenants in future
31
+ return first_tenant["tenantIds"]
32
+ else:
33
+ raise ValueError("Invalid format for tenants")
34
+
35
+ def extract_tenant_field(tenants: Tenants, dashboard_owner: str) -> str:
36
+ """
37
+ Extract tenant field from the tenants parameter, falling back to dashboard_owner
38
+ if tenants is a simple list of IDs.
39
+
40
+ Args:
41
+ tenants: Either a list of tenant IDs (strings/integers) or a list of tenant info dictionaries
42
+ dashboard_owner: The default tenant field to use if tenants is a simple list
43
+
44
+ Returns:
45
+ The tenant field string
46
+
47
+ Raises:
48
+ ValueError: If the tenants parameter format is invalid
49
+ """
50
+ if not tenants:
51
+ raise ValueError("Invalid format for tenants: empty list")
52
+
53
+ first_tenant = tenants[0]
54
+
55
+ if isinstance(first_tenant, (str, int)):
56
+ return dashboard_owner
57
+ elif isinstance(first_tenant, dict) and "tenantField" in first_tenant:
58
+ return first_tenant["tenantField"]
59
+ else:
60
+ raise ValueError("Invalid format for tenants")
@@ -0,0 +1,69 @@
1
+ Metadata-Version: 2.4
2
+ Name: quillsql
3
+ Version: 2.2.1
4
+ Summary: Quill SDK for Python.
5
+ Home-page: https://github.com/quill-sql/quill-python
6
+ Author: Quill
7
+ Author-email: shawn@quill.co
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: psycopg2-binary
10
+ Requires-Dist: requests
11
+ Requires-Dist: redis
12
+ Requires-Dist: python-dotenv
13
+ Requires-Dist: pytest
14
+ Requires-Dist: google-cloud-bigquery
15
+ Requires-Dist: google-auth
16
+ Dynamic: author
17
+ Dynamic: author-email
18
+ Dynamic: description
19
+ Dynamic: description-content-type
20
+ Dynamic: home-page
21
+ Dynamic: requires-dist
22
+ Dynamic: summary
23
+
24
+ # Quill Python SDK
25
+
26
+ ## Quickstart
27
+
28
+ First, install the quillsql package by running:
29
+
30
+ ```bash
31
+ $ pip install quillsql
32
+ ```
33
+
34
+ Then, add a `/quill` endpoint to your existing python server. For example, if
35
+ you were running a FASTAPI app, you would just add the endpoint like this:
36
+
37
+ ```python
38
+ from quillsql import Quill
39
+
40
+ quill = Quill(
41
+ private_key=os.getenv("QULL_PRIVATE_KEY"),
42
+ database_connection_string=os.getenv("POSTGRES_READ"),
43
+ database_type="postgresql"
44
+ )
45
+
46
+ security = HTTPBearer()
47
+
48
+ async def authenticate_jwt(token: str = Depends(security)):
49
+ # Your JWT validation logic here
50
+ # Return user object or raise HTTPException
51
+ user = validate_jwt_token(token.credentials)
52
+ return user
53
+
54
+ @app.post("/quill")
55
+ async def quill_post(data: Request, user: dict = Depends(authenticate_jwt)):
56
+ # assuming user fetched via auth middleware has an userId
57
+ user_id = user["user_id"]
58
+ body = await data.json()
59
+ metadata = body.get("metadata")
60
+
61
+ result = quill.query(
62
+ tenants=[{"tenantField": "user_id", "tenantIds": [user_id]}],
63
+ metadata=metadata
64
+ )
65
+ return result
66
+ ```
67
+
68
+ Then you can run your app like normally. Pass in this route to our react library
69
+ on the frontend and you all set!
@@ -0,0 +1,20 @@
1
+ quillsql/__init__.py,sha256=FiuoxaNZveKXOPB0hkpfGNlpZKmSn3pRwcqm9HKYbCQ,180
2
+ quillsql/core.py,sha256=cWWu_ME3kapzv1fBhoJLmkA7QIlbVCAOMHyce_VE3BU,22464
3
+ quillsql/error.py,sha256=n9VKHw4FAgg7ZEAz2YQ8L_8FdRG_1shwGngf2iWhUSM,175
4
+ quillsql/assets/__init__.py,sha256=oXQ2ZS5XDXkXTYjADxNfGt55cIn_rqfgWL2EDqjTyoI,45
5
+ quillsql/assets/pgtypes.py,sha256=-B_2wUaoAsdX7_HnJhUlx4ptZQ6x-cXwuST9ACgGFdE,33820
6
+ quillsql/db/__init__.py,sha256=sPgYMF3eqKuc2k96i1Re8NHazLdGKCVN-rs15F1sovw,63
7
+ quillsql/db/bigquery.py,sha256=xJv3WUjyDmnfwaAAeLTTezUEw_qxrxQy-CTCwj8Hmjs,4811
8
+ quillsql/db/cached_connection.py,sha256=Pp0R2XGY-QuQYh8ThiDxSwNb6SEuEKfZcQRcvzjeC28,2556
9
+ quillsql/db/db_helper.py,sha256=qiIP-BM7R-3PhvWBELYjNazi-92EcQB0q9eN7Ej7XUA,2111
10
+ quillsql/db/postgres.py,sha256=ZTLtUVTJHkqAj7nZkcwbmkSOwR2ySN7vS5snoxqLRN0,4156
11
+ quillsql/utils/__init__.py,sha256=C2k9Xe0sG5XrP0XJo9K_-iej1S9PLMRKOYMeLxj7NYE,210
12
+ quillsql/utils/filters.py,sha256=REXOLIQZDHL4EDKtConXY9_GaqUmc2uTcyUa2_4MvAg,6786
13
+ quillsql/utils/pivot_template.py,sha256=NzHO7Ux8GVAKY-DUtsOmE7TUls2q6FJG2kgJxVWq-wQ,18282
14
+ quillsql/utils/run_query_processes.py,sha256=FRmNvjTDLUBr7MqDKQmivdC0anwybMXUyzQbKnaZx70,698
15
+ quillsql/utils/schema_conversion.py,sha256=TFfMibN9nOsxNRhHw5YIFl3jGTvipG81bxX4LFDulUY,314
16
+ quillsql/utils/tenants.py,sha256=ZD2FuKz0gjBVSsThHDv1P8PU6EL8E009NWihE5hAH-Q,2022
17
+ quillsql-2.2.1.dist-info/METADATA,sha256=AImLKL4nUys0Yz6i_12iPMHLxi4q5KHnxZJWRoIyw7U,1786
18
+ quillsql-2.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
19
+ quillsql-2.2.1.dist-info/top_level.txt,sha256=eU2vHnVqwpYQJ3ADl1Q-DIBzbYejZRUhcMdN_4zMCz8,9
20
+ quillsql-2.2.1.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.42.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,72 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: quillsql
3
- Version: 2.1.6
4
- Summary: Quill SDK for Python.
5
- Home-page: https://github.com/quill-sql/quill-python
6
- Author: Quill
7
- Author-email: shawn@quillsql.com
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: psycopg2-binary
10
- Requires-Dist: requests
11
- Requires-Dist: redis
12
- Requires-Dist: python-dotenv
13
- Requires-Dist: pytest
14
- Requires-Dist: google-cloud-bigquery
15
- Requires-Dist: google-auth
16
-
17
- # Quill Python SDK
18
-
19
- ## Quickstart
20
-
21
- First, install the quillsql package by running:
22
-
23
- ```bash
24
- $ pip install quillsql
25
- ```
26
-
27
- Then, add a `/quill` endpoint to your existing python server. For example, if
28
- you were running a FASTAPI app, you would just add the endpoint like this:
29
-
30
- ```python
31
- from quillsql import Quill
32
- from fastapi import FastAPI, Request
33
-
34
- app = FastAPI()
35
-
36
- quill = Quill(
37
- private_key=<YOUR_PRIVATE_KEY_HERE>,
38
- database_connection_string=<YOUR_DB_CONNECTION_STRING_HERE>,
39
- )
40
-
41
- # ... your existing endpoints here ...
42
-
43
- @app.post("/quill")
44
- async def quill_post(data: Request):
45
- body = await data.json()
46
- return quill.query(org_id="2", data=body)
47
- ```
48
-
49
- Then you can run your app like normally. Pass in this route to our react library
50
- on the frontend and you all set!
51
-
52
- ## For local testing (dev purposes only)
53
-
54
- ```
55
- pipenv install
56
- pipenv shell
57
- uvicorn examples.fastapi-server.app:app --reload --port 3000
58
- ```
59
-
60
- You are now ready to ping your local server at http://localhost:3000.
61
-
62
- ## Troubleshooting
63
-
64
- If you run into issues with `Library not loaded: @rpath/libpq.5.dylib` or `no LC_RPATH's found`, try uninstalling and reinstalling postgres on your machine. For example, using homebrew:
65
-
66
- ```bash
67
- $ brew uninstall c
68
- $ brew update
69
- $ brew install postgresql
70
- ```
71
-
72
- If you're still having this issue, this resource might also be useful for you: https://www.psycopg.org/docs/install.html.
@@ -1,17 +0,0 @@
1
- quillsql/__init__.py,sha256=xxVDrfIXLIbt45yHKGYRbqmgXSPe03uNbqENMLUnUC8,70
2
- quillsql/core.py,sha256=cCoCLwudlfmOj-o2hW-7Bwx5-XrCvXxQg3iNpTDX6z0,7670
3
- quillsql/error.py,sha256=XltjRgdBcq3lQN0KdUba5eDzA21yQ7KisIjvqqUSELI,161
4
- quillsql/assets/__init__.py,sha256=PX43SCko4w5P197YXghGI2VAq3-X1J91IO_tWY7rpiM,44
5
- quillsql/assets/pgtypes.py,sha256=qWAcGO6QfWN6XXtGI7cMreNSeTjw-xNgcc1aLoq9EV0,40768
6
- quillsql/db/__init__.py,sha256=mBGMd22nAtp9CdTpEG1Ty47zvSpO8gGejORCACF3-3c,62
7
- quillsql/db/bigquery.py,sha256=Hzs2DjJ9p8l-HywvaaAk5PbadueNgTVDyDMpCGTcd48,4220
8
- quillsql/db/cached_connection.py,sha256=1y_GzW5mIAYpmGKJjxpBqmFafpmgUA0Qm9oW_ufyPko,2570
9
- quillsql/db/db_helper.py,sha256=PFAcX2V26sIaR-hF8orGGltKXdEzR5b_enMSOHlAMUg,2054
10
- quillsql/db/postgres.py,sha256=iw71feFvnCDBMKpeGbhiJ_4Z4h7AlUi4Hk12Pfyzx6c,2799
11
- quillsql/utils/__init__.py,sha256=jJLp0OkFQdWohu8vIijfggiWf4eWmeAafVzx3YpdE4E,75
12
- quillsql/utils/run_query_processes.py,sha256=hElCVACq6bz1_jVIjQUrZzI1CPY188I3_5sHc21jtOc,673
13
- quillsql/utils/schema_conversion.py,sha256=MwFk95SIZ8OX5EAv141QXLjmCef-1z8jiVKlW71-sk8,297
14
- quillsql-2.1.6.dist-info/METADATA,sha256=HNtsQyw_xKnQasZ5OKDvKNZf_1OS_qCbPQguu-YTk_U,1809
15
- quillsql-2.1.6.dist-info/WHEEL,sha256=oiQVh_5PnQM0E3gPdiz09WCNmwiHDMaGer_elqB3coM,92
16
- quillsql-2.1.6.dist-info/top_level.txt,sha256=eU2vHnVqwpYQJ3ADl1Q-DIBzbYejZRUhcMdN_4zMCz8,9
17
- quillsql-2.1.6.dist-info/RECORD,,