fluentmap 0.0.2__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.
@@ -0,0 +1,145 @@
1
+ Metadata-Version: 2.1
2
+ Name: fluentmap
3
+ Version: 0.1.1
4
+ Summary: A drop-in Python map replacement featuring parallel and batch processing.
5
+ Author: leavers
6
+ Author-Email: Leavers <leavers930@gmail.com>
7
+ License: MIT
8
+ Classifier: Intended Audience :: Developers
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Classifier: Programming Language :: Python
12
+ Classifier: Programming Language :: Python :: 3
13
+ Classifier: Programming Language :: Python :: 3.8
14
+ Classifier: Programming Language :: Python :: 3.9
15
+ Classifier: Programming Language :: Python :: 3.10
16
+ Classifier: Programming Language :: Python :: 3.11
17
+ Classifier: Programming Language :: Python :: 3.12
18
+ Classifier: Programming Language :: Python :: 3.13
19
+ Classifier: Programming Language :: Python :: 3.14
20
+ Classifier: Programming Language :: Python :: 3.15
21
+ Classifier: Topic :: Software Development
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+
27
+ # Fluentmap
28
+
29
+ [![Testing](https://github.com/leavers/fluentmap/actions/workflows/test-suite.yml/badge.svg)](https://github.com/leavers/fluentmap/actions/workflows/test-suite.yml)
30
+ [![Package version](https://img.shields.io/pypi/v/fluentmap.svg)](https://pypi.org/project/fluentmap/)
31
+ [![Python](https://img.shields.io/pypi/pyversions/fluentmap.svg)](https://pypi.org/project/fluentmap/)
32
+
33
+ Fluentmap provides a drop-in Python map replacement featuring parallel and batch
34
+ processing.
35
+
36
+ ## Features
37
+
38
+ - Use `executor` to run tasks in parallel.
39
+ - Use `batch_size`/`chunk_size` to send parameters in batches/chunks.
40
+ - Use `num_prepare` to prepare data in advance for better performance.
41
+ - Call `on_return` hook to process the return value of each task.
42
+
43
+ ## Installation
44
+
45
+ Fluentmap requires Python 3.8 or newer, has no runtime dependencies, and is tested
46
+ on CPython 3.8-3.15, including the free-threaded builds (3.13t-3.15t).
47
+
48
+ Fluentmap is available on [PyPI](https://pypi.org/project/fluentmap/):
49
+
50
+ ```shell
51
+ pip install fluentmap
52
+ ```
53
+
54
+ ## Usage
55
+
56
+ ### Drop-in replacement
57
+
58
+ You can start to use fluentmap just like built-in `map`:
59
+
60
+ ```python
61
+ from typing import Any, List
62
+
63
+ from fluentmap import map
64
+
65
+
66
+ items: List[str] = [...]
67
+
68
+
69
+ def heavy_task(item: str) -> Any:
70
+ """Suppose this function represents a computationally expensive task."""
71
+
72
+
73
+ def postprocessing(result: Any):
74
+ """Suppose this function represents a postprocessing task."""
75
+
76
+
77
+ for result in map(heavy_task, items):
78
+ postprocessing(result)
79
+ ```
80
+
81
+ ### Parallel processing
82
+
83
+ As `heavy_task` is a computationally expensive task, you can use `executor` to
84
+ run it in parallel.
85
+
86
+ ```python
87
+ from concurrent.futures import ProcessPoolExecutor
88
+
89
+ from fluentmap import map
90
+
91
+ # ......
92
+
93
+ with ProcessPoolExecutor() as executor:
94
+ # each heavy_task invocation runs in a separate process
95
+ for result in map(heavy_task, items, executor=executor):
96
+ postprocessing(result)
97
+ ```
98
+
99
+ ### Batch/chunk processing
100
+
101
+ You can use `batch_size`/`chunk_size` to send arguments in batches/chunks.
102
+
103
+ The difference between them is that `batch_size` packs multiple arguments into a batch
104
+ before sending them to the function, therefore the function needs to be modified to
105
+ handle a list of arguments.
106
+
107
+ On the other hand, `chunk_size` packs multiple arguments into a chunks before passing
108
+ them to executor workers, while workers still process each argument sequentially.
109
+
110
+ ```python
111
+ from concurrent.futures import ProcessPoolExecutor
112
+ from typing import Any, List
113
+
114
+ from fluentmap import map
115
+
116
+
117
+ # ......
118
+
119
+
120
+ def heavy_task_in_batch(item: List[str]) -> Any:
121
+ """Note that `item` is a list since when `batch_size` is set,
122
+ fluentmap will concatenate multiple items into a batch before sending them to
123
+ the function which is to be invoked.
124
+ """
125
+
126
+
127
+ # An example of using `batch_size`
128
+ with ProcessPoolExecutor() as executor:
129
+ for result in map(
130
+ heavy_task_in_batch,
131
+ items,
132
+ executor=executor,
133
+ batch_size=64,
134
+ ):
135
+ postprocessing(result)
136
+
137
+ # An example of using `chunk_size`
138
+ with ProcessPoolExecutor() as executor:
139
+ for result in map(
140
+ heavy_task,
141
+ items,
142
+ executor=executor,
143
+ chunk_size=32,
144
+ ):
145
+ postprocessing(result)
@@ -0,0 +1,119 @@
1
+ # Fluentmap
2
+
3
+ [![Testing](https://github.com/leavers/fluentmap/actions/workflows/test-suite.yml/badge.svg)](https://github.com/leavers/fluentmap/actions/workflows/test-suite.yml)
4
+ [![Package version](https://img.shields.io/pypi/v/fluentmap.svg)](https://pypi.org/project/fluentmap/)
5
+ [![Python](https://img.shields.io/pypi/pyversions/fluentmap.svg)](https://pypi.org/project/fluentmap/)
6
+
7
+ Fluentmap provides a drop-in Python map replacement featuring parallel and batch
8
+ processing.
9
+
10
+ ## Features
11
+
12
+ - Use `executor` to run tasks in parallel.
13
+ - Use `batch_size`/`chunk_size` to send parameters in batches/chunks.
14
+ - Use `num_prepare` to prepare data in advance for better performance.
15
+ - Call `on_return` hook to process the return value of each task.
16
+
17
+ ## Installation
18
+
19
+ Fluentmap requires Python 3.8 or newer, has no runtime dependencies, and is tested
20
+ on CPython 3.8-3.15, including the free-threaded builds (3.13t-3.15t).
21
+
22
+ Fluentmap is available on [PyPI](https://pypi.org/project/fluentmap/):
23
+
24
+ ```shell
25
+ pip install fluentmap
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ ### Drop-in replacement
31
+
32
+ You can start to use fluentmap just like built-in `map`:
33
+
34
+ ```python
35
+ from typing import Any, List
36
+
37
+ from fluentmap import map
38
+
39
+
40
+ items: List[str] = [...]
41
+
42
+
43
+ def heavy_task(item: str) -> Any:
44
+ """Suppose this function represents a computationally expensive task."""
45
+
46
+
47
+ def postprocessing(result: Any):
48
+ """Suppose this function represents a postprocessing task."""
49
+
50
+
51
+ for result in map(heavy_task, items):
52
+ postprocessing(result)
53
+ ```
54
+
55
+ ### Parallel processing
56
+
57
+ As `heavy_task` is a computationally expensive task, you can use `executor` to
58
+ run it in parallel.
59
+
60
+ ```python
61
+ from concurrent.futures import ProcessPoolExecutor
62
+
63
+ from fluentmap import map
64
+
65
+ # ......
66
+
67
+ with ProcessPoolExecutor() as executor:
68
+ # each heavy_task invocation runs in a separate process
69
+ for result in map(heavy_task, items, executor=executor):
70
+ postprocessing(result)
71
+ ```
72
+
73
+ ### Batch/chunk processing
74
+
75
+ You can use `batch_size`/`chunk_size` to send arguments in batches/chunks.
76
+
77
+ The difference between them is that `batch_size` packs multiple arguments into a batch
78
+ before sending them to the function, therefore the function needs to be modified to
79
+ handle a list of arguments.
80
+
81
+ On the other hand, `chunk_size` packs multiple arguments into a chunks before passing
82
+ them to executor workers, while workers still process each argument sequentially.
83
+
84
+ ```python
85
+ from concurrent.futures import ProcessPoolExecutor
86
+ from typing import Any, List
87
+
88
+ from fluentmap import map
89
+
90
+
91
+ # ......
92
+
93
+
94
+ def heavy_task_in_batch(item: List[str]) -> Any:
95
+ """Note that `item` is a list since when `batch_size` is set,
96
+ fluentmap will concatenate multiple items into a batch before sending them to
97
+ the function which is to be invoked.
98
+ """
99
+
100
+
101
+ # An example of using `batch_size`
102
+ with ProcessPoolExecutor() as executor:
103
+ for result in map(
104
+ heavy_task_in_batch,
105
+ items,
106
+ executor=executor,
107
+ batch_size=64,
108
+ ):
109
+ postprocessing(result)
110
+
111
+ # An example of using `chunk_size`
112
+ with ProcessPoolExecutor() as executor:
113
+ for result in map(
114
+ heavy_task,
115
+ items,
116
+ executor=executor,
117
+ chunk_size=32,
118
+ ):
119
+ postprocessing(result)
@@ -1,5 +1,6 @@
1
1
  """
2
- Fluentmap is a drop-in replacement for Python map with concurrency support.
2
+ Fluentmap is a drop-in replacement for Python map featuring parallel and batch
3
+ processing.
3
4
 
4
5
  Copyright (c) 2020-2024, Leavers.
5
6
  License: MIT
@@ -25,7 +26,7 @@ from typing import (
25
26
  runtime_checkable,
26
27
  )
27
28
 
28
- __version__ = "0.0.2"
29
+ __version__ = "0.1.1"
29
30
  __all__ = ("Arguments", "map")
30
31
 
31
32
 
@@ -292,14 +293,14 @@ def _concurrent_chunk_map(
292
293
  break
293
294
 
294
295
  i, raw_result_chunk = pair
295
- results: List[Tuple[Union[T, BaseException], bool]] = []
296
+ results: List[Tuple[Union[T, R, BaseException], bool]] = []
296
297
  for raw_result, is_exc in raw_result_chunk:
297
298
  if is_exc:
298
299
  results.append((raw_result, True))
299
300
  continue
300
301
  try:
301
- new_result = on_return(raw_result) # type: ignore[arg-type]
302
- results.append((new_result, False)) # type: ignore[arg-type]
302
+ new_result = on_return(cast(T, raw_result))
303
+ results.append((new_result, False))
303
304
  except BaseException as exc:
304
305
  results.append((exc, True))
305
306
  del exc
@@ -516,7 +517,7 @@ def _concurrent_map(
516
517
 
517
518
  i, raw_result = pair
518
519
  try:
519
- result = on_return(raw_result) # type: ignore[misc]
520
+ result = on_return(raw_result)
520
521
  outqueue.put((i, result, False))
521
522
  except BaseException as exc:
522
523
  outqueue.put((i, exc, True))
@@ -739,7 +740,7 @@ def map(
739
740
  *more_args,
740
741
  batch_size=batch_size,
741
742
  num_prepare=num_prepare,
742
- on_return=on_return, # type: ignore[arg-type]
743
+ on_return=on_return,
743
744
  )
744
745
 
745
746
  if chunk_size is None or chunk_size <= 1:
@@ -751,7 +752,7 @@ def map(
751
752
  batch_size=batch_size,
752
753
  num_prepare=num_prepare,
753
754
  sort_by_completion=sort_by_completion,
754
- on_return=on_return, # type: ignore[arg-type]
755
+ on_return=on_return,
755
756
  )
756
757
  return _concurrent_chunk_map(
757
758
  fn,
@@ -762,5 +763,5 @@ def map(
762
763
  chunk_size=chunk_size,
763
764
  num_prepare=num_prepare,
764
765
  sort_by_completion=sort_by_completion,
765
- on_return=on_return, # type: ignore[arg-type]
766
+ on_return=on_return,
766
767
  )
@@ -0,0 +1,99 @@
1
+ [project]
2
+ name = "fluentmap"
3
+ description = "A drop-in Python map replacement featuring parallel and batch processing."
4
+ authors = [
5
+ { name = "leavers" },
6
+ { name = "Leavers", email = "leavers930@gmail.com" },
7
+ ]
8
+ classifiers = [
9
+ "Intended Audience :: Developers",
10
+ "License :: OSI Approved :: MIT License",
11
+ "Operating System :: OS Independent",
12
+ "Programming Language :: Python",
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.8",
15
+ "Programming Language :: Python :: 3.9",
16
+ "Programming Language :: Python :: 3.10",
17
+ "Programming Language :: Python :: 3.11",
18
+ "Programming Language :: Python :: 3.12",
19
+ "Programming Language :: Python :: 3.13",
20
+ "Programming Language :: Python :: 3.14",
21
+ "Programming Language :: Python :: 3.15",
22
+ "Topic :: Software Development",
23
+ "Topic :: Software Development :: Libraries :: Python Modules",
24
+ "Topic :: Utilities",
25
+ ]
26
+ dependencies = []
27
+ requires-python = ">=3.8"
28
+ readme = "README.md"
29
+ dynamic = []
30
+ version = "0.1.1"
31
+
32
+ [project.license]
33
+ text = "MIT"
34
+
35
+ [build-system]
36
+ requires = [
37
+ "pdm-backend",
38
+ ]
39
+ build-backend = "pdm.backend"
40
+
41
+ [tool.pdm]
42
+ distribution = true
43
+
44
+ [tool.pdm.build]
45
+ includes = [
46
+ "fluentmap.py",
47
+ ]
48
+ excludes = [
49
+ "tests",
50
+ ]
51
+
52
+ [tool.pdm.version]
53
+ source = "file"
54
+ path = "fluentmap.py"
55
+
56
+ [tool.coverage.run]
57
+ branch = true
58
+ source = [
59
+ "fluentmap.py",
60
+ ]
61
+ parallel = true
62
+
63
+ [tool.coverage.report]
64
+ show_missing = true
65
+ exclude_lines = [
66
+ "pragma: no cover",
67
+ ]
68
+
69
+ [tool.ruff]
70
+ line-length = 88
71
+
72
+ [tool.ruff.lint]
73
+ select = [
74
+ "F401",
75
+ "F841",
76
+ "F601",
77
+ ]
78
+
79
+ [tool.ruff.lint.per-file-ignores]
80
+ "__init__.py" = [
81
+ "F401",
82
+ ]
83
+
84
+ [tool.pytest.ini_options]
85
+ asyncio_mode = "strict"
86
+
87
+ [dependency-groups]
88
+ dev = [
89
+ "coverage[toml]>=7.6.1",
90
+ "ty>=0.0.91",
91
+ "nox>=2024.4.15",
92
+ "pytest>=8.3.2",
93
+ "pytest-asyncio>=0.23.8",
94
+ "pytest-cov>=5.0.0",
95
+ "pytest-mock>=3.14.0",
96
+ "pytest-timeout>=2.3.1",
97
+ "ruff>=0.6.1",
98
+ "tomli>=2.0.1",
99
+ ]
fluentmap-0.0.2/PKG-INFO DELETED
@@ -1,13 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: fluentmap
3
- Version: 0.0.2
4
- Summary: Drop-in replacement for Python map with concurrency support
5
- Author-Email: Leavers <leavers930@gmail.com>
6
- License: MIT
7
- Requires-Python: >=3.8
8
- Description-Content-Type: text/markdown
9
-
10
- # Fluentmap
11
-
12
- Drop-in replacement for Python map with concurrency support.
13
-
fluentmap-0.0.2/README.md DELETED
@@ -1,4 +0,0 @@
1
- # Fluentmap
2
-
3
- Drop-in replacement for Python map with concurrency support.
4
-
@@ -1,79 +0,0 @@
1
- [project]
2
- name = "fluentmap"
3
- description = "Drop-in replacement for Python map with concurrency support"
4
- authors = [
5
- { name = "Leavers", email = "leavers930@gmail.com" },
6
- ]
7
- dependencies = []
8
- requires-python = ">=3.8"
9
- readme = "README.md"
10
- dynamic = []
11
- version = "0.0.2"
12
-
13
- [project.license]
14
- text = "MIT"
15
-
16
- [build-system]
17
- requires = [
18
- "pdm-backend",
19
- ]
20
- build-backend = "pdm.backend"
21
-
22
- [tool.pdm]
23
- distribution = true
24
-
25
- [tool.pdm.build]
26
- includes = [
27
- "fluentmap.py",
28
- ]
29
- excludes = [
30
- "tests",
31
- ]
32
-
33
- [tool.pdm.version]
34
- source = "file"
35
- path = "fluentmap.py"
36
-
37
- [tool.pdm.dev-dependencies]
38
- dev = [
39
- "autoflake>=2.3.1",
40
- "mypy>=1.11.1",
41
- "nox>=2024.4.15",
42
- "pytest>=8.3.2",
43
- "ruff>=0.6.1",
44
- "rtoml>=0.11.0",
45
- ]
46
-
47
- [tool.autoflake]
48
- in-place = true
49
- recursive = true
50
- remove-all-unused-imports = true
51
- ignore-init-module-imports = true
52
- remove-duplicate-keys = true
53
- remove-unused-variables = true
54
-
55
- [tool.coverage.run]
56
- branch = true
57
- source = [
58
- "fluentmap.py",
59
- ]
60
- parallel = true
61
-
62
- [tool.coverage.report]
63
- show_missing = true
64
- exclude_lines = [
65
- "pragma: no cover",
66
- ]
67
-
68
- [tool.ruff]
69
- line-length = 88
70
-
71
- [tool.mypy]
72
- check_untyped_defs = true
73
- follow_imports = "error"
74
- ignore_missing_imports = true
75
- show_error_codes = true
76
- warn_unused_configs = true
77
-
78
- [tool.pytest.ini_options]
79
- asyncio_mode = "strict"
File without changes