Skip to content

Commit 2b072a6

Browse files
committed
review comments
1 parent e729623 commit 2b072a6

2 files changed

Lines changed: 42 additions & 40 deletions

File tree

fsspec/prefetcher.py

Lines changed: 5 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,13 @@
11
import asyncio
2-
import ctypes
32
import logging
43
import weakref
54
from collections import deque
65

76
from . import asyn as fsspec_asyn
7+
from .utils import HAS_CPYTHON_API, _fast_slice
88

99
logger = logging.getLogger(__name__)
1010

11-
try:
12-
PyBytes_FromStringAndSize = ctypes.pythonapi.PyBytes_FromStringAndSize
13-
PyBytes_FromStringAndSize.argtypes = (ctypes.c_void_p, ctypes.c_ssize_t)
14-
PyBytes_FromStringAndSize.restype = ctypes.py_object
15-
16-
PyBytes_AsString = ctypes.pythonapi.PyBytes_AsString
17-
PyBytes_AsString.argtypes = (ctypes.py_object,)
18-
PyBytes_AsString.restype = ctypes.c_void_p
19-
HAS_CPYTHON_API = True
20-
except Exception:
21-
PyBytes_FromStringAndSize = None
22-
PyBytes_AsString = None
23-
HAS_CPYTHON_API = False
24-
25-
26-
# Please refer to following discussion to understand why this is required at this point
27-
# Discussion = https://github.com/fsspec/gcsfs/pull/795#discussion_r3032749881
28-
def _fast_slice(src_bytes, offset, read_size):
29-
if read_size == 0:
30-
return b""
31-
if offset < 0 or offset + read_size > len(src_bytes):
32-
raise ValueError("Slice indices out of bounds")
33-
34-
if HAS_CPYTHON_API:
35-
dest_bytes = PyBytes_FromStringAndSize(None, read_size)
36-
src_ptr = PyBytes_AsString(src_bytes)
37-
dest_ptr = PyBytes_AsString(dest_bytes)
38-
# Releases the GIL
39-
ctypes.memmove(dest_ptr, src_ptr + offset, read_size)
40-
return dest_bytes
41-
else:
42-
# Standard fallback for PyPy/non-CPython
43-
return src_bytes[offset : offset + read_size]
44-
4511

4612
class RunningAverageTracker:
4713
"""Tracks a running average of values over a sliding window.
@@ -237,7 +203,7 @@ async def stop(self):
237203
self._producer_task.cancel()
238204
tasks_to_wait.append(self._producer_task)
239205

240-
tasks_to_wait.extend(task for task in self._active_tasks if not task.done())
206+
tasks_to_wait.extend(task for task in list(self._active_tasks) if not task.done())
241207

242208
# We do not cancel the network task, instead we wait on them.
243209
# This is intentionally done to avoid MRD stream disruption.
@@ -300,8 +266,7 @@ async def _loop(self):
300266
logger.debug("PrefetchProducer loop was cancelled.")
301267
except Exception as e:
302268
logger.exception(
303-
"PrefetchProducer loop encountered an unexpected error: %s",
304-
e,
269+
"PrefetchProducer loop encountered an unexpected error."
305270
)
306271
self.is_stopped = True
307272
self.orchestrator.set_error(e)
@@ -557,7 +522,7 @@ async def _advance(self, size: int, save_data: bool) -> list[bytes]:
557522
except asyncio.CancelledError:
558523
raise
559524
except Exception as e:
560-
logger.exception("Consumer caught an error: %s", e)
525+
logger.exception("Consumer caught an error.")
561526
self.orchestrator.set_error(e)
562527
raise e
563528

@@ -817,7 +782,7 @@ async def _async_fetch(self, start, end):
817782
self._error = e
818783
raise
819784
except Exception as e:
820-
logger.exception("Exception raised during asynchronous fetch: %s", e)
785+
logger.exception("Exception raised during asynchronous fetch.")
821786
self._error = e
822787
if self.producer and not self.producer.is_stopped:
823788
await self.producer.stop()

fsspec/utils.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import contextlib
4+
import ctypes
45
import logging
56
import math
67
import os
@@ -755,3 +756,39 @@ def glob_translate(pat):
755756
results.append(any_sep)
756757
res = "".join(results)
757758
return rf"(?s:{res})\Z"
759+
760+
761+
try:
762+
PyBytes_FromStringAndSize = ctypes.pythonapi.PyBytes_FromStringAndSize
763+
PyBytes_FromStringAndSize.argtypes = (ctypes.c_void_p, ctypes.c_ssize_t)
764+
PyBytes_FromStringAndSize.restype = ctypes.py_object
765+
766+
PyBytes_AsString = ctypes.pythonapi.PyBytes_AsString
767+
PyBytes_AsString.argtypes = (ctypes.py_object,)
768+
PyBytes_AsString.restype = ctypes.c_void_p
769+
HAS_CPYTHON_API = True
770+
except Exception:
771+
PyBytes_FromStringAndSize = None
772+
PyBytes_AsString = None
773+
HAS_CPYTHON_API = False
774+
775+
776+
# Please refer to following discussion to understand why this is required at this point
777+
# Discussion = https://github.com/fsspec/gcsfs/pull/795#discussion_r3032749881
778+
def _fast_slice(src_bytes: bytes, offset: int, read_size: int) -> bytes:
779+
if read_size == 0:
780+
return b""
781+
if offset < 0 or offset + read_size > len(src_bytes):
782+
raise ValueError("Slice indices out of bounds")
783+
784+
if HAS_CPYTHON_API:
785+
dest_bytes = PyBytes_FromStringAndSize(None, read_size)
786+
src_ptr = PyBytes_AsString(src_bytes)
787+
dest_ptr = PyBytes_AsString(dest_bytes)
788+
# Releases the GIL
789+
ctypes.memmove(dest_ptr, src_ptr + offset, read_size)
790+
return dest_bytes
791+
else:
792+
# Standard fallback for PyPy/non-CPython
793+
return src_bytes[offset : offset + read_size]
794+

0 commit comments

Comments
 (0)