From f6e7ebe73d5d61c45db4f9543b750f20a031e912 Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 10:17:46 +0300 Subject: [PATCH 01/12] Update README.md --- README.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index e47f3afd1ce..58339e61a8d 100644 --- a/README.md +++ b/README.md @@ -14,20 +14,29 @@ ## Documentation -For reference and tutorials, see the [Firebolt Python SDK reference](https://python-sdk.docs.firebolt.io/). +For reference and tutorials, see the [Firebolt Python SDK reference](https://python-sdk.docs.firebolt.io/en/0.x/). ## Connection parameters These parameters are used to connect to a Firebolt database: -- **engine_url** - url for an engine to make requests to. Can be retrieved from Web UI, or from [engine](https://github.com/firebolt-db/firebolt-sdk/tree/main/src/firebolt/model/engine.py) attribute `endpoint` +- Username/Password authentication + - **username** - account username + - **password** - account password +- Service Account authentication + - **client_id** - service account client id + - **client_secret** - service account client secret - **database** - name of the database to make queries to -- **username** - account username -- **password** - account password +- **engine_url** - url for an engine to make requests to. Can be retrieved from Web UI, or from [engine](https://github.com/firebolt-db/firebolt-sdk/tree/0.x/src/firebolt/model/engine.py) attribute `endpoint` + (Mutually exclusive with **engine_name**) +- **engine_name** - name of an engine to make requests to. Can be retrieved from Web UI, or from [engine](https://github.com/firebolt-db/firebolt-sdk/tree/0.x/src/firebolt/model/engine.py) attribute `name` + (Mutually exclusive with **engine_url**) Optional parameters +- **account_name** - name of a Firebolt account to use. Default account is used if it's not provided +- **use_token_cache** - whether to store obtained authentication tokens in cache file. Defaults to True - **api_endpoint** - api hostname for logging in. Defaults to `api.app.firebolt.io`. ## Examples -See [PEP-249](https://www.python.org/dev/peps/pep-0249) for the DB API reference and specifications. An example [jupyter notebook](https://github.com/firebolt-db/firebolt-sdk/tree/main/examples/dbapi.ipynb) is included to illustrate the use of the Firebolt API. +See [PEP-249](https://www.python.org/dev/peps/pep-0249) for the DB API reference and specifications. An example [jupyter notebook](https://github.com/firebolt-db/firebolt-sdk/tree/0.x/examples/dbapi.ipynb) is included to illustrate the use of the Firebolt API. ## Special considerations ### Cursor objects should not be shared between threads @@ -39,7 +48,7 @@ By default, firebolt-sdk uses `datetime` module to parse date and datetime value ## Contributing -See: [CONTRIBUTING.MD](https://github.com/firebolt-db/firebolt-sdk/tree/main/CONTRIBUTING.MD) +See: [CONTRIBUTING.MD](https://github.com/firebolt-db/firebolt-sdk/tree/0.x/CONTRIBUTING.MD) ## License -The Firebolt DB API is licensed under the [Apache License Version 2.0](https://github.com/firebolt-db/firebolt-sdk/tree/main/LICENSE) software license. +The Firebolt DB API is licensed under the [Apache License Version 2.0](https://github.com/firebolt-db/firebolt-sdk/tree/0.x/LICENSE) software license. From d40aec457dee1d744aa3d72c63db7f53acf92ae5 Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 10:25:16 +0300 Subject: [PATCH 02/12] Update README_MANAGEMENT.md --- README_MANAGEMENT.md | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/README_MANAGEMENT.md b/README_MANAGEMENT.md index 8c1141685f2..04d1c7d25d3 100644 --- a/README_MANAGEMENT.md +++ b/README_MANAGEMENT.md @@ -1,7 +1,7 @@ # Resource Management ### Usage -See: [examples/management.ipynb](https://github.com/firebolt-db/firebolt-sdk/tree/main/examples/management.ipynb). +See: [examples/management.ipynb](https://github.com/firebolt-db/firebolt-sdk/tree/0.x/examples/management.ipynb). ### Configuration @@ -9,14 +9,12 @@ To use the SDK, you generally will want to set the following environment variabl ``` FIREBOLT_USER='email@domain.com' FIREBOLT_PASSWORD='*****' +FIREBOLT_ACCOUNT='my_account' FIREBOLT_SERVER='api.app.firebolt.io' FIREBOLT_DEFAULT_REGION='us-east-1' ``` -* You can store these in a `.env` file -* environment variables on your system always take precedence over those in `.env` - -Once the environment variables are defined (either on your system or in `.env`), +Once the environment variables are defined, you can initialize a ResourceManager with: ```python @@ -29,23 +27,19 @@ print(rm.regions.default_region) # see your default region Or you can configure settings manually: ```python +from firebolt.client.auth import UsernamePassword from firebolt.service.manager import ResourceManager from firebolt.common.settings import Settings -from pydantic import SecretStr rm = ResourceManager(settings=Settings( - server="api.app.firebolt.io", - user="email@domain.com", - password=SecretStr("*****"), + auth=UsernamePassword("email@domain.com", "*****") account_name="account", # Necessary if you have multiple accounts. + server="api.app.firebolt.io", default_region="us-east-1", )) print(rm.client.account_id) # see your account id ``` -Under the hood, configuration works via Pydantic, -see [here](https://pydantic-docs.helpmanual.io/usage/settings/). - ### Contributing -See: [CONTRIBUTING.MD](https://github.com/firebolt-db/firebolt-sdk/tree/main/CONTRIBUTING.MD) +See: [CONTRIBUTING.MD](https://github.com/firebolt-db/firebolt-sdk/tree/0.x/CONTRIBUTING.MD) From fd1ca1b6b6f5f2103d123e6da9762e76bf940b4f Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:06:14 +0300 Subject: [PATCH 03/12] async enhancements --- setup.cfg | 6 +-- src/firebolt/async_db/cursor.py | 10 ++--- src/firebolt/utils/util.py | 22 +---------- tests/unit/common/test_util.py | 68 --------------------------------- 4 files changed, 10 insertions(+), 96 deletions(-) delete mode 100644 tests/unit/common/test_util.py diff --git a/setup.cfg b/setup.cfg index cdbf39f41bc..036443bc417 100755 --- a/setup.cfg +++ b/setup.cfg @@ -31,8 +31,8 @@ install_requires = httpx[http2]==0.24.0 pydantic[dotenv]>=1.8.2,<2.0 python-dateutil>=2.8.2 - readerwriterlock==1.0.9 sqlparse>=0.4.2 + tricycle>=0.2.2 trio<0.22.0 python_requires = >=3.7 include_package_data = True @@ -52,11 +52,11 @@ dev = pre-commit==2.15.0 pyfakefs>=4.5.3 pytest==6.2.5 - pytest-asyncio==0.19.0 pytest-cov==3.0.0 pytest-httpx==0.22.0 pytest-mock==3.6.1 pytest-timeout==2.1.0 + pytest-trio==0.8.0 pytest-xdist==2.5.0 trio-typing[mypy]==0.6.* types-cryptography==3.3.18 @@ -91,4 +91,4 @@ docstring-convention = google inline-quotes = " [tool:pytest] -asyncio_mode = auto +trio_mode = true diff --git a/src/firebolt/async_db/cursor.py b/src/firebolt/async_db/cursor.py index 783cc931364..a5348597422 100644 --- a/src/firebolt/async_db/cursor.py +++ b/src/firebolt/async_db/cursor.py @@ -17,8 +17,8 @@ Union, ) -from aiorwlock import RWLock from httpx import Response, codes +from tricycle import RWLock from firebolt.async_db.util import is_db_available, is_engine_running from firebolt.common._types import ( @@ -438,13 +438,13 @@ async def cancel(self, query_id: str) -> None: @wraps(BaseCursor.fetchone) async def fetchone(self) -> Optional[List[ColType]]: - async with self._async_query_lock.reader: + async with self._async_query_lock.read_locked(): """Fetch the next row of a query result set.""" return super().fetchone() @wraps(BaseCursor.fetchmany) async def fetchmany(self, size: Optional[int] = None) -> List[List[ColType]]: - async with self._async_query_lock.reader: + async with self._async_query_lock.read_locked(): """ Fetch the next set of rows of a query result; size is cursor.arraysize by default. @@ -453,11 +453,11 @@ async def fetchmany(self, size: Optional[int] = None) -> List[List[ColType]]: @wraps(BaseCursor.fetchall) async def fetchall(self) -> List[List[ColType]]: - async with self._async_query_lock.reader: + async with self._async_query_lock.read_locked(): """Fetch all remaining rows of a query result.""" return super().fetchall() @wraps(BaseCursor.nextset) async def nextset(self) -> None: - async with self._async_query_lock.reader: + async with self._async_query_lock.read_locked(): return super().nextset() diff --git a/src/firebolt/utils/util.py b/src/firebolt/utils/util.py index 96ac7a1ae64..dda26917646 100644 --- a/src/firebolt/utils/util.py +++ b/src/firebolt/utils/util.py @@ -1,7 +1,6 @@ -from functools import lru_cache, partial, wraps -from typing import TYPE_CHECKING, Any, Callable, Optional, Type, TypeVar +from functools import lru_cache +from typing import TYPE_CHECKING, Callable, Optional, Type, TypeVar -import trio from httpx import URL from firebolt.utils.exception import ConfigurationError @@ -72,23 +71,6 @@ def fix_url_schema(url: str) -> str: return url if url.startswith("http") else f"https://{url}" -def async_to_sync(f: Callable) -> Callable: - """Convert async function to sync. - - Args: - f (Callable): function to convert - - Returns: - Callable: regular function, which can be executed synchronously - """ - - @wraps(f) - def sync(*args: Any, **kwargs: Any) -> Any: - return trio.run(partial(f, *args, **kwargs)) - - return sync - - def merge_urls(base: URL, merge: URL) -> URL: """Merge a base and merge urls. diff --git a/tests/unit/common/test_util.py b/tests/unit/common/test_util.py deleted file mode 100644 index 1b02b7b3dc9..00000000000 --- a/tests/unit/common/test_util.py +++ /dev/null @@ -1,68 +0,0 @@ -from asyncio import run -from threading import Thread - -from pytest import raises - -from firebolt.utils.util import async_to_sync - - -def test_async_to_sync_happy_path(): - """async_to_sync properly converts coroutine to sync function.""" - - class JobMarker(Exception): - pass - - async def task(): - raise JobMarker() - - for i in range(3): - with raises(JobMarker): - async_to_sync(task)() - - -def test_async_to_sync_thread(): - """async_to_sync works correctly in threads.""" - - marks = [False] * 3 - - async def task(id: int): - marks[id] = True - - ts = [Thread(target=async_to_sync(task), args=[i]) for i in range(3)] - [t.start() for t in ts] - [t.join() for t in ts] - assert all(marks) - - -def test_async_to_sync_after_run(): - """async_to_sync runs correctly after asyncio.run.""" - - class JobMarker(Exception): - pass - - async def task(): - raise JobMarker() - - with raises(JobMarker): - run(task()) - - # Here local event loop is closed by run - - with raises(JobMarker): - async_to_sync(task)() - - -async def test_nested_loops() -> None: - """async_to_sync works correctly inside a running loop.""" - - class JobMarker(Exception): - pass - - async def task(): - raise JobMarker() - - with raises(JobMarker): - await task() - - with raises(JobMarker): - async_to_sync(task)() From 0debafe10ad22000ec76977a6524654c6bda1a94 Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:12:59 +0300 Subject: [PATCH 04/12] update dbapi examples --- examples/dbapi.ipynb | 142 +++++++++++++++++++++---------------------- 1 file changed, 69 insertions(+), 73 deletions(-) diff --git a/examples/dbapi.ipynb b/examples/dbapi.ipynb index ee34671aa8a..34d0974ea18 100644 --- a/examples/dbapi.ipynb +++ b/examples/dbapi.ipynb @@ -17,6 +17,7 @@ "source": [ "from firebolt.db import connect\n", "from firebolt.client import DEFAULT_API_URL\n", + "from firebolt.client.auth import UsernamePassword, ServiceAccount\n", "from datetime import datetime" ] }, @@ -25,7 +26,7 @@ "id": "9cc3c3d4", "metadata": {}, "source": [ - "### Database credentials" + "### Connection parameters" ] }, { @@ -35,15 +36,29 @@ "metadata": {}, "outputs": [], "source": [ + "# Using username/password authentication\n", + "username = \"\"\n", + "password = \"\"\n", + "\n", + "# Using service account authentication\n", + "client_id = \"\"\n", + "client_secret = \"\"\n", + "\n", + "assert not (username and client_id), \"Specify only one set of credentials\"\n", + "if username and password:\n", + " auth = UsernamePassword(username, password)\n", + "else: # client_id and client_secret\n", + " auth = ServiceAccount(client_id, client_secret)\n", + "\n", "# Only one of these two parameters should be specified\n", "engine_url = \"\"\n", - "assert bool(engine_url) != bool(\n", - " engine_name\n", + "engine_name = \"\"\n", + "assert not (\n", + " engine_url and engine_name\n", "), \"Specify only one of engine_name and engine_url\"\n", "\n", "database_name = \"\"\n", - "username = \"\"\n", - "password = \"\"\n", + "account_name = \"\"\n", "api_endpoint = DEFAULT_API_URL" ] }, @@ -64,11 +79,11 @@ "source": [ "# create a connection based on provided credentials\n", "connection = connect(\n", + " auth=auth,\n", + " database=database_name,\n", " engine_url=engine_url,\n", " engine_name=engine_name,\n", - " database=database_name,\n", - " username=username,\n", - " password=password,\n", + " account_name=account_name,\n", " api_endpoint=api_endpoint,\n", ")\n", "\n", @@ -238,7 +253,7 @@ "metadata": {}, "outputs": [], "source": [ - "from firebolt.async_db import connect" + "from firebolt.async_db import connect as async_connect" ] }, { @@ -256,30 +271,18 @@ "metadata": {}, "outputs": [], "source": [ - "async def async_connect():\n", - " # create a connection based on provided credentials\n", - " connection = await connect(\n", - " engine_url=engine_url,\n", - " engine_name=engine_name,\n", - " database=database_name,\n", - " username=username,\n", - " password=password,\n", - " api_endpoint=api_endpoint,\n", - " )\n", + "# create a connection based on provided credentials\n", + "async_connection = await async_connect(\n", + " auth=auth,\n", + " database=database_name,\n", + " engine_url=engine_url,\n", + " engine_name=engine_name,\n", + " account_name=account_name,\n", + " api_endpoint=api_endpoint,\n", + ")\n", "\n", - " # create a cursor for connection\n", - " cursor = connection.cursor()\n", - " return cursor" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "58885c37", - "metadata": {}, - "outputs": [], - "source": [ - "async_cursor = await async_connect()" + "# create a cursor for connection\n", + "async_cursor = async_connection.cursor()" ] }, { @@ -297,26 +300,15 @@ "metadata": {}, "outputs": [], "source": [ - "async def run_queries(cursor):\n", - " await cursor.execute(\n", - " \"create fact table if not exists test_table (id int, name text, dt datetime) primary index id\"\n", - " )\n", - " await cursor.execute(\n", - " \"insert into test_table values (1, 'hello', '2021-01-01 01:01:01'),\"\n", - " \"(2, 'world', '2022-02-02 02:02:02'),\"\n", - " \"(3, '!', '2023-03-03 03:03:03')\"\n", - " )\n", - " await cursor.execute(\"select * from test_table\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "768fc91a", - "metadata": {}, - "outputs": [], - "source": [ - "await run_queries(async_cursor)" + "await async_cursor.execute(\n", + " \"create fact table if not exists test_table (id int, name text, dt datetime) primary index id\"\n", + ")\n", + "await async_cursor.execute(\n", + " \"insert into test_table values (1, 'hello', '2021-01-01 01:01:01'),\"\n", + " \"(2, 'world', '2022-02-02 02:02:02'),\"\n", + " \"(3, '!', '2023-03-03 03:03:03')\"\n", + ")\n", + "await async_cursor.execute(\"select * from test_table\")" ] }, { @@ -353,20 +345,9 @@ "metadata": {}, "outputs": [], "source": [ - "async def print_results(cursor):\n", - " print(await cursor.fetchone())\n", - " print(await cursor.fetchmany(1))\n", - " print(await cursor.fetchall())" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "15f24a0a", - "metadata": {}, - "outputs": [], - "source": [ - "await print_results(async_cursor)" + "print(await async_cursor.fetchone())\n", + "print(await async_cursor.fetchmany(1))\n", + "print(await async_cursor.fetchall())" ] }, { @@ -386,27 +367,42 @@ "source": [ "# manually\n", "connection.close()\n", + "print(connection.closed)\n", + "\n", + "await async_connection.aclose()\n", + "print(async_connection.closed)\n", "\n", "# using context manager\n", "with connect(\n", - " engine_url=engine_url,\n", + " auth=auth,\n", + " account_name=account_name,\n", " engine_name=engine_name,\n", " database=database_name,\n", - " username=username,\n", - " password=password,\n", " api_endpoint=api_endpoint,\n", ") as conn:\n", " # create cursors, perform database queries\n", " pass\n", - "conn.closed" + "print(conn.closed)\n", + "\n", + "# using context manager\n", + "async with await async_connect(\n", + " auth=auth,\n", + " account_name=account_name,\n", + " engine_name=engine_name,\n", + " database=database_name,\n", + " api_endpoint=api_endpoint,\n", + ") as async_conn:\n", + " # create cursors, perform database queries\n", + " pass\n", + "async_conn.closed" ] } ], "metadata": { "kernelspec": { - "display_name": "python37", + "display_name": "Python 3 Trio", "language": "python", - "name": "python37" + "name": "python3-trio" }, "language_info": { "codemirror_mode": { @@ -418,7 +414,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.7.12" + "version": "3.9.16" } }, "nbformat": 4, From c6a3faf3cdbfdd1df6b2bff4ea90478d39702d9b Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:28:05 +0300 Subject: [PATCH 05/12] update management examples --- examples/management.ipynb | 79 +++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 36 deletions(-) diff --git a/examples/management.ipynb b/examples/management.ipynb index 6f51bb99bd3..c825b596fe6 100644 --- a/examples/management.ipynb +++ b/examples/management.ipynb @@ -17,24 +17,13 @@ "source": [ "# required imports\n", "from firebolt.service.manager import ResourceManager\n", + "from firebolt.client import DEFAULT_API_URL\n", + "from firebolt.client.auth import UsernamePassword, ServiceAccount\n", "\n", "# use debug function for pretty printing\n", "from devtools import debug" ] }, - { - "cell_type": "code", - "execution_count": null, - "id": "93073ef6", - "metadata": {}, - "outputs": [], - "source": [ - "# support async_to_sync in notebooks\n", - "import nest_asyncio\n", - "\n", - "nest_asyncio.apply()" - ] - }, { "cell_type": "markdown", "id": "443e8468", @@ -109,6 +98,32 @@ "**Option 2**: Specify settings manually using the Settings object:" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "640f0efe-fe54-4cef-b1de-32a4339d3dad", + "metadata": {}, + "outputs": [], + "source": [ + "# Using username/password authentication\n", + "username = \"\"\n", + "password = \"\"\n", + "\n", + "# Using service account authentication\n", + "client_id = \"\"\n", + "client_secret = \"\"\n", + "\n", + "assert not (username and client_id), \"Specify only one set of credentials\"\n", + "if username and password:\n", + " auth = UsernamePassword(username, password)\n", + "else: # client_id and client_secret\n", + " auth = ServiceAccount(client_id, client_secret)\n", + "\n", + "account_name = \"\"\n", + "server = DEFAULT_API_URL\n", + "default_region = \"us-east-1\"" + ] + }, { "cell_type": "code", "execution_count": null, @@ -119,10 +134,10 @@ "from firebolt.common import Settings\n", "\n", "settings = Settings(\n", - " server=\"\", # api.app.firebolt.io\n", - " user=\"\",\n", - " password=\"\",\n", - " default_region=\"\", # us-east-1\n", + " auth=auth,\n", + " account_name=account_name,\n", + " server=server,\n", + " default_region=default_region,\n", ")" ] }, @@ -170,8 +185,8 @@ "import time\n", "\n", "default_name = f\"temp_{int(time.time())}\"\n", - "database_name = \"\" or default_name\n", - "engine_name = \"\" or default_name" + "database_name = default_name # Change to use you own name for creating a new database\n", + "engine_name = default_name # Change to use you own name for creating a new engine" ] }, { @@ -260,9 +275,7 @@ "cell_type": "code", "execution_count": null, "id": "9dad9f23", - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [], "source": [ "engine = rm.engines.create(name=engine_name)\n", @@ -340,12 +353,10 @@ "metadata": {}, "outputs": [], "source": [ - "connection = engine.get_connection()\n", - "cursor = connection.cursor()\n", - "result = cursor.execute(\"select 1\")\n", - "debug(result)\n", - "\n", - "cursor.close()" + "with engine.get_connection() as connection:\n", + " with connection.cursor() as cursor:\n", + " result = cursor.execute(\"select 1\")\n", + " debug(result)" ] }, { @@ -360,9 +371,7 @@ "cell_type": "code", "execution_count": null, "id": "a069e9eb", - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [], "source": [ "stopped_engine = engine.stop()\n", @@ -411,13 +420,11 @@ "cell_type": "code", "execution_count": null, "id": "8372e49f", - "metadata": { - "scrolled": false - }, + "metadata": {}, "outputs": [], "source": [ "debug(rm.regions.default_region)\n", - "debug(rm.instance_types.get_by_name(instance_type_name=\"i3.4xlarge\"))" + "debug(rm.instance_types.get_by_name(instance_type_name=\"B2\"))" ] } ], @@ -437,7 +444,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.8.12" + "version": "3.9.16" } }, "nbformat": 4, From 5d710988b755e9d6dbcb7c2fb3b8c4e4d8021e20 Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:38:05 +0300 Subject: [PATCH 06/12] fix dependency issues --- setup.cfg | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 036443bc417..1a147409a53 100755 --- a/setup.cfg +++ b/setup.cfg @@ -33,7 +33,7 @@ install_requires = python-dateutil>=2.8.2 sqlparse>=0.4.2 tricycle>=0.2.2 - trio<0.22.0 + trio>=0.22.0 python_requires = >=3.7 include_package_data = True package_dir = @@ -51,7 +51,7 @@ dev = mypy==0.910 pre-commit==2.15.0 pyfakefs>=4.5.3 - pytest==6.2.5 + pytest==7.2.0 pytest-cov==3.0.0 pytest-httpx==0.22.0 pytest-mock==3.6.1 From 69e33cfe48205d14fa9bc9c1bc6defcc3b9d9b11 Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:45:33 +0300 Subject: [PATCH 07/12] fix mypy issue --- src/firebolt/db/cursor.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/firebolt/db/cursor.py b/src/firebolt/db/cursor.py index 8790fdef8e8..ec4327a8c04 100644 --- a/src/firebolt/db/cursor.py +++ b/src/firebolt/db/cursor.py @@ -18,7 +18,7 @@ from httpx import Client as HttpxClient from httpx import Response, codes -from readerwriterlock.rwlock import RWLockWrite +from readerwriterlock.rwlock import RWLockWrite # type: ignore from firebolt.common._types import ( ColType, From 1636db04ccc84d02c896c5768af4c57736a69e5b Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:47:22 +0300 Subject: [PATCH 08/12] Use DEFAULT_API_URL in readme --- README_MANAGEMENT.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README_MANAGEMENT.md b/README_MANAGEMENT.md index 04d1c7d25d3..07e6a0f2968 100644 --- a/README_MANAGEMENT.md +++ b/README_MANAGEMENT.md @@ -27,6 +27,7 @@ print(rm.regions.default_region) # see your default region Or you can configure settings manually: ```python +from firebolt.client import DEFAULT_API_URL from firebolt.client.auth import UsernamePassword from firebolt.service.manager import ResourceManager from firebolt.common.settings import Settings @@ -34,7 +35,7 @@ from firebolt.common.settings import Settings rm = ResourceManager(settings=Settings( auth=UsernamePassword("email@domain.com", "*****") account_name="account", # Necessary if you have multiple accounts. - server="api.app.firebolt.io", + server=DEFAULT_API_URL, default_region="us-east-1", )) print(rm.client.account_id) # see your account id From 59f00678b6a70066e69bd43934f9af1d7ef31787 Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:49:44 +0300 Subject: [PATCH 09/12] fix more mypy issues --- src/firebolt/db/connection.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/firebolt/db/connection.py b/src/firebolt/db/connection.py index cf591c13eef..95a4be60a68 100644 --- a/src/firebolt/db/connection.py +++ b/src/firebolt/db/connection.py @@ -10,7 +10,7 @@ from httpcore._backends.base import NetworkStream from httpcore._backends.sync import SyncBackend from httpx import HTTPStatusError, HTTPTransport, RequestError, Timeout -from readerwriterlock.rwlock import RWLockWrite +from readerwriterlock.rwlock import RWLockWrite # type: ignore from firebolt.client import DEFAULT_API_URL, Client from firebolt.client.auth import Auth, _get_auth From b1ca75d4c3d37ff04164792d0d237c61b4f581d6 Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:53:22 +0300 Subject: [PATCH 10/12] add missing dependency --- setup.cfg | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.cfg b/setup.cfg index 1a147409a53..2df8b5d9e73 100755 --- a/setup.cfg +++ b/setup.cfg @@ -26,6 +26,7 @@ install_requires = aiorwlock==1.1.0 appdirs>=1.4.4 appdirs-stubs>=0.1.0 + async-generator>=1.10 cryptography>=3.4.0 httpcore>=0.17.3 httpx[http2]==0.24.0 From e540e421063a7467c7f6148a5061cc7dd131b57c Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 11:56:17 +0300 Subject: [PATCH 11/12] add one more missing dependency --- setup.cfg | 1 + src/firebolt/db/connection.py | 2 +- src/firebolt/db/cursor.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/setup.cfg b/setup.cfg index 2df8b5d9e73..e8eecb4099e 100755 --- a/setup.cfg +++ b/setup.cfg @@ -32,6 +32,7 @@ install_requires = httpx[http2]==0.24.0 pydantic[dotenv]>=1.8.2,<2.0 python-dateutil>=2.8.2 + readerwriterlock>=1.0.9 sqlparse>=0.4.2 tricycle>=0.2.2 trio>=0.22.0 diff --git a/src/firebolt/db/connection.py b/src/firebolt/db/connection.py index 95a4be60a68..cf591c13eef 100644 --- a/src/firebolt/db/connection.py +++ b/src/firebolt/db/connection.py @@ -10,7 +10,7 @@ from httpcore._backends.base import NetworkStream from httpcore._backends.sync import SyncBackend from httpx import HTTPStatusError, HTTPTransport, RequestError, Timeout -from readerwriterlock.rwlock import RWLockWrite # type: ignore +from readerwriterlock.rwlock import RWLockWrite from firebolt.client import DEFAULT_API_URL, Client from firebolt.client.auth import Auth, _get_auth diff --git a/src/firebolt/db/cursor.py b/src/firebolt/db/cursor.py index ec4327a8c04..8790fdef8e8 100644 --- a/src/firebolt/db/cursor.py +++ b/src/firebolt/db/cursor.py @@ -18,7 +18,7 @@ from httpx import Client as HttpxClient from httpx import Response, codes -from readerwriterlock.rwlock import RWLockWrite # type: ignore +from readerwriterlock.rwlock import RWLockWrite from firebolt.common._types import ( ColType, From a7d601c4e503db0bf747b2f689c37da1a7f1609a Mon Sep 17 00:00:00 2001 From: Stepan Burlakov Date: Wed, 9 Aug 2023 12:01:59 +0300 Subject: [PATCH 12/12] fix async tests --- tests/unit/async_db/conftest.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/tests/unit/async_db/conftest.py b/tests/unit/async_db/conftest.py index 35470220c96..f0a1c61268c 100644 --- a/tests/unit/async_db/conftest.py +++ b/tests/unit/async_db/conftest.py @@ -2,14 +2,13 @@ from typing import Dict from pytest import fixture -from pytest_asyncio import fixture as asyncio_fixture from firebolt.async_db import ARRAY, DECIMAL, Connection, Cursor, connect from firebolt.common.settings import Settings from tests.unit.db_conftest import * # noqa -@asyncio_fixture +@fixture async def connection(settings: Settings, db_name: str) -> Connection: async with ( await connect( @@ -24,7 +23,7 @@ async def connection(settings: Settings, db_name: str) -> Connection: yield connection -@asyncio_fixture +@fixture async def cursor(connection: Connection, settings: Settings) -> Cursor: return connection.cursor()