python-filewrap 0.1.0.1__tar.gz → 0.1.2__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.1.0.1
3
+ Version: 0.1.2
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,7 +2,7 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 1)
5
+ __version__ = (0, 1, 2)
6
6
  __all__ = [
7
7
  "Buffer", "SupportsRead", "SupportsReadinto",
8
8
  "SupportsWrite", "SupportsSeek",
@@ -12,16 +12,17 @@ __all__ = [
12
12
  "bytes_iter_to_reader", "bytes_iter_to_async_reader",
13
13
  "bytes_to_chunk_iter", "bytes_to_chunk_async_iter",
14
14
  "bytes_ensure_part_iter", "bytes_ensure_part_async_iter",
15
+ "progress_bytes_iter", "progress_bytes_async_iter",
15
16
  ]
16
17
 
17
18
  from asyncio import to_thread, Lock as AsyncLock
18
19
  from collections.abc import Awaitable, AsyncIterable, AsyncIterator, Callable, Iterable, Iterator
19
20
  from functools import update_wrapper
20
- from inspect import isawaitable, iscoroutinefunction
21
+ from inspect import isawaitable, iscoroutinefunction, isasyncgen, isgenerator
21
22
  from itertools import chain
22
23
  from shutil import COPY_BUFSIZE # type: ignore
23
24
  from threading import Lock
24
- from typing import runtime_checkable, Any, Protocol, TypeVar
25
+ from typing import cast, runtime_checkable, Any, ParamSpec, Protocol, TypeVar
25
26
 
26
27
  try:
27
28
  from collections.abc import Buffer # type: ignore
@@ -59,10 +60,10 @@ except ImportError:
59
60
  Buffer.register(memoryview)
60
61
  Buffer.register(array)
61
62
 
62
-
63
63
  from asynctools import async_chain, ensure_async, ensure_aiter
64
64
 
65
65
 
66
+ Args = ParamSpec("Args")
66
67
  _T_co = TypeVar("_T_co", covariant=True)
67
68
  _T_contra = TypeVar("_T_contra", contravariant=True)
68
69
 
@@ -655,3 +656,83 @@ async def bytes_ensure_part_async_iter(
655
656
  else:
656
657
  n = partsize
657
658
 
659
+
660
+ def progress_bytes_iter(
661
+ it: Iterable[Buffer] | Callable[[], Buffer],
662
+ make_progress: None | Callable[Args, Any] = None,
663
+ /,
664
+ *args: Args.args,
665
+ **kwds: Args.kwargs,
666
+ ) -> Iterator[Buffer]:
667
+ update_progress: None | Callable = None
668
+ close_progress: None | Callable = None
669
+ if callable(it):
670
+ it = iter(it, b"")
671
+ if callable(make_progress):
672
+ progress = make_progress(*args, **kwds)
673
+ if isgenerator(progress):
674
+ next(progress)
675
+ update_progress = progress.send
676
+ close_progress = progress.close
677
+ else:
678
+ update_progress = progress
679
+ close_progress = getattr(progress, "close", None)
680
+ try:
681
+ if callable(update_progress):
682
+ for chunk in it:
683
+ yield chunk
684
+ update_progress(len(chunk))
685
+ else:
686
+ for chunk in it:
687
+ yield chunk
688
+ finally:
689
+ if callable(close_progress):
690
+ close_progress()
691
+
692
+
693
+ async def progress_bytes_async_iter(
694
+ it: Iterable[Buffer] | AsyncIterable[Buffer] | Callable[[], Buffer] | Callable[[], Awaitable[Buffer]],
695
+ make_progress: None | Callable[Args, Any] = None,
696
+ /,
697
+ *args: Args.args,
698
+ **kwds: Args.kwargs,
699
+ ) -> AsyncIterator[Buffer]:
700
+ update_progress: None | Callable = None
701
+ close_progress: None | Callable = None
702
+ if callable(it):
703
+ async def wrapiter(it) -> Buffer:
704
+ while True:
705
+ chunk = it()
706
+ if isawaitable(chunk):
707
+ chunk = await chunk
708
+ if not chunk:
709
+ break
710
+ yield chunk
711
+ it = cast(AsyncIterable[Buffer], wrapiter(it))
712
+ if callable(make_progress):
713
+ progress = make_progress(*args, **kwds)
714
+ if isgenerator(progress):
715
+ await ensure_async(next)(progress)
716
+ update_progress = progress.send
717
+ close_progress = progress.close
718
+ elif isasyncgen(progress):
719
+ await anext(progress)
720
+ update_progress = progress.asend
721
+ close_progress = progress.aclose
722
+ else:
723
+ update_progress = progress
724
+ close_progress = getattr(progress, "close", None)
725
+ try:
726
+ it = ensure_aiter(it)
727
+ if callable(update_progress):
728
+ update_progress = ensure_async(update_progress)
729
+ async for chunk in it:
730
+ yield chunk
731
+ await update_progress(len(chunk))
732
+ else:
733
+ async for chunk in it:
734
+ yield chunk
735
+ finally:
736
+ if callable(close_progress):
737
+ await ensure_async(close_progress)()
738
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-filewrap"
3
- version = "0.1.0.1"
3
+ version = "0.1.2"
4
4
  description = "Python file wrappers."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"