python-redux 0.18.0__tar.gz → 0.18.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.
Files changed (23) hide show
  1. python_redux-0.18.1/.gitignore +104 -0
  2. {python_redux-0.18.0 → python_redux-0.18.1}/PKG-INFO +8 -18
  3. python_redux-0.18.1/pyproject.toml +93 -0
  4. python_redux-0.18.1/redux/_version.py +16 -0
  5. {python_redux-0.18.0 → python_redux-0.18.1}/redux/autorun.py +2 -3
  6. {python_redux-0.18.0 → python_redux-0.18.1}/redux/basic_types.py +2 -5
  7. {python_redux-0.18.0 → python_redux-0.18.1}/redux/main.py +26 -12
  8. {python_redux-0.18.0 → python_redux-0.18.1}/redux/serialization_mixin.py +2 -2
  9. {python_redux-0.18.0 → python_redux-0.18.1}/redux/side_effect_runner.py +2 -1
  10. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/fixtures/event_loop.py +4 -1
  11. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/fixtures/snapshot.py +3 -1
  12. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/fixtures/store.py +3 -1
  13. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/fixtures/wait_for.py +1 -3
  14. python_redux-0.18.0/pyproject.toml +0 -84
  15. {python_redux-0.18.0 → python_redux-0.18.1}/LICENSE +0 -0
  16. {python_redux-0.18.0 → python_redux-0.18.1}/README.md +0 -0
  17. {python_redux-0.18.0 → python_redux-0.18.1}/redux/__init__.py +0 -0
  18. {python_redux-0.18.0 → python_redux-0.18.1}/redux/combine_reducers.py +0 -0
  19. {python_redux-0.18.0 → python_redux-0.18.1}/redux/py.typed +0 -0
  20. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/__init__.py +0 -0
  21. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/fixtures/__init__.py +0 -0
  22. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/fixtures/monitor.py +0 -0
  23. {python_redux-0.18.0 → python_redux-0.18.1}/redux_pytest/plugin.py +0 -0
@@ -0,0 +1,104 @@
1
+ ### Python ###
2
+ # Byte-compiled / optimized / DLL files
3
+ __pycache__/
4
+ *.py[cod]
5
+ *py.class
6
+
7
+ # C extensions
8
+ *.so
9
+
10
+ # Distribution / packaging
11
+ .Python
12
+ build/
13
+ develop-eggs/
14
+ dist/
15
+ downloads/
16
+ eggs/
17
+ .eggs/
18
+ lib/
19
+ lib64/
20
+ parts/
21
+ sdist/
22
+ var/
23
+ wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+
28
+ # PyInstaller
29
+ # Usually these files are written by a python script from a template
30
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
31
+ *.manifest
32
+ *.spec
33
+
34
+ # Installer Logs
35
+ pip-log.txt
36
+ pip-delete-this-directory.txt
37
+
38
+ # Unit test / coverage reports
39
+ htmlcov/
40
+ .tox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ .hypothesis/
48
+ tests/**/results/**/*.mismatch.jsonc
49
+
50
+ # Translations
51
+ *.mo
52
+ *.pot
53
+
54
+ # Django stuff:
55
+ *.log
56
+ local_settings.py
57
+
58
+ # Flask stuff:
59
+ instance/
60
+ .webassets-cache
61
+
62
+ # Scrapy stuff:
63
+ .scrapy
64
+
65
+ # Sphinx documentation
66
+ docs/_build/
67
+
68
+ # PyBuilder
69
+ target/
70
+
71
+ # Jupyter Notebook
72
+ .ipynb_checkpoints
73
+
74
+ # pyenv
75
+ .python-version
76
+
77
+ # celery beat schedule file
78
+ celerybeat-schedule
79
+
80
+ # SageMath parsed files
81
+ *.sage.py
82
+
83
+ # Environments
84
+ .env
85
+ .venv
86
+ env/
87
+ venv/
88
+ ENV/
89
+
90
+ # Spyder project settings
91
+ .spyderproject
92
+ .spyproject
93
+
94
+ # Rope project settings
95
+ .ropeproject
96
+
97
+ # mkdocs documentation
98
+ /site
99
+
100
+ # mypy
101
+ .mypy_cache/
102
+
103
+ # hatch
104
+ redux/_version.py
@@ -1,23 +1,14 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.3
2
2
  Name: python-redux
3
- Version: 0.18.0
3
+ Version: 0.18.1
4
4
  Summary: Redux implementation for Python
5
- Home-page: https://github.com/sassanh/python-redux/
5
+ Author-email: Sassan Haradji <sassanh@gmail.com>
6
6
  License: Apache-2.0
7
- Keywords: store,redux,reactive,autorun
8
- Author: Sassan Haradji
9
- Author-email: sassanh@gmail.com
10
- Requires-Python: >=3.11,<4.0
11
- Classifier: License :: OSI Approved :: Apache Software License
12
- Classifier: Programming Language :: Python :: 3
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: Programming Language :: Python :: 3.12
15
- Classifier: Programming Language :: Python :: 3.13
16
- Requires-Dist: pyright (>=1.1.383,<2.0.0)
17
- Requires-Dist: python-immutable (>=1.1.1,<2.0.0)
18
- Requires-Dist: python-strtobool (>=1.0.0,<2.0.0)
19
- Requires-Dist: ruff (>=0.6.9,<0.7.0)
20
- Project-URL: Repository, https://github.com/sassanh/python-redux/
7
+ License-File: LICENSE
8
+ Keywords: autorun,reactive,redux,store
9
+ Requires-Python: >=3.11
10
+ Requires-Dist: python-immutable>=1.1.1
11
+ Requires-Dist: python-strtobool>=1.0.0
21
12
  Description-Content-Type: text/markdown
22
13
 
23
14
  # 🎛️ Python Redux
@@ -325,4 +316,3 @@ Contributions following Python best practices are welcome.
325
316
 
326
317
  This project is released under the Apache-2.0 License. See the [LICENSE](./LICENSE)
327
318
  file for more details.
328
-
@@ -0,0 +1,93 @@
1
+ [project]
2
+ name = "python-redux"
3
+ dynamic = ["version"]
4
+ description = "Redux implementation for Python"
5
+ license = { text = "Apache-2.0" }
6
+ readme = "README.md"
7
+ requires-python = ">=3.11"
8
+ keywords = ['store', 'redux', 'reactive', 'autorun']
9
+ dependencies = ["python-immutable >= 1.1.1", "python-strtobool >= 1.0.0"]
10
+
11
+ [tool.uv]
12
+ dev-dependencies = [
13
+ "poethepoet >= 0.24.4",
14
+ "pyright >= 1.1.376",
15
+ "ruff >= 0.6.0",
16
+ "pytest >= 8.1.1",
17
+ "pytest-cov >= 4.1.0",
18
+ "pytest-timeout >= 2.3.1",
19
+ "pytest-mock >= 3.14.0",
20
+ "tenacity >= 8.2.3",
21
+ ]
22
+
23
+ [build-system]
24
+ requires = ["hatchling", "hatch-vcs"]
25
+ build-backend = "hatchling.build"
26
+
27
+ [tool.hatch.version]
28
+ source = "vcs"
29
+
30
+ [tool.hatch.build.hooks.vcs]
31
+ version-file = "redux/_version.py"
32
+
33
+ [tool.hatch.version.raw-options]
34
+ local_scheme = "setup_scm_schemes:local_scheme"
35
+
36
+ [tool.hatch.build]
37
+ packages = ["redux", "redux_pytest"]
38
+
39
+ [tool.hatch.build.targets.sdist]
40
+ packages = ["redux", "redux_pytest"]
41
+
42
+ [[project.authors]]
43
+ name = "Sassan Haradji"
44
+ email = "sassanh@gmail.com"
45
+
46
+ [project.scripts]
47
+ demo = "demo:main"
48
+ todo_demo = "todo_demo:main"
49
+
50
+ [tool.poe.tasks]
51
+ lint = "ruff check . --unsafe-fixes"
52
+ typecheck = "pyright -p pyproject.toml ."
53
+ test = "pytest --cov --cov-report=term-missing --cov-report=html --cov-report=xml"
54
+ sanity = ["typecheck", "lint", "test"]
55
+
56
+ [tool.ruff]
57
+ target-version = 'py311'
58
+
59
+ [tool.ruff.lint]
60
+ select = ['ALL']
61
+ ignore = ['INP001', 'PLR0911', 'D203', 'D213']
62
+ fixable = ['ALL']
63
+ unfixable = []
64
+
65
+ [tool.ruff.lint.flake8-quotes]
66
+ docstring-quotes = "double"
67
+ inline-quotes = "single"
68
+ multiline-quotes = "double"
69
+
70
+ [tool.ruff.lint.per-file-ignores]
71
+ "tests/*" = ["S101", "PLR0915", "PLR2004"]
72
+
73
+ [tool.ruff.format]
74
+ quote-style = 'single'
75
+
76
+ [tool.isort]
77
+ profile = "black"
78
+
79
+ [tool.pyright]
80
+ exclude = ['typings', '.venv']
81
+ filterwarnings = 'error'
82
+
83
+ [tool.pytest.ini_options]
84
+ log_cli = 1
85
+ log_cli_level = 'ERROR'
86
+ timeout = 1
87
+
88
+ [tool.coverage.report]
89
+ exclude_also = ["if TYPE_CHECKING:"]
90
+
91
+ [tool.coverage.run]
92
+ source = ['redux', 'redux_pytest']
93
+ omit = ['redux_pytest/plugin.py', 'redux/_version.py', "setup_scm_schemes.py"]
@@ -0,0 +1,16 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ TYPE_CHECKING = False
4
+ if TYPE_CHECKING:
5
+ from typing import Tuple, Union
6
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
7
+ else:
8
+ VERSION_TUPLE = object
9
+
10
+ version: str
11
+ __version__: str
12
+ __version_tuple__: VERSION_TUPLE
13
+ version_tuple: VERSION_TUPLE
14
+
15
+ __version__ = version = '0.18.1'
16
+ __version_tuple__ = version_tuple = (0, 18, 1)
@@ -9,10 +9,7 @@ from asyncio import Future, Task, iscoroutine, iscoroutinefunction
9
9
  from typing import (
10
10
  TYPE_CHECKING,
11
11
  Any,
12
- Callable,
13
12
  Concatenate,
14
- Coroutine,
15
- Generator,
16
13
  Generic,
17
14
  TypeVar,
18
15
  cast,
@@ -30,6 +27,8 @@ from redux.basic_types import (
30
27
  )
31
28
 
32
29
  if TYPE_CHECKING:
30
+ from collections.abc import Callable, Coroutine, Generator
31
+
33
32
  from redux.main import Store
34
33
 
35
34
 
@@ -1,20 +1,17 @@
1
1
  # ruff: noqa: A003, D100, D101, D102, D103, D104, D105, D107
2
2
  from __future__ import annotations
3
3
 
4
+ from collections.abc import Awaitable, Callable, Coroutine, Sequence
4
5
  from dataclasses import field
5
6
  from types import NoneType
6
7
  from typing import (
7
8
  TYPE_CHECKING,
8
9
  Any,
9
- Awaitable,
10
- Callable,
11
10
  Concatenate,
12
- Coroutine,
13
11
  Generic,
14
12
  Never,
15
13
  ParamSpec,
16
14
  Protocol,
17
- Sequence,
18
15
  TypeAlias,
19
16
  TypeGuard,
20
17
  overload,
@@ -285,7 +282,7 @@ class EventSubscriber(Protocol):
285
282
  ) -> Callable[[], None]: ...
286
283
 
287
284
 
288
- DispatchParameters: TypeAlias = Action | Event | list[Action | Event]
285
+ DispatchParameters: TypeAlias = Action | list[Action]
289
286
 
290
287
 
291
288
  class Dispatch(Protocol, Generic[State, Action, Event]):
@@ -7,11 +7,10 @@ import inspect
7
7
  import queue
8
8
  import weakref
9
9
  from collections import defaultdict
10
+ from collections.abc import Awaitable, Callable
10
11
  from threading import Lock, Thread
11
12
  from typing import (
12
13
  Any,
13
- Awaitable,
14
- Callable,
15
14
  Concatenate,
16
15
  Generic,
17
16
  cast,
@@ -137,13 +136,13 @@ class Store(Generic[State, Action, Event], SerializationMixin):
137
136
  if is_complete_reducer_result(result):
138
137
  self._state = result.state
139
138
  self._call_listeners(self._state)
140
- self.dispatch([*(result.actions or []), *(result.events or [])])
139
+ self._dispatch([*(result.actions or []), *(result.events or [])])
141
140
  elif is_state_reducer_result(result):
142
141
  self._state = result
143
142
  self._call_listeners(self._state)
144
143
 
145
144
  if isinstance(action, FinishAction):
146
- self.dispatch(cast(Event, FinishEvent()))
145
+ self._dispatch([cast(Event, FinishEvent())])
147
146
 
148
147
  def _run_event_handlers(self: Store[State, Action, Event]) -> None:
149
148
  while len(self._events) > 0:
@@ -178,22 +177,37 @@ class Store(Generic[State, Action, Event], SerializationMixin):
178
177
  """Wait for the event handlers to finish."""
179
178
  self._event_handlers_queue.join()
180
179
 
180
+ @overload
181
181
  def dispatch(
182
182
  self: Store[State, Action, Event],
183
- *parameters: DispatchParameters[Action, Event],
184
- with_state: Callable[[State | None], DispatchParameters[Action, Event]]
185
- | None = None,
183
+ *parameters: DispatchParameters[Action],
184
+ ) -> None: ...
185
+ @overload
186
+ def dispatch(
187
+ self: Store[State, Action, Event],
188
+ *,
189
+ with_state: Callable[[State | None], DispatchParameters[Action]] | None = None,
190
+ ) -> None: ...
191
+ def dispatch(
192
+ self: Store[State, Action, Event],
193
+ *parameters: DispatchParameters[Action],
194
+ with_state: Callable[[State | None], DispatchParameters[Action]] | None = None,
186
195
  ) -> None:
187
- """Dispatch actions and/or events."""
196
+ """Dispatch actions."""
188
197
  if with_state is not None:
189
198
  self.dispatch(with_state(self._state))
190
199
 
191
- items = [
192
- item
193
- for items in parameters
194
- for item in (items if isinstance(items, list) else [items])
200
+ actions = [
201
+ action
202
+ for actions in parameters
203
+ for action in (actions if isinstance(actions, list) else [actions])
195
204
  ]
205
+ self._dispatch(actions)
196
206
 
207
+ def _dispatch(
208
+ self: Store[State, Action, Event],
209
+ items: list[Action | Event],
210
+ ) -> None:
197
211
  for item in items:
198
212
  if isinstance(item, BaseAction):
199
213
  action = cast(Action, item)
@@ -21,11 +21,11 @@ class SerializationMixin:
21
21
  obj: object | type,
22
22
  ) -> SnapshotAtom:
23
23
  """Serialize a value to a snapshot atom."""
24
- if isinstance(obj, (int, float, str, bool, NoneType)):
24
+ if isinstance(obj, int | float | str | bool | NoneType):
25
25
  return obj
26
26
  if callable(obj):
27
27
  return cls.serialize_value(obj())
28
- if isinstance(obj, (list, tuple)):
28
+ if isinstance(obj, list | tuple):
29
29
  return [cls.serialize_value(i) for i in obj]
30
30
  if is_immutable(obj):
31
31
  return cls._serialize_dataclass_to_dict(obj)
@@ -7,8 +7,9 @@ import contextlib
7
7
  import threading
8
8
  import weakref
9
9
  from asyncio import Handle, iscoroutine
10
+ from collections.abc import Callable
10
11
  from inspect import signature
11
- from typing import TYPE_CHECKING, Any, Callable, Generic, cast
12
+ from typing import TYPE_CHECKING, Any, Generic, cast
12
13
 
13
14
  from redux.basic_types import Event, EventHandler
14
15
 
@@ -3,10 +3,13 @@ from __future__ import annotations
3
3
 
4
4
  import asyncio
5
5
  import threading
6
- from typing import Coroutine
6
+ from typing import TYPE_CHECKING
7
7
 
8
8
  import pytest
9
9
 
10
+ if TYPE_CHECKING:
11
+ from collections.abc import Coroutine
12
+
10
13
 
11
14
  class LoopThread(threading.Thread):
12
15
  def __init__(self: LoopThread) -> None:
@@ -7,7 +7,7 @@ import json
7
7
  import os
8
8
  from collections import defaultdict
9
9
  from pathlib import Path
10
- from typing import TYPE_CHECKING, Any, Callable, Generic, cast
10
+ from typing import TYPE_CHECKING, Any, Generic, cast
11
11
 
12
12
  import pytest
13
13
  from str_to_bool import str_to_bool
@@ -15,6 +15,8 @@ from str_to_bool import str_to_bool
15
15
  from redux.basic_types import FinishEvent, State
16
16
 
17
17
  if TYPE_CHECKING:
18
+ from collections.abc import Callable
19
+
18
20
  from _pytest.fixtures import SubRequest
19
21
 
20
22
  from redux.main import Store
@@ -2,11 +2,13 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from typing import TYPE_CHECKING, Generator
5
+ from typing import TYPE_CHECKING
6
6
 
7
7
  import pytest
8
8
 
9
9
  if TYPE_CHECKING:
10
+ from collections.abc import Generator
11
+
10
12
  from redux.main import Store
11
13
 
12
14
 
@@ -2,11 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ from collections.abc import Callable, Coroutine, Generator
5
6
  from typing import (
6
7
  TYPE_CHECKING,
7
- Callable,
8
- Coroutine,
9
- Generator,
10
8
  Literal,
11
9
  ParamSpec,
12
10
  TypeAlias,
@@ -1,84 +0,0 @@
1
- [tool.poetry]
2
- name = "python-redux"
3
- version = "0.18.0"
4
- description = "Redux implementation for Python"
5
- authors = ["Sassan Haradji <sassanh@gmail.com>"]
6
- license = "Apache-2.0"
7
- readme = "README.md"
8
- homepage = 'https://github.com/sassanh/python-redux/'
9
- repository = 'https://github.com/sassanh/python-redux/'
10
- keywords = ['store', 'redux', 'reactive', 'autorun']
11
- packages = [{ include = "redux" }, { include = "redux_pytest" }]
12
-
13
- [tool.poetry.dependencies]
14
- python = "^3.11"
15
- python-immutable = "^1.1.1"
16
- python-strtobool = "^1.0.0"
17
- pyright = "^1.1.383"
18
- ruff = "^0.6.9"
19
-
20
- [tool.poetry.group.dev]
21
- optional = true
22
-
23
- [tool.poetry.group.dev.dependencies]
24
- poethepoet = "^0.24.4"
25
- pyright = "^1.1.376"
26
- ruff = "^0.6.0"
27
- pytest = "^8.1.1"
28
- pytest-cov = "^4.1.0"
29
- pytest-timeout = "^2.3.1"
30
- pytest-mock = "^3.14.0"
31
- tenacity = "^8.2.3"
32
-
33
- [build-system]
34
- requires = ["poetry-core"]
35
- build-backend = "poetry.core.masonry.api"
36
-
37
- [tool.poetry.scripts]
38
- demo = "demo:main"
39
- todo_demo = "todo_demo:main"
40
-
41
- [tool.poe.tasks]
42
- lint = "ruff check . --unsafe-fixes"
43
- typecheck = "pyright -p pyproject.toml ."
44
- test = "pytest --cov --cov-report=term-missing --cov-report=html --cov-report=xml"
45
- sanity = ["typecheck", "lint", "test"]
46
-
47
- [tool.ruff]
48
- lint.select = ['ALL']
49
- lint.ignore = ['INP001', 'PLR0911', 'D203', 'D213']
50
- lint.fixable = ['ALL']
51
- lint.unfixable = []
52
-
53
- [tool.ruff.lint.flake8-quotes]
54
- docstring-quotes = "double"
55
- inline-quotes = "single"
56
- multiline-quotes = "double"
57
-
58
- [tool.ruff.lint.per-file-ignores]
59
- "tests/*" = ["S101", "PLR0915", "PLR2004"]
60
-
61
- [tool.ruff.format]
62
- quote-style = 'single'
63
-
64
- [tool.isort]
65
- profile = "black"
66
-
67
- [tool.pyright]
68
- exclude = ['typings']
69
- filterwarnings = 'error'
70
-
71
- [tool.pytest.ini_options]
72
- log_cli = 1
73
- log_cli_level = 'ERROR'
74
- timeout = 1
75
-
76
- [tool.coverage.report]
77
- exclude_also = ["if TYPE_CHECKING:"]
78
-
79
- [tool.coverage.run]
80
- source = ['redux', 'redux_pytest']
81
- omit = ['redux_pytest/plugin.py']
82
-
83
- [tool.poetry.plugins.pytest11]
84
- redux = "redux_pytest.plugin"
File without changes
File without changes