python-filewrap 0.2.5__tar.gz → 0.2.6.1__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.2.5
3
+ Version: 0.2.6.1
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
@@ -17,6 +17,7 @@ Classifier: Programming Language :: Python :: 3
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
19
  Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
20
21
  Classifier: Programming Language :: Python :: 3 :: Only
21
22
  Classifier: Topic :: Software Development
22
23
  Classifier: Topic :: Software Development :: Libraries
@@ -7,7 +7,7 @@
7
7
  # TODO: AsyncTextIOWrapper.readline 有大量的字符串拼接操作,效率极低,需用 str.joins 方法优化
8
8
 
9
9
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
10
- __version__ = (0, 2, 5)
10
+ __version__ = (0, 2, 6)
11
11
  __all__ = [
12
12
  "Buffer", "SupportsRead", "SupportsReadinto", "SupportsWrite", "SupportsSeek",
13
13
  "AsyncBufferedReader", "AsyncTextIOWrapper",
@@ -22,6 +22,7 @@ __all__ = [
22
22
  "copyfileobj", "copyfileobj_async",
23
23
  ]
24
24
 
25
+ from array import array
25
26
  from asyncio import to_thread, Lock as AsyncLock
26
27
  from collections.abc import Awaitable, AsyncIterable, AsyncIterator, Callable, Iterable, Iterator, Sized
27
28
  from functools import update_wrapper
@@ -69,6 +70,19 @@ class VirtualBufferedReader:
69
70
  CRE_NOT_UNIX_NEWLINES_sub = re_compile("\r\n|\r").sub
70
71
 
71
72
 
73
+ def buffer_length(b: Buffer, /) -> int:
74
+ if isinstance(b, Sized):
75
+ return len(b)
76
+ else:
77
+ return len(memoryview(b))
78
+
79
+
80
+ def ensure_bytes(b: Buffer, /) -> array | bytes | bytearray | memoryview:
81
+ if isinstance(b, (array, bytes, bytearray, memoryview)):
82
+ return b
83
+ return memoryview(b)
84
+
85
+
72
86
  @runtime_checkable
73
87
  class SupportsRead(Protocol[_T_co]):
74
88
  def read(self, /, __length: int = ...) -> _T_co: ...
@@ -92,9 +106,9 @@ class SupportsSeek(Protocol):
92
106
  # TODO: 一些特定编码的 bom 用字典写死,编码名可以规范化,用 codecs.lookup(encoding).name
93
107
  def get_bom(encoding: str) -> bytes:
94
108
  code = memoryview(bytes("a", encoding))
95
- if len(code) == 1:
109
+ if buffer_length(code) == 1:
96
110
  return b""
97
- for i in range(1, len(code)):
111
+ for i in range(1, buffer_length(code)):
98
112
  try:
99
113
  str(code[:i], encoding)
100
114
  return code[:i].tobytes()
@@ -227,13 +241,13 @@ class AsyncBufferedReader(BufferedReader):
227
241
  self._pos += buf_size
228
242
  buf_size += await self.readinto(buffer_view[buf_size:])
229
243
  return buffer_view[:buf_size].tobytes()
230
- BUFSIZE = len(buf_view)
244
+ BUFSIZE = buffer_length(buf_view)
231
245
  read = ensure_async(self.raw.read, threaded=True)
232
246
  buffer = bytearray(buf_view[buf_pos:buf_stop])
233
247
  try:
234
248
  while data := await read(BUFSIZE):
235
249
  buffer += data
236
- length = len(data)
250
+ length = buffer_length(data)
237
251
  self._pos += length
238
252
  if BUFSIZE == length:
239
253
  buf_view[:] = data
@@ -279,9 +293,9 @@ class AsyncBufferedReader(BufferedReader):
279
293
  raise
280
294
  prev_data = buf_view[buf_pos:buf_stop].tobytes()
281
295
  if data:
282
- BUFSIZE = len(buf_view)
283
- length = len(data)
284
- self._pos += len(prev_data) + length
296
+ BUFSIZE = buffer_length(buf_view)
297
+ length = buffer_length(data)
298
+ self._pos += buffer_length(prev_data) + length
285
299
  if BUFSIZE <= length:
286
300
  buf_view[:] = memoryview(data)[-BUFSIZE:]
287
301
  self._buf_pos = self._buf_stop = BUFSIZE
@@ -302,7 +316,7 @@ class AsyncBufferedReader(BufferedReader):
302
316
  async def readinto(self, buffer, /) -> int: # type: ignore
303
317
  if self.closed:
304
318
  raise ValueError("I/O operation on closed file.")
305
- size = len(buffer)
319
+ size = buffer_length(buffer)
306
320
  if size == 0:
307
321
  return 0
308
322
  buf_view = self._buf_view
@@ -320,14 +334,14 @@ class AsyncBufferedReader(BufferedReader):
320
334
  except AttributeError:
321
335
  read = ensure_async(self.raw.read, threaded=True)
322
336
  async def readinto(buffer, /) -> int:
323
- data = await read(len(buffer))
337
+ data = await read(buffer_length(buffer))
324
338
  if data:
325
- size = len(data)
339
+ size = buffer_length(data)
326
340
  buffer[:size] = data
327
341
  return size
328
342
  else:
329
343
  return 0
330
- BUFSIZE = len(buf_view)
344
+ BUFSIZE = buffer_length(buf_view)
331
345
  buffer_view = memoryview(buffer)
332
346
  buffer_view[:buf_size] = buf_view[buf_pos:buf_stop]
333
347
  buf_pos = self._buf_pos = buf_stop
@@ -350,7 +364,7 @@ class AsyncBufferedReader(BufferedReader):
350
364
  break
351
365
  if length < BUFSIZE:
352
366
  part1, part2 = buf_view[length:].tobytes(), buf_view[:length].tobytes()
353
- index = len(part1)
367
+ index = buffer_length(part1)
354
368
  buf_view[:index] = part1
355
369
  buf_view[index:] = part2
356
370
  running = False
@@ -374,7 +388,7 @@ class AsyncBufferedReader(BufferedReader):
374
388
  async def readinto1(self, buffer, /) -> int: # type: ignore
375
389
  if self.closed:
376
390
  raise ValueError("I/O operation on closed file.")
377
- size = len(buffer)
391
+ size = buffer_length(buffer)
378
392
  if size == 0:
379
393
  return 0
380
394
  buf_view = self._buf_view
@@ -392,14 +406,14 @@ class AsyncBufferedReader(BufferedReader):
392
406
  except AttributeError:
393
407
  read = ensure_async(self.raw.read, threaded=True)
394
408
  async def readinto(buffer, /) -> int:
395
- data = await read(len(buffer))
409
+ data = await read(buffer_length(buffer))
396
410
  if data:
397
- size = len(data)
411
+ size = buffer_length(data)
398
412
  buffer[:size] = data
399
413
  return size
400
414
  else:
401
415
  return 0
402
- BUFSIZE = len(buf_view)
416
+ BUFSIZE = buffer_length(buf_view)
403
417
  buffer_view = memoryview(buffer)
404
418
  buffer_view[:buf_size] = buf_view[buf_pos:buf_stop]
405
419
  buf_pos = self._buf_pos = buf_stop
@@ -412,7 +426,7 @@ class AsyncBufferedReader(BufferedReader):
412
426
  self.calibrate()
413
427
  raise
414
428
  if length:
415
- BUFSIZE = len(buf_view)
429
+ BUFSIZE = buffer_length(buf_view)
416
430
  buffer_pos += length
417
431
  self._pos += length
418
432
  if BUFSIZE <= buffer_pos:
@@ -486,10 +500,10 @@ class AsyncBufferedReader(BufferedReader):
486
500
  self.calibrate()
487
501
  raise
488
502
  buf_view = self._buf_view
489
- BUFSIZE = len(buf_view)
490
- length = len(data)
503
+ BUFSIZE = buffer_length(buf_view)
504
+ length = buffer_length(data)
491
505
  prev_data = buf_view[buf_pos:buf_stop].tobytes()
492
- self._pos += len(prev_data) + length
506
+ self._pos += buffer_length(prev_data) + length
493
507
  if BUFSIZE <= length:
494
508
  buf_view[:] = memoryview(data)[-BUFSIZE:]
495
509
  self._buf_pos = self._buf_stop = BUFSIZE
@@ -517,7 +531,7 @@ class AsyncBufferedReader(BufferedReader):
517
531
  else:
518
532
  while hint > 0 and (line := await readline()):
519
533
  append(line)
520
- hint -= len(line)
534
+ hint -= buffer_length(line)
521
535
  return lines
522
536
 
523
537
  async def seek(self, target: int, whence: int = 0, /) -> int: # type: ignore
@@ -632,7 +646,7 @@ class AsyncTextIOWrapper(TextIOWrapper):
632
646
  data = await read(size)
633
647
  if not isinstance(data, Sized):
634
648
  data = memoryview(data)
635
- if size < 0 or len(cast(Sized, data)) < size:
649
+ if size < 0 or buffer_length(data) < size:
636
650
  text = str(data, encoding, errors)
637
651
  if newline is None:
638
652
  text = CRE_NOT_UNIX_NEWLINES_sub("\n", text)
@@ -650,7 +664,7 @@ class AsyncTextIOWrapper(TextIOWrapper):
650
664
  if not isinstance(data, Sized):
651
665
  data = memoryview(data)
652
666
  cache = bytes(data)
653
- while size and len(cast(Sized, data)) == size:
667
+ while size and buffer_length(data) == size:
654
668
  while cache:
655
669
  try:
656
670
  size -= process_part(cache)
@@ -660,11 +674,11 @@ class AsyncTextIOWrapper(TextIOWrapper):
660
674
  if start:
661
675
  size -= process_part(cache[:start])
662
676
  if e.reason == "truncated data":
663
- if stop == len(cache):
677
+ if stop == buffer_length(cache):
664
678
  cache = cache[start:]
665
679
  break
666
680
  else:
667
- while stop < len(cache):
681
+ while stop < buffer_length(cache):
668
682
  stop += 1
669
683
  try:
670
684
  size -= process_part(cache[start:stop])
@@ -675,13 +689,13 @@ class AsyncTextIOWrapper(TextIOWrapper):
675
689
  e = exc
676
690
  if e.reason != "truncated data":
677
691
  break
678
- if stop == len(cache):
692
+ if stop == buffer_length(cache):
679
693
  cache = cache[start:]
680
694
  break_this_loop = True
681
695
  break
682
696
  if break_this_loop:
683
697
  break
684
- elif e.reason == "unexpected end of data" and stop == len(cache):
698
+ elif e.reason == "unexpected end of data" and stop == buffer_length(cache):
685
699
  cache = cache[start:]
686
700
  break
687
701
  if errors == "strict":
@@ -721,7 +735,7 @@ class AsyncTextIOWrapper(TextIOWrapper):
721
735
  if bom := self._bom:
722
736
  crb = crb.removeprefix(bom)
723
737
  lfb = lfb.removeprefix(bom)
724
- lfb_len = len(lfb)
738
+ lfb_len = buffer_length(lfb)
725
739
  buf = bytearray()
726
740
  text = ""
727
741
  reach_end = False
@@ -743,7 +757,7 @@ class AsyncTextIOWrapper(TextIOWrapper):
743
757
  buf += lfb
744
758
  elif peek_maybe_lfb:
745
759
  # TODO: 这是一个提前量,未必需要立即往回 seek,因为转换为 str 后可能尾部不是 \r(因为可以和前面的符号结合),所以这个可能可以被复用,如果需要优化,可以在程序结束时的 finally 部分最终执行 seek(可能最终字符被消耗所以不需要 seek)
746
- o = len(cast(Sized, peek_maybe_lfb))
760
+ o = buffer_length(peek_maybe_lfb)
747
761
  await seek(-o, 1)
748
762
  if o < lfb_len:
749
763
  reach_end = True
@@ -752,23 +766,23 @@ class AsyncTextIOWrapper(TextIOWrapper):
752
766
  reach_end = True
753
767
  else:
754
768
  while True:
755
- buf_stop = len(buf)
769
+ buf_stop = buffer_length(buf)
756
770
  peek_b = peek()
757
771
  if peek_b:
758
772
  buf += peek_b
759
773
  if newline:
760
774
  if (idx := buf.find(sepb)) > -1:
761
- idx += len(sepb)
775
+ idx += buffer_length(sepb)
762
776
  await read(idx - buf_stop)
763
777
  del buf[idx:]
764
778
  break
765
779
  elif (idx := buf.find(lfb)) > -1:
766
- idx += len(lfb)
780
+ idx += buffer_length(lfb)
767
781
  await read(idx - buf_stop)
768
782
  del buf[idx:]
769
783
  break
770
784
  elif (idx := buf.find(crb)) > -1:
771
- idx += len(crb)
785
+ idx += buffer_length(crb)
772
786
  await read(idx - buf_stop)
773
787
  if buf.startswith(lfb, idx):
774
788
  await read(lfb_len)
@@ -777,7 +791,7 @@ class AsyncTextIOWrapper(TextIOWrapper):
777
791
  del buf[idx:]
778
792
  break
779
793
  if peek_b:
780
- await read(len(peek_b))
794
+ await read(buffer_length(peek_b))
781
795
  c = await read(1)
782
796
  if not c:
783
797
  reach_end = True
@@ -792,11 +806,11 @@ class AsyncTextIOWrapper(TextIOWrapper):
792
806
  if start:
793
807
  text += str(buf[:start], encoding)
794
808
  if e.reason == "truncated data":
795
- if stop == len(buf):
809
+ if stop == buffer_length(buf):
796
810
  buf = buf[start:]
797
811
  break
798
812
  else:
799
- while stop < len(buf):
813
+ while stop < buffer_length(buf):
800
814
  stop += 1
801
815
  try:
802
816
  text += str(buf[start:stop], encoding)
@@ -807,13 +821,13 @@ class AsyncTextIOWrapper(TextIOWrapper):
807
821
  e = exc
808
822
  if e.reason != "truncated data":
809
823
  break
810
- if stop == len(buf):
824
+ if stop == buffer_length(buf):
811
825
  buf = buf[start:]
812
826
  break_this_loop = True
813
827
  break
814
828
  if break_this_loop:
815
829
  break
816
- if e.reason == "unexpected end of data" and stop == len(buf):
830
+ if e.reason == "unexpected end of data" and stop == buffer_length(buf):
817
831
  buf = buf[start:]
818
832
  break
819
833
  if errors == "strict":
@@ -854,7 +868,7 @@ class AsyncTextIOWrapper(TextIOWrapper):
854
868
  if peek_maybe_lfb == lfb:
855
869
  buf += lfb
856
870
  elif peek_maybe_lfb:
857
- o = len(cast(Sized, peek_maybe_lfb))
871
+ o = buffer_length(peek_maybe_lfb)
858
872
  await seek(-o, 1)
859
873
  if o < lfb_len:
860
874
  reach_end = True
@@ -863,15 +877,15 @@ class AsyncTextIOWrapper(TextIOWrapper):
863
877
  reach_end = True
864
878
  else:
865
879
  while rem:
866
- buf_stop = len(buf)
880
+ buf_stop = buffer_length(buf)
867
881
  peek_b = peek()
868
882
  if peek_b:
869
- if len(peek_b) >= rem:
883
+ if buffer_length(peek_b) >= rem:
870
884
  buf += peek_b[:rem]
871
885
  rem = 0
872
886
  else:
873
887
  buf += peek_b
874
- rem -= len(peek_b)
888
+ rem -= buffer_length(peek_b)
875
889
  if newline:
876
890
  if (idx := buf.find(sepb)) > -1:
877
891
  idx += 1
@@ -907,7 +921,7 @@ class AsyncTextIOWrapper(TextIOWrapper):
907
921
  start, stop = e.start, e.end
908
922
  if start:
909
923
  text += str(buf[:start], encoding)
910
- if e.reason in ("unexpected end of data", "truncated data") and stop == len(buf):
924
+ if e.reason in ("unexpected end of data", "truncated data") and stop == buffer_length(buf):
911
925
  buf = buf[start:]
912
926
  break
913
927
  if errors == "strict":
@@ -1028,7 +1042,7 @@ def bio_chunk_iter(
1028
1042
  length = readinto(buf)
1029
1043
  if callback:
1030
1044
  callback(length)
1031
- if length < len(buf):
1045
+ if length < buffer_length(buf):
1032
1046
  del buf[length:]
1033
1047
  yield buf
1034
1048
  break
@@ -1048,7 +1062,7 @@ def bio_chunk_iter(
1048
1062
  while size:
1049
1063
  readsize = min(chunksize, size)
1050
1064
  chunk = read(readsize)
1051
- length = len(chunk)
1065
+ length = buffer_length(chunk)
1052
1066
  if callback:
1053
1067
  callback(length)
1054
1068
  yield chunk
@@ -1058,12 +1072,12 @@ def bio_chunk_iter(
1058
1072
  elif size < 0:
1059
1073
  while (chunk := read(chunksize)):
1060
1074
  if callback:
1061
- callback(len(chunk))
1075
+ callback(buffer_length(chunk))
1062
1076
  yield chunk
1063
1077
 
1064
1078
 
1065
1079
  async def bio_chunk_async_iter(
1066
- bio: SupportsRead[Buffer] | SupportsReadinto | Callable[[int], Buffer | Awaitable[Buffer]],
1080
+ bio: SupportsRead[Buffer] | SupportsRead[Awaitable[Buffer]] | SupportsReadinto | Callable[[int], Buffer | Awaitable[Buffer]],
1067
1081
  /,
1068
1082
  size: int = -1,
1069
1083
  chunksize: int = COPY_BUFSIZE,
@@ -1096,7 +1110,7 @@ async def bio_chunk_async_iter(
1096
1110
  length = await readinto(buf)
1097
1111
  if callback:
1098
1112
  await callback(length)
1099
- if length < len(buf):
1113
+ if length < buffer_length(buf):
1100
1114
  del buf[length:]
1101
1115
  yield buf
1102
1116
  break
@@ -1116,7 +1130,7 @@ async def bio_chunk_async_iter(
1116
1130
  while size:
1117
1131
  readsize = min(chunksize, size)
1118
1132
  chunk = await read(readsize)
1119
- length = len(chunk)
1133
+ length = buffer_length(chunk)
1120
1134
  if callback:
1121
1135
  await callback(length)
1122
1136
  yield chunk
@@ -1126,7 +1140,7 @@ async def bio_chunk_async_iter(
1126
1140
  elif size < 0:
1127
1141
  while (chunk := (await read(chunksize))):
1128
1142
  if callback:
1129
- await callback(len(chunk))
1143
+ await callback(buffer_length(chunk))
1130
1144
  yield chunk
1131
1145
 
1132
1146
 
@@ -1183,7 +1197,7 @@ def bio_skip_iter(
1183
1197
  if size > 0:
1184
1198
  while size:
1185
1199
  readsize = min(chunksize, size)
1186
- length = len(read(readsize))
1200
+ length = buffer_length(read(readsize))
1187
1201
  if callback:
1188
1202
  callback(length)
1189
1203
  yield length
@@ -1191,7 +1205,7 @@ def bio_skip_iter(
1191
1205
  break
1192
1206
  size -= readsize
1193
1207
  else:
1194
- while (length := len(read(chunksize))):
1208
+ while (length := buffer_length(read(chunksize))):
1195
1209
  if callback:
1196
1210
  callback(length)
1197
1211
  yield length
@@ -1202,7 +1216,7 @@ def bio_skip_iter(
1202
1216
 
1203
1217
 
1204
1218
  async def bio_skip_async_iter(
1205
- bio: SupportsRead[Buffer] | SupportsReadinto | Callable[[int], Buffer | Awaitable[Buffer]],
1219
+ bio: SupportsRead[Buffer] | SupportsRead[Awaitable[Buffer]] | SupportsReadinto | Callable[[int], Buffer | Awaitable[Buffer]],
1206
1220
  /,
1207
1221
  size: int = -1,
1208
1222
  chunksize: int = COPY_BUFSIZE,
@@ -1253,7 +1267,7 @@ async def bio_skip_async_iter(
1253
1267
  if size > 0:
1254
1268
  while size:
1255
1269
  readsize = min(chunksize, size)
1256
- length = len(await read(readsize))
1270
+ length = buffer_length(await read(readsize))
1257
1271
  if callback:
1258
1272
  await callback(length)
1259
1273
  yield length
@@ -1261,7 +1275,7 @@ async def bio_skip_async_iter(
1261
1275
  break
1262
1276
  size -= readsize
1263
1277
  else:
1264
- while (length := len(await read(chunksize))):
1278
+ while (length := buffer_length(await read(chunksize))):
1265
1279
  if callback:
1266
1280
  await callback(length)
1267
1281
  yield length
@@ -1284,7 +1298,7 @@ def bytes_iter(
1284
1298
  elif size == 0:
1285
1299
  return
1286
1300
  for b in it:
1287
- l = len(b)
1301
+ l = buffer_length(b)
1288
1302
  if l <= size:
1289
1303
  yield b
1290
1304
  if callback is not None:
@@ -1316,7 +1330,7 @@ async def bytes_async_iter(
1316
1330
  return
1317
1331
  callback = ensure_async(callback) if callable(callback) else None
1318
1332
  async for b in it:
1319
- l = len(b)
1333
+ l = buffer_length(b)
1320
1334
  if l <= size:
1321
1335
  yield b
1322
1336
  if callback is not None:
@@ -1345,7 +1359,7 @@ def bytes_iter_skip(
1345
1359
  callback = None
1346
1360
  m: memoryview
1347
1361
  for m in map(memoryview, it): # type: ignore
1348
- l = len(m)
1362
+ l = buffer_length(m)
1349
1363
  if callback:
1350
1364
  callback(min(l, size))
1351
1365
  if l == size:
@@ -1370,7 +1384,7 @@ async def bytes_async_iter_skip(
1370
1384
  callback = ensure_async(callback) if callable(callback) else None
1371
1385
  async for b in it:
1372
1386
  m = memoryview(b)
1373
- l = len(m)
1387
+ l = buffer_length(m)
1374
1388
  if callback:
1375
1389
  await callback(min(l, size))
1376
1390
  if l == size:
@@ -1419,23 +1433,23 @@ def bytes_iter_to_reader(
1419
1433
  while True:
1420
1434
  unconsumed += getnext()
1421
1435
  else:
1422
- while n > len(unconsumed):
1436
+ while n > buffer_length(unconsumed):
1423
1437
  unconsumed += getnext()
1424
1438
  b, unconsumed = unconsumed[:n], unconsumed[n:]
1425
- pos += len(b)
1439
+ pos += buffer_length(b)
1426
1440
  return b
1427
1441
  except StopIteration:
1428
1442
  at_end = True
1429
1443
  b = unconsumed[:]
1430
1444
  del unconsumed[:]
1431
- pos += len(b)
1445
+ pos += buffer_length(b)
1432
1446
  return b
1433
1447
  def readinto(buf, /) -> int:
1434
1448
  nonlocal pos, at_end, unconsumed
1435
- if at_end or not (bufsize := len(buf)):
1449
+ if at_end or not (bufsize := buffer_length(buf)):
1436
1450
  return 0
1437
1451
  with lock:
1438
- n = len(unconsumed)
1452
+ n = buffer_length(unconsumed)
1439
1453
  if bufsize <= n:
1440
1454
  buf[:], unconsumed = unconsumed[:bufsize], unconsumed[bufsize:]
1441
1455
  pos += bufsize
@@ -1444,10 +1458,10 @@ def bytes_iter_to_reader(
1444
1458
  del unconsumed[:]
1445
1459
  try:
1446
1460
  while True:
1447
- b = getnext()
1461
+ b = ensure_bytes(getnext())
1448
1462
  if not b:
1449
1463
  continue
1450
- m = n + len(b)
1464
+ m = n + buffer_length(b)
1451
1465
  if m >= bufsize:
1452
1466
  buf[n:] = b[:bufsize-n]
1453
1467
  unconsumed += b[bufsize-n:]
@@ -1455,7 +1469,7 @@ def bytes_iter_to_reader(
1455
1469
  return bufsize
1456
1470
  else:
1457
1471
  buf[n:m] = b
1458
- pos += len(b)
1472
+ pos += buffer_length(b)
1459
1473
  n = m
1460
1474
  except StopIteration:
1461
1475
  at_end = True
@@ -1475,12 +1489,12 @@ def bytes_iter_to_reader(
1475
1489
  b, unconsumed = unconsumed[:idx], unconsumed[idx:]
1476
1490
  pos += idx
1477
1491
  return b
1478
- if n > 0 and len(unconsumed) >= n:
1492
+ if n > 0 and buffer_length(unconsumed) >= n:
1479
1493
  b, unconsumed = unconsumed[:n], unconsumed[n:]
1480
1494
  pos += n
1481
1495
  return b
1482
1496
  try:
1483
- start = len(unconsumed)
1497
+ start = buffer_length(unconsumed)
1484
1498
  while True:
1485
1499
  r = getnext()
1486
1500
  if not r:
@@ -1492,7 +1506,7 @@ def bytes_iter_to_reader(
1492
1506
  b, unconsumed = unconsumed[:idx], unconsumed[idx:]
1493
1507
  pos += idx
1494
1508
  return b
1495
- start = len(unconsumed)
1509
+ start = buffer_length(unconsumed)
1496
1510
  if n > 0 and start >= n:
1497
1511
  b, unconsumed = unconsumed[:n], unconsumed[n:]
1498
1512
  pos += n
@@ -1502,7 +1516,7 @@ def bytes_iter_to_reader(
1502
1516
  if unconsumed:
1503
1517
  b = unconsumed[:]
1504
1518
  del unconsumed[:]
1505
- pos += len(b)
1519
+ pos += buffer_length(b)
1506
1520
  return b
1507
1521
  raise
1508
1522
  def readlines(hint: int = -1, /) -> list[bytearray]:
@@ -1516,7 +1530,7 @@ def bytes_iter_to_reader(
1516
1530
  else:
1517
1531
  while hint > 0 and (line := readline()):
1518
1532
  append(line)
1519
- hint -= len(line)
1533
+ hint -= buffer_length(line)
1520
1534
  return lines
1521
1535
  def __next__() -> bytearray:
1522
1536
  if at_end or not (b := readline()):
@@ -1546,7 +1560,7 @@ def bytes_iter_to_async_reader(
1546
1560
  it: Iterable[Buffer] | AsyncIterable[Buffer],
1547
1561
  /,
1548
1562
  threaded: bool = True,
1549
- ) -> SupportsRead[bytearray]:
1563
+ ) -> SupportsRead[Awaitable[bytearray]]:
1550
1564
  if isinstance(it, AsyncIterable):
1551
1565
  getnext = aiter(it).__anext__
1552
1566
  else:
@@ -1596,23 +1610,23 @@ def bytes_iter_to_async_reader(
1596
1610
  while True:
1597
1611
  unconsumed += await getnext()
1598
1612
  else:
1599
- while n > len(unconsumed):
1613
+ while n > buffer_length(unconsumed):
1600
1614
  unconsumed += await getnext()
1601
1615
  b, unconsumed = unconsumed[:n], unconsumed[n:]
1602
- pos += len(b)
1616
+ pos += buffer_length(b)
1603
1617
  return b
1604
1618
  except (StopIteration, StopAsyncIteration):
1605
1619
  at_end = True
1606
1620
  b = unconsumed[:]
1607
1621
  del unconsumed[:]
1608
- pos += len(b)
1622
+ pos += buffer_length(b)
1609
1623
  return b
1610
1624
  async def readinto(buf, /) -> int:
1611
1625
  nonlocal pos, at_end, unconsumed
1612
- if at_end or not (bufsize := len(buf)):
1626
+ if at_end or not (bufsize := buffer_length(buf)):
1613
1627
  return 0
1614
1628
  async with lock:
1615
- n = len(unconsumed)
1629
+ n = buffer_length(unconsumed)
1616
1630
  if bufsize <= n:
1617
1631
  buf[:], unconsumed = unconsumed[:bufsize], unconsumed[bufsize:]
1618
1632
  pos += bufsize
@@ -1621,10 +1635,10 @@ def bytes_iter_to_async_reader(
1621
1635
  del unconsumed[:]
1622
1636
  try:
1623
1637
  while True:
1624
- b = await getnext()
1638
+ b = ensure_bytes(await getnext())
1625
1639
  if not b:
1626
1640
  continue
1627
- m = n + len(b)
1641
+ m = n + buffer_length(b)
1628
1642
  if m >= bufsize:
1629
1643
  buf[n:] = b[:bufsize-n]
1630
1644
  unconsumed += b[bufsize-n:]
@@ -1632,7 +1646,7 @@ def bytes_iter_to_async_reader(
1632
1646
  return bufsize
1633
1647
  else:
1634
1648
  buf[n:m] = b
1635
- pos += len(b)
1649
+ pos += buffer_length(b)
1636
1650
  n = m
1637
1651
  except (StopIteration, StopAsyncIteration):
1638
1652
  at_end = True
@@ -1652,12 +1666,12 @@ def bytes_iter_to_async_reader(
1652
1666
  b, unconsumed = unconsumed[:idx], unconsumed[idx:]
1653
1667
  pos += idx
1654
1668
  return b
1655
- if n > 0 and len(unconsumed) >= n:
1669
+ if n > 0 and buffer_length(unconsumed) >= n:
1656
1670
  b, unconsumed = unconsumed[:n], unconsumed[n:]
1657
1671
  pos += n
1658
1672
  return b
1659
1673
  try:
1660
- start = len(unconsumed)
1674
+ start = buffer_length(unconsumed)
1661
1675
  while True:
1662
1676
  r = await getnext()
1663
1677
  if not r:
@@ -1669,7 +1683,7 @@ def bytes_iter_to_async_reader(
1669
1683
  b, unconsumed = unconsumed[:idx], unconsumed[idx:]
1670
1684
  pos += idx
1671
1685
  return b
1672
- start = len(unconsumed)
1686
+ start = buffer_length(unconsumed)
1673
1687
  if n > 0 and start >= n:
1674
1688
  b, unconsumed = unconsumed[:n], unconsumed[n:]
1675
1689
  pos += n
@@ -1679,7 +1693,7 @@ def bytes_iter_to_async_reader(
1679
1693
  if unconsumed:
1680
1694
  b = unconsumed[:]
1681
1695
  del unconsumed[:]
1682
- pos += len(b)
1696
+ pos += buffer_length(b)
1683
1697
  return b
1684
1698
  raise
1685
1699
  async def readlines(hint: int = -1, /) -> list[bytearray]:
@@ -1696,7 +1710,7 @@ def bytes_iter_to_async_reader(
1696
1710
  else:
1697
1711
  while hint > 0 and (line := await readline()):
1698
1712
  append(line)
1699
- hint -= len(line)
1713
+ hint -= buffer_length(line)
1700
1714
  return lines
1701
1715
  async def __anext__() -> bytearray:
1702
1716
  if at_end or not (b := await readline()):
@@ -1729,7 +1743,7 @@ def bytes_to_chunk_iter(
1729
1743
  chunksize: int = COPY_BUFSIZE,
1730
1744
  ) -> Iterator[memoryview]:
1731
1745
  m = memoryview(b)
1732
- for i in range(0, len(m), chunksize):
1746
+ for i in range(0, buffer_length(m), chunksize):
1733
1747
  yield m[i:i+chunksize]
1734
1748
 
1735
1749
 
@@ -1739,7 +1753,7 @@ async def bytes_to_chunk_async_iter(
1739
1753
  chunksize: int = COPY_BUFSIZE,
1740
1754
  ) -> AsyncIterator[memoryview]:
1741
1755
  m = memoryview(b)
1742
- for i in range(0, len(m), chunksize):
1756
+ for i in range(0, buffer_length(m), chunksize):
1743
1757
  yield m[i:i+chunksize]
1744
1758
 
1745
1759
 
@@ -1751,7 +1765,7 @@ def bytes_ensure_part_iter(
1751
1765
  n = partsize
1752
1766
  for b in it:
1753
1767
  m = memoryview(b)
1754
- l = len(m)
1768
+ l = buffer_length(m)
1755
1769
  if l <= n:
1756
1770
  yield b
1757
1771
  if l == n:
@@ -1761,12 +1775,12 @@ def bytes_ensure_part_iter(
1761
1775
  else:
1762
1776
  yield m[:n]
1763
1777
  m = m[n:]
1764
- while len(m) >= partsize:
1778
+ while buffer_length(m) >= partsize:
1765
1779
  yield m[:partsize]
1766
1780
  m = m[partsize:]
1767
1781
  if m:
1768
1782
  yield m
1769
- n = partsize - len(m)
1783
+ n = partsize - buffer_length(m)
1770
1784
  else:
1771
1785
  n = partsize
1772
1786
 
@@ -1779,7 +1793,7 @@ async def bytes_ensure_part_async_iter(
1779
1793
  n = partsize
1780
1794
  async for b in ensure_aiter(it):
1781
1795
  m = memoryview(b)
1782
- l = len(m)
1796
+ l = buffer_length(m)
1783
1797
  if l <= n:
1784
1798
  yield b
1785
1799
  if l == n:
@@ -1789,12 +1803,12 @@ async def bytes_ensure_part_async_iter(
1789
1803
  else:
1790
1804
  yield m[:n]
1791
1805
  m = m[n:]
1792
- while len(m) >= partsize:
1806
+ while buffer_length(m) >= partsize:
1793
1807
  yield m[:partsize]
1794
1808
  m = m[partsize:]
1795
1809
  if m:
1796
1810
  yield m
1797
- n = partsize - len(m)
1811
+ n = partsize - buffer_length(m)
1798
1812
  else:
1799
1813
  n = partsize
1800
1814
 
@@ -1823,7 +1837,7 @@ def progress_bytes_iter(
1823
1837
  if callable(update_progress):
1824
1838
  for chunk in it:
1825
1839
  yield chunk
1826
- update_progress(len(chunk))
1840
+ update_progress(buffer_length(chunk))
1827
1841
  else:
1828
1842
  for chunk in it:
1829
1843
  yield chunk
@@ -1842,7 +1856,7 @@ async def progress_bytes_async_iter(
1842
1856
  update_progress: None | Callable = None
1843
1857
  close_progress: None | Callable = None
1844
1858
  if callable(it):
1845
- async def wrapiter(it) -> Buffer:
1859
+ async def wrapiter(it) -> AsyncIterator[Buffer]:
1846
1860
  while True:
1847
1861
  chunk = it()
1848
1862
  if isawaitable(chunk):
@@ -1870,7 +1884,7 @@ async def progress_bytes_async_iter(
1870
1884
  update_progress = ensure_async(update_progress)
1871
1885
  async for chunk in it:
1872
1886
  yield chunk
1873
- await update_progress(len(chunk))
1887
+ await update_progress(buffer_length(chunk))
1874
1888
  else:
1875
1889
  async for chunk in it:
1876
1890
  yield chunk
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-filewrap"
3
- version = "0.2.5"
3
+ version = "0.2.6.1"
4
4
  description = "Python file wrappers."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"