python-filewrap 0.2.3.1__tar.gz → 0.2.5__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.
- {python_filewrap-0.2.3.1 → python_filewrap-0.2.5}/PKG-INFO +2 -2
- {python_filewrap-0.2.3.1 → python_filewrap-0.2.5}/filewrap/__init__.py +30 -16
- {python_filewrap-0.2.3.1 → python_filewrap-0.2.5}/pyproject.toml +2 -2
- {python_filewrap-0.2.3.1 → python_filewrap-0.2.5}/LICENSE +0 -0
- {python_filewrap-0.2.3.1 → python_filewrap-0.2.5}/filewrap/py.typed +0 -0
- {python_filewrap-0.2.3.1 → python_filewrap-0.2.5}/readme.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-filewrap
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.5
|
|
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
|
|
@@ -22,7 +22,7 @@ Classifier: Topic :: Software Development
|
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries
|
|
23
23
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
24
|
Requires-Dist: python-asynctools (>=0.0.5)
|
|
25
|
-
Requires-Dist: python-property (>=0.0.
|
|
25
|
+
Requires-Dist: python-property (>=0.0.3)
|
|
26
26
|
Project-URL: Repository, https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-filewrap
|
|
27
27
|
Description-Content-Type: text/markdown
|
|
28
28
|
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env python3
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
|
+
# TODO: 实现一种 memoryview,可以作为环形缓冲区使用
|
|
4
5
|
# TODO: 使用 codecs.iterdecode 来避免解码过程中的一些重复操作
|
|
5
6
|
# TODO: AsyncTextIOWrapper 的 read 和 readline 算法效率不高,因为会反复创建二进制对象,如果可以复用一段或者几段(内存块组)内存,则可以大大增加效率,还可以引入环形缓冲区(使用长度限定的 bytearray,之后所有操作在 memoryview 上进行,根据当前的可用区块开返回 memoryview),以减少内存分配的开销
|
|
6
7
|
# TODO: AsyncTextIOWrapper.readline 有大量的字符串拼接操作,效率极低,需用 str.joins 方法优化
|
|
7
8
|
|
|
8
9
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
9
|
-
__version__ = (0, 2,
|
|
10
|
+
__version__ = (0, 2, 5)
|
|
10
11
|
__all__ = [
|
|
11
12
|
"Buffer", "SupportsRead", "SupportsReadinto", "SupportsWrite", "SupportsSeek",
|
|
12
13
|
"AsyncBufferedReader", "AsyncTextIOWrapper",
|
|
@@ -22,7 +23,7 @@ __all__ = [
|
|
|
22
23
|
]
|
|
23
24
|
|
|
24
25
|
from asyncio import to_thread, Lock as AsyncLock
|
|
25
|
-
from collections.abc import Awaitable, AsyncIterable, AsyncIterator, Callable, Iterable, Iterator
|
|
26
|
+
from collections.abc import Awaitable, AsyncIterable, AsyncIterator, Callable, Iterable, Iterator, Sized
|
|
26
27
|
from functools import update_wrapper
|
|
27
28
|
from io import BufferedIOBase, BufferedReader, BytesIO, RawIOBase, TextIOWrapper
|
|
28
29
|
from inspect import isawaitable, iscoroutinefunction, isasyncgen, isgenerator
|
|
@@ -51,7 +52,7 @@ except ImportError:
|
|
|
51
52
|
Buffer.register(array)
|
|
52
53
|
|
|
53
54
|
from asynctools import async_chain, ensure_async, ensure_aiter, run_async
|
|
54
|
-
from property import
|
|
55
|
+
from property import funcproperty
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
Args = ParamSpec("Args")
|
|
@@ -629,7 +630,9 @@ class AsyncTextIOWrapper(TextIOWrapper):
|
|
|
629
630
|
data = await read(-1)
|
|
630
631
|
else:
|
|
631
632
|
data = await read(size)
|
|
632
|
-
if
|
|
633
|
+
if not isinstance(data, Sized):
|
|
634
|
+
data = memoryview(data)
|
|
635
|
+
if size < 0 or len(cast(Sized, data)) < size:
|
|
633
636
|
text = str(data, encoding, errors)
|
|
634
637
|
if newline is None:
|
|
635
638
|
text = CRE_NOT_UNIX_NEWLINES_sub("\n", text)
|
|
@@ -644,8 +647,10 @@ class AsyncTextIOWrapper(TextIOWrapper):
|
|
|
644
647
|
|
|
645
648
|
ls_parts: list[str] = []
|
|
646
649
|
add_part = ls_parts.append
|
|
647
|
-
|
|
648
|
-
|
|
650
|
+
if not isinstance(data, Sized):
|
|
651
|
+
data = memoryview(data)
|
|
652
|
+
cache = bytes(data)
|
|
653
|
+
while size and len(cast(Sized, data)) == size:
|
|
649
654
|
while cache:
|
|
650
655
|
try:
|
|
651
656
|
size -= process_part(cache)
|
|
@@ -684,6 +689,8 @@ class AsyncTextIOWrapper(TextIOWrapper):
|
|
|
684
689
|
size -= process_part(cache[start:stop], errors)
|
|
685
690
|
cache = cache[stop:]
|
|
686
691
|
data = await read(size)
|
|
692
|
+
if not isinstance(data, Sized):
|
|
693
|
+
data = memoryview(data)
|
|
687
694
|
cache += data
|
|
688
695
|
if cache:
|
|
689
696
|
process_part(cache, errors)
|
|
@@ -730,12 +737,15 @@ class AsyncTextIOWrapper(TextIOWrapper):
|
|
|
730
737
|
break
|
|
731
738
|
elif buf.endswith(crb):
|
|
732
739
|
peek_maybe_lfb = await read(lfb_len)
|
|
740
|
+
if not isinstance(peek_maybe_lfb, Sized):
|
|
741
|
+
peek_maybe_lfb = memoryview(peek_maybe_lfb)
|
|
733
742
|
if peek_maybe_lfb == lfb:
|
|
734
743
|
buf += lfb
|
|
735
744
|
elif peek_maybe_lfb:
|
|
736
745
|
# TODO: 这是一个提前量,未必需要立即往回 seek,因为转换为 str 后可能尾部不是 \r(因为可以和前面的符号结合),所以这个可能可以被复用,如果需要优化,可以在程序结束时的 finally 部分最终执行 seek(可能最终字符被消耗所以不需要 seek)
|
|
737
|
-
|
|
738
|
-
|
|
746
|
+
o = len(cast(Sized, peek_maybe_lfb))
|
|
747
|
+
await seek(-o, 1)
|
|
748
|
+
if o < lfb_len:
|
|
739
749
|
reach_end = True
|
|
740
750
|
break
|
|
741
751
|
else:
|
|
@@ -839,11 +849,14 @@ class AsyncTextIOWrapper(TextIOWrapper):
|
|
|
839
849
|
break
|
|
840
850
|
elif buf.endswith(crb):
|
|
841
851
|
peek_maybe_lfb = await read(lfb_len)
|
|
852
|
+
if not isinstance(peek_maybe_lfb, Sized):
|
|
853
|
+
peek_maybe_lfb = memoryview(peek_maybe_lfb)
|
|
842
854
|
if peek_maybe_lfb == lfb:
|
|
843
855
|
buf += lfb
|
|
844
856
|
elif peek_maybe_lfb:
|
|
845
|
-
|
|
846
|
-
|
|
857
|
+
o = len(cast(Sized, peek_maybe_lfb))
|
|
858
|
+
await seek(-o, 1)
|
|
859
|
+
if o < lfb_len:
|
|
847
860
|
reach_end = True
|
|
848
861
|
break
|
|
849
862
|
else:
|
|
@@ -951,13 +964,13 @@ class AsyncTextIOWrapper(TextIOWrapper):
|
|
|
951
964
|
self.newline = newline
|
|
952
965
|
|
|
953
966
|
async def seek(self, target: int, whence: int = 0, /) -> int: # type: ignore
|
|
954
|
-
return await ensure_async(self.buffer
|
|
967
|
+
return await ensure_async(getattr(self.buffer, "seek"), threaded=True)(target, whence)
|
|
955
968
|
|
|
956
969
|
def tell(self, /) -> int:
|
|
957
|
-
return self.buffer
|
|
970
|
+
return getattr(self.buffer, "tell")()
|
|
958
971
|
|
|
959
972
|
async def truncate(self, pos: None | int = None, /) -> int: # type: ignore
|
|
960
|
-
return await ensure_async(self.buffer
|
|
973
|
+
return await ensure_async(getattr(self.buffer, "truncate"), threaded=True)(pos)
|
|
961
974
|
|
|
962
975
|
async def write(self, text: str, /) -> int: # type: ignore
|
|
963
976
|
match self.newline:
|
|
@@ -1330,7 +1343,8 @@ def bytes_iter_skip(
|
|
|
1330
1343
|
return it
|
|
1331
1344
|
if not callable(callback):
|
|
1332
1345
|
callback = None
|
|
1333
|
-
|
|
1346
|
+
m: memoryview
|
|
1347
|
+
for m in map(memoryview, it): # type: ignore
|
|
1334
1348
|
l = len(m)
|
|
1335
1349
|
if callback:
|
|
1336
1350
|
callback(min(l, size))
|
|
@@ -1516,7 +1530,7 @@ def bytes_iter_to_reader(
|
|
|
1516
1530
|
"__next__": staticmethod(__next__),
|
|
1517
1531
|
"__repr__": staticmethod(lambda: reprs),
|
|
1518
1532
|
"close": staticmethod(close),
|
|
1519
|
-
"closed":
|
|
1533
|
+
"closed": funcproperty(staticmethod(lambda: at_end)),
|
|
1520
1534
|
"peek": staticmethod(peek),
|
|
1521
1535
|
"read": staticmethod(read),
|
|
1522
1536
|
"readinto": staticmethod(readinto),
|
|
@@ -1697,7 +1711,7 @@ def bytes_iter_to_async_reader(
|
|
|
1697
1711
|
"__repr__": staticmethod(lambda: reprs),
|
|
1698
1712
|
"close": staticmethod(close),
|
|
1699
1713
|
"aclose": staticmethod(aclose),
|
|
1700
|
-
"closed":
|
|
1714
|
+
"closed": funcproperty(staticmethod(lambda: at_end)),
|
|
1701
1715
|
"peek": staticmethod(peek),
|
|
1702
1716
|
"read": staticmethod(read),
|
|
1703
1717
|
"readinto": staticmethod(readinto),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "python-filewrap"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.5"
|
|
4
4
|
description = "Python file wrappers."
|
|
5
5
|
authors = ["ChenyangGao <wosiwujm@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -28,7 +28,7 @@ include = [
|
|
|
28
28
|
[tool.poetry.dependencies]
|
|
29
29
|
python = "^3.10"
|
|
30
30
|
python-asynctools = ">=0.0.5"
|
|
31
|
-
python-property = ">=0.0.
|
|
31
|
+
python-property = ">=0.0.3"
|
|
32
32
|
|
|
33
33
|
[build-system]
|
|
34
34
|
requires = ["poetry-core"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|