python-filewrap 0.0.7.1__tar.gz → 0.0.8__tar.gz

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,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-filewrap
3
- Version: 0.0.7.1
3
+ Version: 0.0.8
4
4
  Summary: Python file wrappers.
5
5
  Home-page: https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-filewrap
6
6
  License: MIT
@@ -2,9 +2,9 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 0, 7)
5
+ __version__ = (0, 0, 8)
6
6
  __all__ = [
7
- "SupportsRead", "SupportsWrite",
7
+ "SupportsRead", "SupportsWrite", "SupportsSeek",
8
8
  "bio_chunk_iter", "bio_chunk_async_iter",
9
9
  "bio_skip_iter", "bio_skip_async_iter",
10
10
  "bytes_iter_skip", "bytes_async_iter_skip",
@@ -14,11 +14,10 @@ __all__ = [
14
14
  ]
15
15
 
16
16
  from asyncio import to_thread, Lock as AsyncLock
17
- from collections.abc import Awaitable, AsyncIterable, Iterable
17
+ from collections.abc import Awaitable, AsyncIterable, AsyncIterator, Callable, Iterable, Iterator
18
18
  from functools import update_wrapper
19
19
  from inspect import isawaitable, iscoroutinefunction
20
20
  from itertools import chain
21
- from collections.abc import AsyncIterator, Callable, Iterator
22
21
  from shutil import COPY_BUFSIZE # type: ignore
23
22
  from threading import Lock
24
23
  from typing import runtime_checkable, Any, Protocol, TypeVar
@@ -37,12 +36,17 @@ _T_contra = TypeVar("_T_contra", contravariant=True)
37
36
 
38
37
  @runtime_checkable
39
38
  class SupportsRead(Protocol[_T_co]):
40
- def read(self, __length: int = ...) -> _T_co: ...
39
+ def read(self, /, __length: int = ...) -> _T_co: ...
41
40
 
42
41
 
43
42
  @runtime_checkable
44
43
  class SupportsWrite(Protocol[_T_contra]):
45
- def write(self, __s: _T_contra) -> object: ...
44
+ def write(self, /, __s: _T_contra) -> object: ...
45
+
46
+
47
+ @runtime_checkable
48
+ class SupportsSeek(Protocol):
49
+ def seek(self, /, __offset: int, __whence: int = 0) -> int: ...
46
50
 
47
51
 
48
52
  def bio_chunk_iter(
@@ -50,30 +54,60 @@ def bio_chunk_iter(
50
54
  /,
51
55
  size: int = -1,
52
56
  chunksize: int = COPY_BUFSIZE,
57
+ can_buffer: bool = False,
53
58
  callback: None | Callable[[int], Any] = None,
54
59
  ) -> Iterator[Buffer]:
60
+ use_readinto = False
55
61
  if callable(bio):
56
62
  read = bio
63
+ elif can_buffer and hasattr(bio, "readinto"):
64
+ readinto = bio.readinto
65
+ use_readinto = True
57
66
  else:
58
67
  read = bio.read
59
68
  if not callable(callback):
60
69
  callback = None
61
- if size > 0:
62
- while size:
63
- readsize = min(chunksize, size)
64
- chunk = read(readsize)
65
- length = len(chunk)
66
- if callback:
67
- callback(length)
68
- yield chunk
69
- if length < readsize:
70
- break
71
- size -= readsize
72
- elif size < 0:
73
- while (chunk := read(chunksize)):
74
- if callback:
75
- callback(len(chunk))
76
- yield chunk
70
+ if use_readinto:
71
+ buf = bytearray(chunksize)
72
+ if size > 0:
73
+ while size:
74
+ if size < chunksize:
75
+ del buf[size:]
76
+ length = readinto(buf)
77
+ if callback:
78
+ callback(length)
79
+ if length < len(buf):
80
+ del buf[length:]
81
+ yield buf
82
+ break
83
+ yield buf
84
+ size -= length
85
+ else:
86
+ while (length := readinto(buf)):
87
+ if callback:
88
+ callback(length)
89
+ if length < chunksize:
90
+ del buf[length:]
91
+ yield buf
92
+ break
93
+ yield buf
94
+ else:
95
+ if size > 0:
96
+ while size:
97
+ readsize = min(chunksize, size)
98
+ chunk = read(readsize)
99
+ length = len(chunk)
100
+ if callback:
101
+ callback(length)
102
+ yield chunk
103
+ if length < readsize:
104
+ break
105
+ size -= length
106
+ elif size < 0:
107
+ while (chunk := read(chunksize)):
108
+ if callback:
109
+ callback(len(chunk))
110
+ yield chunk
77
111
 
78
112
 
79
113
  async def bio_chunk_async_iter(
@@ -81,29 +115,59 @@ async def bio_chunk_async_iter(
81
115
  /,
82
116
  size: int = -1,
83
117
  chunksize: int = COPY_BUFSIZE,
118
+ can_buffer: bool = False,
84
119
  callback: None | Callable[[int], Any] = None,
85
120
  ) -> AsyncIterator[Buffer]:
121
+ use_readinto = False
86
122
  if callable(bio):
87
123
  read = ensure_async(bio)
124
+ elif can_buffer and hasattr(bio, "readinto"):
125
+ readinto = ensure_async(bio.readinto)
126
+ use_readinto = True
88
127
  else:
89
128
  read = ensure_async(bio.read)
90
129
  callback = ensure_async(callback) if callable(callback) else None
91
- if size > 0:
92
- while size:
93
- readsize = min(chunksize, size)
94
- chunk = await read(readsize)
95
- length = len(chunk)
96
- if callback:
97
- await callback(length)
98
- yield chunk
99
- if length < readsize:
100
- break
101
- size -= readsize
102
- elif size < 0:
103
- while (chunk := (await read(chunksize))):
104
- if callback:
105
- await callback(len(chunk))
106
- yield chunk
130
+ if use_readinto:
131
+ buf = bytearray(chunksize)
132
+ if size > 0:
133
+ while size:
134
+ if size < chunksize:
135
+ del buf[size:]
136
+ length = await readinto(buf)
137
+ if callback:
138
+ await callback(length)
139
+ if length < len(buf):
140
+ del buf[length:]
141
+ yield buf
142
+ break
143
+ yield buf
144
+ size -= length
145
+ else:
146
+ while (length := (await readinto(buf))):
147
+ if callback:
148
+ await callback(length)
149
+ if length < chunksize:
150
+ del buf[length:]
151
+ yield buf
152
+ break
153
+ yield buf
154
+ else:
155
+ if size > 0:
156
+ while size:
157
+ readsize = min(chunksize, size)
158
+ chunk = await read(readsize)
159
+ length = len(chunk)
160
+ if callback:
161
+ await callback(length)
162
+ yield chunk
163
+ if length < readsize:
164
+ break
165
+ size -= readsize
166
+ elif size < 0:
167
+ while (chunk := (await read(chunksize))):
168
+ if callback:
169
+ await callback(len(chunk))
170
+ yield chunk
107
171
 
108
172
 
109
173
  def bio_skip_iter(
@@ -187,6 +251,7 @@ async def bio_skip_async_iter(
187
251
  if size == 0:
188
252
  return
189
253
  callback = ensure_async(callback) if callable(callback) else None
254
+ length: int
190
255
  try:
191
256
  seek = ensure_async(getattr(bio, "seek"))
192
257
  curpos = await seek(0, 1)
@@ -271,7 +336,7 @@ def bytes_iter_skip(
271
336
 
272
337
 
273
338
  async def bytes_async_iter_skip(
274
- it: Iterable[Buffer] | AsyncIterator[Buffer],
339
+ it: Iterable[Buffer] | AsyncIterable[Buffer],
275
340
  /,
276
341
  size: int = -1,
277
342
  callback: None | Callable[[int], Any] = None,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-filewrap"
3
- version = "0.0.7.1"
3
+ version = "0.0.8"
4
4
  description = "Python file wrappers."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"