django-lambda-tasks 0.4.6__tar.gz → 0.4.8__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 (101) hide show
  1. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/PKG-INFO +1 -1
  2. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/local_executor.py +12 -2
  3. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/pyproject.toml +1 -1
  4. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_local_executor.py +23 -5
  5. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.github/workflows/ci.yml +0 -0
  6. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.github/workflows/release.yml +0 -0
  7. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.gitignore +0 -0
  8. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/async-local-execution/.config.kiro +0 -0
  9. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/async-local-execution/design.md +0 -0
  10. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/async-local-execution/requirements.md +0 -0
  11. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/async-local-execution/tasks.md +0 -0
  12. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/deferred-task-enqueue/.config.kiro +0 -0
  13. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/deferred-task-enqueue/design.md +0 -0
  14. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/deferred-task-enqueue/requirements.md +0 -0
  15. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/deferred-task-enqueue/tasks.md +0 -0
  16. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/eager-mode-example-app/.config.kiro +0 -0
  17. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/eager-mode-example-app/design.md +0 -0
  18. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/eager-mode-example-app/requirements.md +0 -0
  19. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/eager-mode-example-app/tasks.md +0 -0
  20. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ignore-errors-decorator-option/.config.kiro +0 -0
  21. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ignore-errors-decorator-option/design.md +0 -0
  22. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ignore-errors-decorator-option/requirements.md +0 -0
  23. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ignore-errors-decorator-option/tasks.md +0 -0
  24. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/import-string-task-resolution/.config.kiro +0 -0
  25. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/import-string-task-resolution/design.md +0 -0
  26. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/import-string-task-resolution/requirements.md +0 -0
  27. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/import-string-task-resolution/tasks.md +0 -0
  28. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/retry-delay/.config.kiro +0 -0
  29. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/retry-delay/design.md +0 -0
  30. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/retry-delay/requirements.md +0 -0
  31. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/retry-delay/tasks.md +0 -0
  32. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks/.config.kiro +0 -0
  33. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks/design.md +0 -0
  34. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks/requirements.md +0 -0
  35. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks/tasks.md +0 -0
  36. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks-bugfix/.config.kiro +0 -0
  37. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks-bugfix/bugfix.md +0 -0
  38. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks-bugfix/design.md +0 -0
  39. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/rse-background-tasks-bugfix/tasks.md +0 -0
  40. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/singleton-task/.config.kiro +0 -0
  41. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/singleton-task/design.md +0 -0
  42. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/singleton-task/requirements.md +0 -0
  43. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/singleton-task/tasks.md +0 -0
  44. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ssm-environment-loader/.config.kiro +0 -0
  45. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ssm-environment-loader/design.md +0 -0
  46. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ssm-environment-loader/requirements.md +0 -0
  47. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/ssm-environment-loader/tasks.md +0 -0
  48. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/task-retry/.config.kiro +0 -0
  49. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/task-retry/design.md +0 -0
  50. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/task-retry/requirements.md +0 -0
  51. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/specs/task-retry/tasks.md +0 -0
  52. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/steering/product.md +0 -0
  53. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/steering/structure.md +0 -0
  54. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.kiro/steering/tech.md +0 -0
  55. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.pre-commit-config.yaml +0 -0
  56. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/.vscode/settings.json +0 -0
  57. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/README.md +0 -0
  58. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/README.md +0 -0
  59. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_app/__init__.py +0 -0
  60. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_app/apps.py +0 -0
  61. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_app/tasks.py +0 -0
  62. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_app/urls.py +0 -0
  63. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_app/views.py +0 -0
  64. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_project/__init__.py +0 -0
  65. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_project/settings.py +0 -0
  66. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_project/urls.py +0 -0
  67. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/example_project/wsgi.py +0 -0
  68. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/example/manage.py +0 -0
  69. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/__init__.py +0 -0
  70. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/admin.py +0 -0
  71. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/apps.py +0 -0
  72. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/decorators.py +0 -0
  73. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/environment_loader.py +0 -0
  74. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/handler.py +0 -0
  75. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/logging.py +0 -0
  76. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/migrations/0001_initial.py +0 -0
  77. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/migrations/0002_alter_taskrecord_status.py +0 -0
  78. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/migrations/__init__.py +0 -0
  79. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/models.py +0 -0
  80. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/secret_loader.py +0 -0
  81. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/settings.py +0 -0
  82. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/tasks.py +0 -0
  83. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/lambda_tasks/timeouts.py +0 -0
  84. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/conftest.py +0 -0
  85. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/settings.py +0 -0
  86. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_admin.py +0 -0
  87. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_decorator.py +0 -0
  88. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_decorators.py +0 -0
  89. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_deferred_enqueue.py +0 -0
  90. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_environment_loader.py +0 -0
  91. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_handler.py +0 -0
  92. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_kwargs_only.py +0 -0
  93. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_logging.py +0 -0
  94. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_memory_limit.py +0 -0
  95. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_models.py +0 -0
  96. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_secret_loader.py +0 -0
  97. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_serializer.py +0 -0
  98. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_settings.py +0 -0
  99. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_tasks.py +0 -0
  100. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_timeout_validation.py +0 -0
  101. {django_lambda_tasks-0.4.6 → django_lambda_tasks-0.4.8}/tests/test_timeouts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: django-lambda-tasks
3
- Version: 0.4.6
3
+ Version: 0.4.8
4
4
  Summary: Run async tasks in a lambda function
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: awslambdaric
@@ -2,6 +2,7 @@
2
2
 
3
3
  import atexit
4
4
  import logging
5
+ import signal
5
6
  import uuid
6
7
  from concurrent.futures import Future, ProcessPoolExecutor
7
8
 
@@ -13,7 +14,16 @@ _pool: ProcessPoolExecutor | None = None
13
14
 
14
15
 
15
16
  def _pool_initializer() -> None:
16
- """Run once per worker process. Sets up Django."""
17
+ """Run once per worker process.
18
+
19
+ Ignores SIGINT so that Ctrl+C is handled exclusively by the parent
20
+ process, which shuts down the pool cleanly via atexit. This prevents
21
+ workers from being killed mid-operation and leaking semaphores.
22
+
23
+ Then sets up Django for task execution.
24
+ """
25
+ signal.signal(signal.SIGINT, signal.SIG_IGN)
26
+
17
27
  import django
18
28
 
19
29
  django.setup()
@@ -23,7 +33,7 @@ def _shutdown_pool() -> None:
23
33
  """Shut down the pool at interpreter exit to release semaphores."""
24
34
  global _pool
25
35
  if _pool is not None:
26
- _pool.shutdown(wait=False)
36
+ _pool.shutdown(wait=True, cancel_futures=True)
27
37
  _pool = None
28
38
 
29
39
 
@@ -7,7 +7,7 @@ packages = ["lambda_tasks"]
7
7
 
8
8
  [project]
9
9
  name = "django-lambda-tasks"
10
- version = "0.4.6"
10
+ version = "0.4.8"
11
11
  description = "Run async tasks in a lambda function"
12
12
  readme = "README.md"
13
13
  requires-python = ">=3.10"
@@ -126,12 +126,11 @@ def test_mutual_exclusion_of_eager_and_local_workers(n):
126
126
  def _reset_pool():
127
127
  """Reset the module-level _pool after each test to avoid cross-test contamination."""
128
128
  yield
129
- try:
130
- import lambda_tasks.local_executor
129
+ import lambda_tasks.local_executor
131
130
 
131
+ if lambda_tasks.local_executor._pool is not None:
132
+ lambda_tasks.local_executor._pool.shutdown(wait=True, cancel_futures=True)
132
133
  lambda_tasks.local_executor._pool = None
133
- except ModuleNotFoundError:
134
- pass
135
134
 
136
135
 
137
136
  class TestGetPool:
@@ -216,7 +215,11 @@ def test_pool_created_with_correct_worker_count(n):
216
215
  pool = lambda_tasks.local_executor.get_pool()
217
216
  assert pool._max_workers == n
218
217
  finally:
219
- # Always reset to avoid pool reuse across examples
218
+ # Shut down properly to avoid leaked semaphores
219
+ if lambda_tasks.local_executor._pool is not None:
220
+ lambda_tasks.local_executor._pool.shutdown(
221
+ wait=True, cancel_futures=True
222
+ )
220
223
  lambda_tasks.local_executor._pool = None
221
224
 
222
225
 
@@ -567,6 +570,21 @@ class TestPoolInitializer:
567
570
 
568
571
  mock_django_setup.assert_called_once()
569
572
 
573
+ def test_pool_initializer_ignores_sigint(self):
574
+ """_pool_initializer() sets SIGINT to SIG_IGN so workers don't receive Ctrl+C."""
575
+ import signal
576
+
577
+ from lambda_tasks.local_executor import _pool_initializer
578
+
579
+ original_handler = signal.getsignal(signal.SIGINT)
580
+ try:
581
+ with patch("django.setup"):
582
+ _pool_initializer()
583
+
584
+ assert signal.getsignal(signal.SIGINT) == signal.SIG_IGN
585
+ finally:
586
+ signal.signal(signal.SIGINT, original_handler)
587
+
570
588
 
571
589
  @pytest.mark.django_db(transaction=True)
572
590
  class TestTransactionCommitIntegration: