Skip to content

Commit 9f7c796

Browse files
authored
Merge pull request #1221 from matteomorlack/feature/register-filesystems
feat: register filesystems
2 parents df0b697 + 4c6ac4e commit 9f7c796

File tree

5 files changed

+106
-14
lines changed

5 files changed

+106
-14
lines changed

README.md

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@
55
Basic SQLAlchemy driver for [DuckDB](https://duckdb.org/)
66

77
<!--ts-->
8-
* [duckdb_engine](#duckdb_engine)
9-
* [Installation](#installation)
10-
* [Usage](#usage)
11-
* [Usage in IPython/Jupyter](#usage-in-ipythonjupyter)
12-
* [Configuration](#configuration)
13-
* [How to register a pandas DataFrame](#how-to-register-a-pandas-dataframe)
14-
* [Things to keep in mind](#things-to-keep-in-mind)
15-
* [Auto-incrementing ID columns](#auto-incrementing-id-columns)
16-
* [Pandas read_sql() chunksize](#pandas-read_sql-chunksize)
17-
* [Unsigned integer support](#unsigned-integer-support)
18-
* [Alembic Integration](#alembic-integration)
19-
* [Preloading extensions (experimental)](#preloading-extensions-experimental)
20-
* [The name](#the-name)
8+
- [duckdb\_engine](#duckdb_engine)
9+
- [Installation](#installation)
10+
- [Usage](#usage)
11+
- [Usage in IPython/Jupyter](#usage-in-ipythonjupyter)
12+
- [Configuration](#configuration)
13+
- [How to register a pandas DataFrame](#how-to-register-a-pandas-dataframe)
14+
- [Things to keep in mind](#things-to-keep-in-mind)
15+
- [Auto-incrementing ID columns](#auto-incrementing-id-columns)
16+
- [Pandas `read_sql()` chunksize](#pandas-read_sql-chunksize)
17+
- [Unsigned integer support](#unsigned-integer-support)
18+
- [Alembic Integration](#alembic-integration)
19+
- [Preloading extensions (experimental)](#preloading-extensions-experimental)
20+
- [Registering Filesystems](#registering-filesystems)
21+
- [The name](#the-name)
2122

2223
<!-- Created by https://github.com/ekalinin/github-markdown-toc -->
2324
<!-- Added by: me, at: Wed 20 Sep 2023 12:44:27 AWST -->
@@ -180,6 +181,24 @@ create_engine(
180181
)
181182
```
182183

184+
## Registering Filesystems
185+
186+
> DuckDB allows registering filesystems from [fsspec](https://filesystem-spec.readthedocs.io/), see [documentation](https://duckdb.org/docs/guides/python/filesystems.html) for more information.
187+
188+
Support is provided under `connect_args` parameter
189+
190+
```python
191+
from sqlalchemy import create_engine
192+
from fsspec import filesystem
193+
194+
create_engine(
195+
'duckdb:///:memory:',
196+
connect_args={
197+
'register_filesystems': [filesystem('gcs')],
198+
}
199+
)
200+
```
201+
183202
## The name
184203

185204
Yes, I'm aware this package should be named `duckdb-driver` or something, I wasn't thinking when I named it and it's too hard to change the name now

duckdb_engine/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,16 @@ def connect(self, *cargs: Any, **cparams: Any) -> "Connection":
296296
user_agent = f"{user_agent} {config['custom_user_agent']}"
297297
config["custom_user_agent"] = user_agent
298298

299+
filesystems = cparams.pop("register_filesystems", [])
300+
299301
conn = duckdb.connect(*cargs, **cparams)
300302

301303
for extension in preload_extensions:
302304
conn.execute(f"LOAD {extension}")
303305

306+
for filesystem in filesystems:
307+
conn.register_filesystem(filesystem)
308+
304309
apply_config(self, conn, ext)
305310

306311
return ConnectionWrapper(conn)

duckdb_engine/tests/test_basic.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from typing import Any, Generic, Optional, TypeVar, cast
88

99
import duckdb
10+
import fsspec
1011
import sqlalchemy
1112
from hypothesis import assume, given, settings
1213
from hypothesis.strategies import text as text_strat
@@ -689,3 +690,18 @@ def test_reserved_keywords(engine: Engine) -> None:
689690
stmt = select(column("qualify"))
690691

691692
assert str(stmt.compile(engine)) == 'SELECT "qualify"'
693+
694+
695+
def test_register_filesystem() -> None:
696+
memory_fs = fsspec.filesystem("memory")
697+
file_fs = fsspec.filesystem("file")
698+
engine = create_engine(
699+
"duckdb:///",
700+
connect_args={
701+
"register_filesystems": [memory_fs, file_fs],
702+
},
703+
)
704+
705+
with engine.connect() as conn:
706+
duckdb_conn = getattr(conn.connection.dbapi_connection, "_ConnectionWrapper__c")
707+
assert duckdb.list_filesystems(connection=duckdb_conn) == ["memory", "file"]

poetry.lock

Lines changed: 52 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ pytest-cov = {extras = ["coverage"], version = "^5.0.0"}
3333
pytest-remotedata = "^0.4.0"
3434
pytest-snapshot = ">=0.9.0,<1"
3535
toml = "^0.10.2"
36+
fsspec = "^2025.2.0"
3637

3738
[tool.poetry.group.devtools.dependencies]
3839
pdbpp = "^0.10.3"

0 commit comments

Comments
 (0)