csu 2.2.0__tar.gz → 2.2.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 (106) hide show
  1. {csu-2.2.0 → csu-2.2.1}/.bumpversion.cfg +1 -1
  2. {csu-2.2.0 → csu-2.2.1}/.cookiecutterrc +1 -1
  3. {csu-2.2.0 → csu-2.2.1}/PKG-INFO +3 -3
  4. {csu-2.2.0 → csu-2.2.1}/README.rst +2 -2
  5. {csu-2.2.0 → csu-2.2.1}/pyproject.toml +1 -1
  6. {csu-2.2.0 → csu-2.2.1}/src/csu/__init__.py +1 -1
  7. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/engine.py +9 -4
  8. {csu-2.2.0 → csu-2.2.1}/src/csu.egg-info/PKG-INFO +3 -3
  9. {csu-2.2.0 → csu-2.2.1}/tests/test_exampleworker.py +28 -7
  10. {csu-2.2.0 → csu-2.2.1}/.coveragerc +0 -0
  11. {csu-2.2.0 → csu-2.2.1}/.editorconfig +0 -0
  12. {csu-2.2.0 → csu-2.2.1}/.github/workflows/github-actions.yml +0 -0
  13. {csu-2.2.0 → csu-2.2.1}/.pre-commit-config.yaml +0 -0
  14. {csu-2.2.0 → csu-2.2.1}/.taplo.toml +0 -0
  15. {csu-2.2.0 → csu-2.2.1}/AUTHORS.rst +0 -0
  16. {csu-2.2.0 → csu-2.2.1}/CHANGELOG.rst +0 -0
  17. {csu-2.2.0 → csu-2.2.1}/CONTRIBUTING.rst +0 -0
  18. {csu-2.2.0 → csu-2.2.1}/LICENSE +0 -0
  19. {csu-2.2.0 → csu-2.2.1}/MANIFEST.in +0 -0
  20. {csu-2.2.0 → csu-2.2.1}/ci/bootstrap.py +0 -0
  21. {csu-2.2.0 → csu-2.2.1}/ci/requirements.txt +0 -0
  22. {csu-2.2.0 → csu-2.2.1}/ci/templates/.github/workflows/github-actions.yml +0 -0
  23. {csu-2.2.0 → csu-2.2.1}/pytest.ini +0 -0
  24. {csu-2.2.0 → csu-2.2.1}/setup.cfg +0 -0
  25. {csu-2.2.0 → csu-2.2.1}/src/csu/admin.py +0 -0
  26. {csu-2.2.0 → csu-2.2.1}/src/csu/conf.py +0 -0
  27. {csu-2.2.0 → csu-2.2.1}/src/csu/consts.py +0 -0
  28. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/__init__.py +0 -0
  29. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/auth.py +0 -0
  30. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/fields.py +0 -0
  31. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/forms.py +0 -0
  32. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/perms.py +0 -0
  33. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/phonenumber.py +0 -0
  34. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/serializers.py +0 -0
  35. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/test_auth.py +0 -0
  36. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/test_fields.py +0 -0
  37. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/test_forms.py +0 -0
  38. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/test_phonenumber.py +0 -0
  39. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/test_serializers.py +0 -0
  40. {csu-2.2.0 → csu-2.2.1}/src/csu/drf/views.py +0 -0
  41. {csu-2.2.0 → csu-2.2.1}/src/csu/enums.py +0 -0
  42. {csu-2.2.0 → csu-2.2.1}/src/csu/env.py +0 -0
  43. {csu-2.2.0 → csu-2.2.1}/src/csu/exceptions.py +0 -0
  44. {csu-2.2.0 → csu-2.2.1}/src/csu/export.py +0 -0
  45. {csu-2.2.0 → csu-2.2.1}/src/csu/fixups.py +0 -0
  46. {csu-2.2.0 → csu-2.2.1}/src/csu/forms/__init__.py +0 -0
  47. {csu-2.2.0 → csu-2.2.1}/src/csu/forms/crispy.py +0 -0
  48. {csu-2.2.0 → csu-2.2.1}/src/csu/forms/fields.py +0 -0
  49. {csu-2.2.0 → csu-2.2.1}/src/csu/gettext.py +0 -0
  50. {csu-2.2.0 → csu-2.2.1}/src/csu/gettext_lazy.py +0 -0
  51. {csu-2.2.0 → csu-2.2.1}/src/csu/locale/ro/LC_MESSAGES/django.mo +0 -0
  52. {csu-2.2.0 → csu-2.2.1}/src/csu/locale/ro/LC_MESSAGES/django.po +0 -0
  53. {csu-2.2.0 → csu-2.2.1}/src/csu/logging.py +0 -0
  54. {csu-2.2.0 → csu-2.2.1}/src/csu/management.py +0 -0
  55. {csu-2.2.0 → csu-2.2.1}/src/csu/models.py +0 -0
  56. {csu-2.2.0 → csu-2.2.1}/src/csu/query.py +0 -0
  57. {csu-2.2.0 → csu-2.2.1}/src/csu/routers.py +0 -0
  58. {csu-2.2.0 → csu-2.2.1}/src/csu/service.py +0 -0
  59. {csu-2.2.0 → csu-2.2.1}/src/csu/templates/api_exception.html +0 -0
  60. {csu-2.2.0 → csu-2.2.1}/src/csu/templates/forms/widgets/opaquewidget.html +0 -0
  61. {csu-2.2.0 → csu-2.2.1}/src/csu/test_consts.py +0 -0
  62. {csu-2.2.0 → csu-2.2.1}/src/csu/test_env.py +0 -0
  63. {csu-2.2.0 → csu-2.2.1}/src/csu/test_exceptions.py +0 -0
  64. {csu-2.2.0 → csu-2.2.1}/src/csu/test_logging.py +0 -0
  65. {csu-2.2.0 → csu-2.2.1}/src/csu/test_management.py +0 -0
  66. {csu-2.2.0 → csu-2.2.1}/src/csu/test_service.py +0 -0
  67. {csu-2.2.0 → csu-2.2.1}/src/csu/test_timezones.py +0 -0
  68. {csu-2.2.0 → csu-2.2.1}/src/csu/test_utils.py +0 -0
  69. {csu-2.2.0 → csu-2.2.1}/src/csu/test_xml.py +0 -0
  70. {csu-2.2.0 → csu-2.2.1}/src/csu/timezones.py +0 -0
  71. {csu-2.2.0 → csu-2.2.1}/src/csu/utils.py +0 -0
  72. {csu-2.2.0 → csu-2.2.1}/src/csu/views.py +0 -0
  73. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/__init__.py +0 -0
  74. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/admin.py +0 -0
  75. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/asgi.py +0 -0
  76. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/enums.py +0 -0
  77. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/job.py +0 -0
  78. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/models.py +0 -0
  79. {csu-2.2.0 → csu-2.2.1}/src/csu/worker/registry.py +0 -0
  80. {csu-2.2.0 → csu-2.2.1}/src/csu/wsgi.py +0 -0
  81. {csu-2.2.0 → csu-2.2.1}/src/csu/xml.py +0 -0
  82. {csu-2.2.0 → csu-2.2.1}/src/csu.egg-info/SOURCES.txt +0 -0
  83. {csu-2.2.0 → csu-2.2.1}/src/csu.egg-info/dependency_links.txt +0 -0
  84. {csu-2.2.0 → csu-2.2.1}/src/csu.egg-info/requires.txt +0 -0
  85. {csu-2.2.0 → csu-2.2.1}/src/csu.egg-info/top_level.txt +0 -0
  86. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service/test_custom_context.yaml +0 -0
  87. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service/test_custom_context_0_retries.yaml +0 -0
  88. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service/test_decoding.yaml +0 -0
  89. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service/test_error.yaml +0 -0
  90. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service/test_logging.yaml +0 -0
  91. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service/test_redirects.yaml +0 -0
  92. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service_auth/test_async.yaml +0 -0
  93. {csu-2.2.0 → csu-2.2.1}/tests/cassettes/test_service_auth/test_sync.yaml +0 -0
  94. {csu-2.2.0 → csu-2.2.1}/tests/conftest.py +0 -0
  95. {csu-2.2.0 → csu-2.2.1}/tests/exampleworker.py +0 -0
  96. {csu-2.2.0 → csu-2.2.1}/tests/test_models.py +0 -0
  97. {csu-2.2.0 → csu-2.2.1}/tests/test_service.py +0 -0
  98. {csu-2.2.0 → csu-2.2.1}/tests/test_service_auth.py +0 -0
  99. {csu-2.2.0 → csu-2.2.1}/tests/test_views.py +0 -0
  100. {csu-2.2.0 → csu-2.2.1}/tests/test_worker.py +0 -0
  101. {csu-2.2.0 → csu-2.2.1}/tests/testproject/__init__.py +0 -0
  102. {csu-2.2.0 → csu-2.2.1}/tests/testproject/fixtures/testuser.json +0 -0
  103. {csu-2.2.0 → csu-2.2.1}/tests/testproject/models.py +0 -0
  104. {csu-2.2.0 → csu-2.2.1}/tests/testproject/settings.py +0 -0
  105. {csu-2.2.0 → csu-2.2.1}/tests/testproject/urls.py +0 -0
  106. {csu-2.2.0 → csu-2.2.1}/tox.ini +0 -0
@@ -1,5 +1,5 @@
1
1
  [bumpversion]
2
- current_version = 2.2.0
2
+ current_version = 2.2.1
3
3
  commit = True
4
4
  tag = True
5
5
 
@@ -40,7 +40,7 @@ default_context:
40
40
  sphinx_theme: furo
41
41
  test_matrix_separate_coverage: 'no'
42
42
  tests_inside_package: 'yes'
43
- version: 2.2.0
43
+ version: 2.2.1
44
44
  version_manager: bump2version
45
45
  website: https://blog.ionelmc.ro
46
46
  year_from: '2024'
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csu
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Clean Slate Utils - bunch of utility code, mostly Django/DRF specific.
5
5
  Author-email: Ionel Cristian Mărieș <contact@ionelmc.ro>
6
6
  License-Expression: BSD-2-Clause
@@ -77,9 +77,9 @@ Overview
77
77
  .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/csu.svg
78
78
  :alt: Supported implementations
79
79
  :target: https://pypi.org/project/csu
80
- .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.2.0.svg
80
+ .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.2.1.svg
81
81
  :alt: Commits since latest release
82
- :target: https://github.com/ionelmc/python-csu/compare/v2.2.0...main
82
+ :target: https://github.com/ionelmc/python-csu/compare/v2.2.1...main
83
83
  .. |scrutinizer| image:: https://img.shields.io/scrutinizer/quality/g/ionelmc/python-csu/main.svg
84
84
  :alt: Scrutinizer Status
85
85
  :target: https://scrutinizer-ci.com/g/ionelmc/python-csu/
@@ -34,9 +34,9 @@ Overview
34
34
  .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/csu.svg
35
35
  :alt: Supported implementations
36
36
  :target: https://pypi.org/project/csu
37
- .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.2.0.svg
37
+ .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.2.1.svg
38
38
  :alt: Commits since latest release
39
- :target: https://github.com/ionelmc/python-csu/compare/v2.2.0...main
39
+ :target: https://github.com/ionelmc/python-csu/compare/v2.2.1...main
40
40
  .. |scrutinizer| image:: https://img.shields.io/scrutinizer/quality/g/ionelmc/python-csu/main.svg
41
41
  :alt: Scrutinizer Status
42
42
  :target: https://scrutinizer-ci.com/g/ionelmc/python-csu/
@@ -12,7 +12,7 @@ dynamic = [
12
12
  "readme",
13
13
  ]
14
14
  name = "csu"
15
- version = "2.2.0"
15
+ version = "2.2.1"
16
16
  license = "BSD-2-Clause"
17
17
  license-files = ["LICENSE"]
18
18
  description = "Clean Slate Utils - bunch of utility code, mostly Django/DRF specific."
@@ -2,4 +2,4 @@
2
2
  a.k.a Clean Slate Utils
3
3
  """
4
4
 
5
- __version__ = "2.2.0"
5
+ __version__ = "2.2.1"
@@ -173,7 +173,7 @@ class AbstractProducer(AbstractWorker):
173
173
  if self.shutdown_requested:
174
174
  break
175
175
  self.state = WorkerState.WAITING
176
- await self.engine.wait_worker_ready()
176
+ await self.engine.before_produce()
177
177
  if self.shutdown_requested:
178
178
  break
179
179
  try:
@@ -187,11 +187,13 @@ class AbstractProducer(AbstractWorker):
187
187
  task = None
188
188
  if task:
189
189
  # noinspection PyArgumentList
190
- await self.engine.push(job := self.job_class(**task.job_kwargs))
190
+ job = self.job_class(**task.job_kwargs)
191
+ await self.engine.push(job)
191
192
  logger.info("%s.run() awaiting %s.done of %s.", self, job, task)
192
193
  await task.done_watchdog(job)
193
194
  if self.shutdown_requested:
194
195
  break
196
+ self.engine.after_produce(idle=not task)
195
197
  self.state = WorkerState.AFTER
196
198
  await self.after(idle=not task)
197
199
 
@@ -295,10 +297,14 @@ class AbstractEngine(ABC):
295
297
  # if raised then there's no task to mark as done (this won't be reached on exception)
296
298
  self.queue.task_done()
297
299
 
298
- async def wait_worker_ready(self):
300
+ async def before_produce(self):
299
301
  # event set after consuming, cleared right before there's a task
300
302
  await self.queue_sem.acquire()
301
303
 
304
+ def after_produce(self, *, idle):
305
+ if idle:
306
+ self.queue_sem.release()
307
+
302
308
  def add_worker(self, worker: AbstractWorker):
303
309
  assert self.queue is None, f"{self} is already started, {self.queue=}"
304
310
  self.workers.append(worker)
@@ -352,7 +358,6 @@ class AbstractEngine(ABC):
352
358
  for worker in self.workers:
353
359
  worker.runner.cancel()
354
360
  await asyncio.gather(*[worker.runner for worker in self.workers], return_exceptions=True)
355
- self.workers.clear()
356
361
  logger.info("%s shutdown complete.", self)
357
362
 
358
363
  def report(self, inspect: defaultdict[str, object]):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csu
3
- Version: 2.2.0
3
+ Version: 2.2.1
4
4
  Summary: Clean Slate Utils - bunch of utility code, mostly Django/DRF specific.
5
5
  Author-email: Ionel Cristian Mărieș <contact@ionelmc.ro>
6
6
  License-Expression: BSD-2-Clause
@@ -77,9 +77,9 @@ Overview
77
77
  .. |supported-implementations| image:: https://img.shields.io/pypi/implementation/csu.svg
78
78
  :alt: Supported implementations
79
79
  :target: https://pypi.org/project/csu
80
- .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.2.0.svg
80
+ .. |commits-since| image:: https://img.shields.io/github/commits-since/ionelmc/python-csu/v2.2.1.svg
81
81
  :alt: Commits since latest release
82
- :target: https://github.com/ionelmc/python-csu/compare/v2.2.0...main
82
+ :target: https://github.com/ionelmc/python-csu/compare/v2.2.1...main
83
83
  .. |scrutinizer| image:: https://img.shields.io/scrutinizer/quality/g/ionelmc/python-csu/main.svg
84
84
  :alt: Scrutinizer Status
85
85
  :target: https://scrutinizer-ci.com/g/ionelmc/python-csu/
@@ -108,13 +108,13 @@ def test_graceful_shutdown():
108
108
  "INFO:worker:ExampleEngine(4w/0q) requesting workers to stop and awaiting 1 producers...",
109
109
  "CONSUMER 0 perform_work JOB 1 DONE",
110
110
  "CONSUMER 0 save_result JOB 1",
111
- "INFO:worker:ExampleProducer(1/WAITING).on_exit(<Task finished name='Task-5' coro=<AbstractProducer.run() done, defined at /home/ionel/open-source/python-csu/src/csu/worker/engine.py:167> result=None>) exit with result: None",
111
+ "INFO:worker:ExampleProducer(1/WAITING).on_exit(",
112
112
  "INFO:worker:ExampleEngine(4w/0q) flushing queue (0 items) and awaiting consumers...",
113
- "INFO:worker:ExampleConsumer(1/SHUTDOWN).on_exit(<Task finished name='Task-2' coro=<AbstractConsumer.run() done, defined at /home/ionel/open-source/python-csu/src/csu/worker/engine.py:214> result=None>) exit with result: None",
114
- "INFO:worker:ExampleConsumer(2/SHUTDOWN).on_exit(<Task finished name='Task-3' coro=<AbstractConsumer.run() done, defined at /home/ionel/open-source/python-csu/src/csu/worker/engine.py:214> result=None>) exit with result: None",
115
- "INFO:worker:ExampleConsumer(3/SHUTDOWN).on_exit(<Task finished name='Task-4' coro=<AbstractConsumer.run() done, defined at /home/ionel/open-source/python-csu/src/csu/worker/engine.py:214> result=None>) exit with result: None",
116
- "INFO:worker:ExampleEngine(0w/0q) shutdown complete.",
117
- "DONE: {'ExampleEngine':",
113
+ "INFO:worker:ExampleConsumer(1/SHUTDOWN).on_exit(",
114
+ "INFO:worker:ExampleConsumer(2/SHUTDOWN).on_exit(",
115
+ "INFO:worker:ExampleConsumer(3/SHUTDOWN).on_exit(",
116
+ "INFO:worker:ExampleEngine(4w/0q) shutdown complete.",
117
+ "DONE: {'ExampleConsumer': {'EXITED': 3}, 'ExampleProducer': {'EXITED': 1}, 'ExampleEngine': {'JOBS': 3, 'QSIZE': 0, 'SEMVAL': 2}}",
118
118
  )
119
119
 
120
120
 
@@ -139,5 +139,26 @@ def test_forced_shutdown():
139
139
  "CONSUMER 1 perform_work JOB 2 DONE",
140
140
  "CONSUMER 2 perform_work JOB 3 DONE",
141
141
  "DONE: {'ExampleConsumer': {'CANCELED': 3}, 'ExampleProducer': {'CANCELED': 1}, 'ExampleEngine': {'JOBS': 3, 'QSIZE': 0, 'SEMVAL': 0}}",
142
- "INFO:worker:ExampleEngine(0w/0q) shutdown complete.",
142
+ )
143
+
144
+
145
+ def test_sem_rollback():
146
+ with TestProcess(sys.executable, "-mexampleworker", "1", "2", "10", "10") as target, dump_on_error(target.read):
147
+ wait_for_strings(
148
+ target.read,
149
+ 15,
150
+ "PRODUCER fetch_task @ 1 RETURN",
151
+ "CONSUMER 0 perform_work JOB 1 START",
152
+ "CONSUMER 0 perform_work JOB 1 DONE",
153
+ "CONSUMER 0 save_result JOB 1",
154
+ "PRODUCER fetch_task @ 2 SKIP",
155
+ "PRODUCER fetch_task @ 3 RETURN",
156
+ "CONSUMER 0 perform_work JOB 3 START",
157
+ "CONSUMER 0 perform_work JOB 3 DONE",
158
+ "CONSUMER 0 save_result JOB 3",
159
+ "PRODUCER fetch_task @ 4 SKIP",
160
+ "PRODUCER fetch_task @ 5 RETURN",
161
+ "CONSUMER 0 perform_work JOB 5 START",
162
+ "CONSUMER 0 perform_work JOB 5 DONE",
163
+ "CONSUMER 0 save_result JOB 5",
143
164
  )
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes