44from shutil import copyfileobj
55from typing import Callable
66
7- from pytest import MonkeyPatch , fixture , importorskip , mark , raises
7+ import pytest
88
99import duckdb
1010from duckdb import DuckDBPyConnection , InvalidInputException
1111
12- importorskip ("fsspec" , "2022.11.0" )
13- from fsspec import AbstractFileSystem , filesystem
14- from fsspec .implementations .local import LocalFileOpener , LocalFileSystem
15- from fsspec .implementations .memory import MemoryFileSystem
12+ fsspec = pytest .importorskip ("fsspec" , "2022.11.0" )
1613
1714FILENAME = "integers.csv"
1815
1916logging .basicConfig (level = logging .DEBUG )
2017
2118
22- def intercept (monkeypatch : MonkeyPatch , obj : object , name : str ) -> list [str ]:
19+ def intercept (monkeypatch : pytest . MonkeyPatch , obj : object , name : str ) -> list [str ]:
2320 error_occurred = []
2421 orig = getattr (obj , name )
2522
@@ -34,15 +31,15 @@ def ceptor(*args, **kwargs):
3431 return error_occurred
3532
3633
37- @fixture
34+ @pytest . fixture
3835def duckdb_cursor ():
3936 with duckdb .connect () as conn :
4037 yield conn
4138
4239
43- @fixture
40+ @pytest . fixture
4441def memory ():
45- fs = filesystem ("memory" , skip_instance_cache = True )
42+ fs = fsspec . filesystem ("memory" , skip_instance_cache = True )
4643
4744 # ensure each instance is independent (to work around a weird quirk in fsspec)
4845 fs .store = {}
@@ -60,10 +57,10 @@ def add_file(fs, filename=FILENAME):
6057
6158class TestPythonFilesystem :
6259 def test_unregister_non_existent_filesystem (self , duckdb_cursor : DuckDBPyConnection ):
63- with raises (InvalidInputException ):
60+ with pytest . raises (InvalidInputException ):
6461 duckdb_cursor .unregister_filesystem ("fake" )
6562
66- def test_memory_filesystem (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
63+ def test_memory_filesystem (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
6764 duckdb_cursor .register_filesystem (memory )
6865
6966 assert memory .protocol == "memory"
@@ -75,8 +72,8 @@ def test_memory_filesystem(self, duckdb_cursor: DuckDBPyConnection, memory: Abst
7572 duckdb_cursor .unregister_filesystem ("memory" )
7673
7774 def test_reject_abstract_filesystem (self , duckdb_cursor : DuckDBPyConnection ):
78- with raises (InvalidInputException ):
79- duckdb_cursor .register_filesystem (AbstractFileSystem ())
75+ with pytest . raises (InvalidInputException ):
76+ duckdb_cursor .register_filesystem (fsspec . AbstractFileSystem ())
8077
8178 def test_unregister_builtin (self , require : Callable [[str ], DuckDBPyConnection ]):
8279 duckdb_cursor = require ("httpfs" )
@@ -85,10 +82,10 @@ def test_unregister_builtin(self, require: Callable[[str], DuckDBPyConnection]):
8582 assert not duckdb_cursor .filesystem_is_registered ("S3FileSystem" )
8683
8784 def test_multiple_protocol_filesystems (self , duckdb_cursor : DuckDBPyConnection ):
88- class ExtendedMemoryFileSystem (MemoryFileSystem ):
85+ class ExtendedMemoryFileSystem (fsspec . implementations . memory . MemoryFileSystem ):
8986 protocol = ("file" , "local" )
9087 # defer to the original implementation that doesn't hardcode the protocol
91- _strip_protocol = classmethod (AbstractFileSystem ._strip_protocol .__func__ )
88+ _strip_protocol = classmethod (fsspec . AbstractFileSystem ._strip_protocol .__func__ )
9289
9390 memory = ExtendedMemoryFileSystem (skip_instance_cache = True )
9491 add_file (memory )
@@ -98,14 +95,14 @@ class ExtendedMemoryFileSystem(MemoryFileSystem):
9895
9996 assert duckdb_cursor .fetchall () == [(1 , 10 , 0 ), (2 , 50 , 30 )]
10097
101- def test_write (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
98+ def test_write (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
10299 duckdb_cursor .register_filesystem (memory )
103100
104101 duckdb_cursor .execute ("copy (select 1) to 'memory://01.csv' (FORMAT CSV, HEADER 0)" )
105102
106103 assert memory .open ("01.csv" ).read () == b"1\n "
107104
108- def test_null_bytes (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
105+ def test_null_bytes (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
109106 with memory .open ("test.csv" , "wb" ) as fh :
110107 fh .write (b"hello\n \0 world\0 " )
111108 duckdb_cursor .register_filesystem (memory )
@@ -114,7 +111,7 @@ def test_null_bytes(self, duckdb_cursor: DuckDBPyConnection, memory: AbstractFil
114111
115112 assert duckdb_cursor .fetchall () == [("hello" ,), ("\0 world\0 " ,)]
116113
117- def test_read_parquet (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
114+ def test_read_parquet (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
118115 filename = "binary_string.parquet"
119116 add_file (memory , filename )
120117
@@ -124,23 +121,23 @@ def test_read_parquet(self, duckdb_cursor: DuckDBPyConnection, memory: AbstractF
124121
125122 assert duckdb_cursor .fetchall () == [(b"foo" ,), (b"bar" ,), (b"baz" ,)]
126123
127- def test_write_parquet (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
124+ def test_write_parquet (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
128125 duckdb_cursor .register_filesystem (memory )
129126 filename = "output.parquet"
130127
131128 duckdb_cursor .execute (f"""COPY (SELECT 1) TO 'memory://{ filename } ' (FORMAT PARQUET);""" )
132129
133130 assert memory .open (filename ).read ().startswith (b"PAR1" )
134131
135- def test_when_fsspec_not_installed (self , duckdb_cursor : DuckDBPyConnection , monkeypatch : MonkeyPatch ):
132+ def test_when_fsspec_not_installed (self , duckdb_cursor : DuckDBPyConnection , monkeypatch : pytest . MonkeyPatch ):
136133 monkeypatch .setitem (sys .modules , "fsspec" , None )
137134
138- with raises (ModuleNotFoundError ):
135+ with pytest . raises (ModuleNotFoundError ):
139136 duckdb_cursor .register_filesystem (None )
140137
141- @mark .skipif (sys .version_info < (3 , 8 ), reason = "ArrowFSWrapper requires python 3.8 or higher" )
138+ @pytest . mark .skipif (sys .version_info < (3 , 8 ), reason = "ArrowFSWrapper requires python 3.8 or higher" )
142139 def test_arrow_fs_wrapper (self , tmp_path : Path , duckdb_cursor : DuckDBPyConnection ):
143- fs = importorskip ("pyarrow.fs" )
140+ fs = pytest . importorskip ("pyarrow.fs" )
144141 from fsspec .implementations .arrow import ArrowFSWrapper
145142
146143 local = fs .LocalFileSystem ()
@@ -157,7 +154,7 @@ def test_arrow_fs_wrapper(self, tmp_path: Path, duckdb_cursor: DuckDBPyConnectio
157154
158155 assert duckdb_cursor .fetchall () == [(1 , 2 , 3 ), (4 , 5 , 6 )]
159156
160- def test_database_attach (self , tmp_path : Path , monkeypatch : MonkeyPatch ):
157+ def test_database_attach (self , tmp_path : Path , monkeypatch : pytest . MonkeyPatch ):
161158 db_path = tmp_path / "hello.db"
162159
163160 # setup a database to attach later
@@ -172,8 +169,8 @@ def test_database_attach(self, tmp_path: Path, monkeypatch: MonkeyPatch):
172169 assert db_path .exists ()
173170
174171 with duckdb .connect () as conn :
175- fs = filesystem ("file" , skip_instance_cache = True )
176- write_errors = intercept (monkeypatch , LocalFileOpener , "write" )
172+ fs = fsspec . filesystem ("file" , skip_instance_cache = True )
173+ write_errors = intercept (monkeypatch , fsspec . implementations . local . LocalFileOpener , "write" )
177174 conn .register_filesystem (fs )
178175 db_path_posix = str (PurePosixPath (tmp_path .as_posix ()) / "hello.db" )
179176 conn .execute (f"ATTACH 'file://{ db_path_posix } '" )
@@ -187,14 +184,14 @@ def test_database_attach(self, tmp_path: Path, monkeypatch: MonkeyPatch):
187184 # isn't happening
188185 assert not write_errors
189186
190- def test_copy_partition (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
187+ def test_copy_partition (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
191188 duckdb_cursor .register_filesystem (memory )
192189
193190 duckdb_cursor .execute ("copy (select 1 as a, 2 as b) to 'memory://root' (partition_by (a), HEADER 0)" )
194191
195192 assert memory .open ("/root/a=1/data_0.csv" ).read () == b"2\n "
196193
197- def test_copy_partition_with_columns_written (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
194+ def test_copy_partition_with_columns_written (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
198195 duckdb_cursor .register_filesystem (memory )
199196
200197 duckdb_cursor .execute (
@@ -203,7 +200,7 @@ def test_copy_partition_with_columns_written(self, duckdb_cursor: DuckDBPyConnec
203200
204201 assert memory .open ("/root/a=1/data_0.csv" ).read () == b"1\n "
205202
206- def test_read_hive_partition (self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem ):
203+ def test_read_hive_partition (self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem ):
207204 duckdb_cursor .register_filesystem (memory )
208205 duckdb_cursor .execute (
209206 "copy (select 2 as a, 3 as b, 4 as c) to 'memory://partition' (partition_by (a), HEADER 0)"
@@ -230,7 +227,7 @@ def test_read_hive_partition(self, duckdb_cursor: DuckDBPyConnection, memory: Ab
230227 assert duckdb_cursor .fetchall () == [(3 , 4 , "2" )]
231228
232229 def test_read_hive_partition_with_columns_written (
233- self , duckdb_cursor : DuckDBPyConnection , memory : AbstractFileSystem
230+ self , duckdb_cursor : DuckDBPyConnection , memory : fsspec . AbstractFileSystem
234231 ):
235232 duckdb_cursor .register_filesystem (memory )
236233 duckdb_cursor .execute (
@@ -258,9 +255,9 @@ def test_read_hive_partition_with_columns_written(
258255 assert duckdb_cursor .fetchall () == [(2 , "2" )]
259256
260257 def test_parallel_union_by_name (self , tmp_path ):
261- pa = importorskip ("pyarrow" )
262- pq = importorskip ("pyarrow.parquet" )
263- importorskip ("fsspec" )
258+ pa = pytest . importorskip ("pyarrow" )
259+ pq = pytest . importorskip ("pyarrow.parquet" )
260+ pytest . importorskip ("fsspec" )
264261
265262 table1 = pa .Table .from_pylist (
266263 [
@@ -279,7 +276,7 @@ def test_parallel_union_by_name(self, tmp_path):
279276 pq .write_table (table2 , table2_path )
280277
281278 c = duckdb .connect ()
282- c .register_filesystem (LocalFileSystem ())
279+ c .register_filesystem (fsspec . implementations . local . LocalFileSystem ())
283280
284281 q = f"SELECT * FROM read_parquet('file://{ tmp_path } /table*.parquet', union_by_name = TRUE) ORDER BY time DESC LIMIT 1" # noqa: E501
285282
0 commit comments