python-filewrap 0.1__tar.gz → 0.1.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.1
3
+ Version: 0.1.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
@@ -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, 1)
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 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
 
@@ -354,7 +355,7 @@ def bytes_iter_skip(
354
355
  /,
355
356
  size: int = -1,
356
357
  callback: None | Callable[[int], Any] = None,
357
- ) -> Iterator[memoryview | Buffer]:
358
+ ) -> Iterator[Buffer]:
358
359
  it = iter(it)
359
360
  if size == 0:
360
361
  return it
@@ -378,7 +379,7 @@ async def bytes_async_iter_skip(
378
379
  /,
379
380
  size: int = -1,
380
381
  callback: None | Callable[[int], Any] = None,
381
- ) -> AsyncIterator[memoryview | Buffer]:
382
+ ) -> AsyncIterator[Buffer]:
382
383
  it = aiter(ensure_aiter(it))
383
384
  if size == 0:
384
385
  return it
@@ -604,7 +605,7 @@ def bytes_ensure_part_iter(
604
605
  it: Iterable[Buffer],
605
606
  /,
606
607
  partsize: int = COPY_BUFSIZE,
607
- ) -> Iterator[Buffer | memoryview]:
608
+ ) -> Iterator[Buffer]:
608
609
  n = partsize
609
610
  for b in it:
610
611
  m = memoryview(b)
@@ -632,7 +633,7 @@ async def bytes_ensure_part_async_iter(
632
633
  it: Iterable[Buffer] | AsyncIterable[Buffer],
633
634
  /,
634
635
  partsize: int = COPY_BUFSIZE,
635
- ) -> AsyncIterator[Buffer | memoryview]:
636
+ ) -> AsyncIterator[Buffer]:
636
637
  n = partsize
637
638
  async for b in ensure_aiter(it):
638
639
  m = memoryview(b)
@@ -655,3 +656,71 @@ 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],
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(make_progress):
670
+ progress = make_progress(*args, **kwds)
671
+ if isgenerator(progress):
672
+ next(progress)
673
+ update_progress = progress.send
674
+ close_progress = progress.close
675
+ else:
676
+ update_progress = progress
677
+ close_progress = getattr(progress, "close", None)
678
+ try:
679
+ if callable(update_progress):
680
+ for chunk in it:
681
+ yield chunk
682
+ update_progress(len(chunk))
683
+ else:
684
+ for chunk in it:
685
+ yield chunk
686
+ finally:
687
+ if callable(close_progress):
688
+ close_progress()
689
+
690
+
691
+ async def progress_bytes_async_iter(
692
+ it: Iterable[Buffer] | AsyncIterable[Buffer],
693
+ make_progress: None | Callable[Args, Any] = None,
694
+ /,
695
+ *args: Args.args,
696
+ **kwds: Args.kwargs,
697
+ ) -> AsyncIterator[Buffer]:
698
+ update_progress: None | Callable = None
699
+ close_progress: None | Callable = None
700
+ if callable(make_progress):
701
+ progress = make_progress(*args, **kwds)
702
+ if isgenerator(progress):
703
+ await ensure_async(next)(progress)
704
+ update_progress = progress.send
705
+ close_progress = progress.close
706
+ elif isasyncgen(progress):
707
+ await anext(progress)
708
+ update_progress = progress.asend
709
+ close_progress = progress.aclose
710
+ else:
711
+ update_progress = progress
712
+ close_progress = getattr(progress, "close", None)
713
+ try:
714
+ it = ensure_aiter(it)
715
+ if callable(update_progress):
716
+ update_progress = ensure_async(update_progress)
717
+ async for chunk in it:
718
+ yield chunk
719
+ await update_progress(len(chunk))
720
+ else:
721
+ async for chunk in it:
722
+ yield chunk
723
+ finally:
724
+ if callable(close_progress):
725
+ await ensure_async(close_progress)()
726
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-filewrap"
3
- version = "0.1"
3
+ version = "0.1.1"
4
4
  description = "Python file wrappers."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"
File without changes
File without changes