jararaca 0.4.0a5__py3-none-any.whl → 0.4.0a19__py3-none-any.whl

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 (35) hide show
  1. jararaca/__init__.py +9 -9
  2. jararaca/cli.py +643 -4
  3. jararaca/core/providers.py +4 -0
  4. jararaca/helpers/__init__.py +3 -0
  5. jararaca/helpers/global_scheduler/__init__.py +3 -0
  6. jararaca/helpers/global_scheduler/config.py +21 -0
  7. jararaca/helpers/global_scheduler/controller.py +42 -0
  8. jararaca/helpers/global_scheduler/registry.py +32 -0
  9. jararaca/messagebus/decorators.py +104 -10
  10. jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +50 -8
  11. jararaca/messagebus/interceptors/message_publisher_collector.py +62 -0
  12. jararaca/messagebus/interceptors/publisher_interceptor.py +25 -3
  13. jararaca/messagebus/worker.py +276 -200
  14. jararaca/microservice.py +3 -1
  15. jararaca/observability/providers/otel.py +31 -13
  16. jararaca/persistence/base.py +1 -1
  17. jararaca/persistence/utilities.py +47 -24
  18. jararaca/presentation/decorators.py +3 -3
  19. jararaca/reflect/decorators.py +24 -10
  20. jararaca/reflect/helpers.py +18 -0
  21. jararaca/rpc/http/__init__.py +2 -2
  22. jararaca/rpc/http/decorators.py +9 -9
  23. jararaca/scheduler/beat_worker.py +14 -14
  24. jararaca/tools/typescript/decorators.py +4 -4
  25. jararaca/tools/typescript/interface_parser.py +3 -1
  26. jararaca/utils/env_parse_utils.py +133 -0
  27. jararaca/utils/rabbitmq_utils.py +47 -0
  28. jararaca/utils/retry.py +11 -13
  29. {jararaca-0.4.0a5.dist-info → jararaca-0.4.0a19.dist-info}/METADATA +2 -1
  30. {jararaca-0.4.0a5.dist-info → jararaca-0.4.0a19.dist-info}/RECORD +35 -27
  31. pyproject.toml +2 -1
  32. {jararaca-0.4.0a5.dist-info → jararaca-0.4.0a19.dist-info}/LICENSE +0 -0
  33. {jararaca-0.4.0a5.dist-info → jararaca-0.4.0a19.dist-info}/LICENSES/GPL-3.0-or-later.txt +0 -0
  34. {jararaca-0.4.0a5.dist-info → jararaca-0.4.0a19.dist-info}/WHEEL +0 -0
  35. {jararaca-0.4.0a5.dist-info → jararaca-0.4.0a19.dist-info}/entry_points.txt +0 -0
@@ -0,0 +1,133 @@
1
+ # SPDX-FileCopyrightText: 2025 Lucas S
2
+ #
3
+ # SPDX-License-Identifier: GPL-3.0-or-later
4
+
5
+ import os
6
+ from typing import Literal, Optional, TypeVar, overload
7
+
8
+
9
+ def is_env_truffy(var_name: str) -> bool:
10
+ value = os.getenv(var_name, "").lower()
11
+ return value in ("1", "true", "yes", "on")
12
+
13
+
14
+ DF_BOOL_T = TypeVar("DF_BOOL_T", bound="bool")
15
+
16
+
17
+ @overload
18
+ def get_env_bool(
19
+ var_name: str, default: DF_BOOL_T
20
+ ) -> DF_BOOL_T | bool | Literal["invalid"]: ...
21
+
22
+
23
+ @overload
24
+ def get_env_bool(
25
+ var_name: str, default: None = None
26
+ ) -> bool | None | Literal["invalid"]: ...
27
+
28
+
29
+ def get_env_bool(
30
+ var_name: str, default: DF_BOOL_T | None = None
31
+ ) -> DF_BOOL_T | bool | Literal["invalid"] | None:
32
+ value = os.getenv(var_name)
33
+ if value is None:
34
+ return default
35
+ value_lower = value.lower()
36
+ if value_lower in ("1", "true", "yes", "on"):
37
+ return True
38
+ elif value_lower in ("0", "false", "no", "off"):
39
+ return False
40
+ else:
41
+ return "invalid"
42
+
43
+
44
+ DF_INT_T = TypeVar("DF_INT_T", bound="int | None | Literal[False]")
45
+
46
+
47
+ @overload
48
+ def get_env_int(var_name: str, default: None = None) -> int | None | Literal[False]: ...
49
+
50
+
51
+ @overload
52
+ def get_env_int(
53
+ var_name: str, default: DF_INT_T
54
+ ) -> DF_INT_T | int | Literal[False]: ...
55
+
56
+
57
+ def get_env_int(
58
+ var_name: str, default: DF_INT_T = False # type: ignore[assignment]
59
+ ) -> DF_INT_T | int | Literal[False]:
60
+ value = os.getenv(var_name)
61
+ if value is None:
62
+ return default
63
+ try:
64
+ return int(value)
65
+ except ValueError:
66
+ return False
67
+
68
+
69
+ DF_FLOAT_T = TypeVar("DF_FLOAT_T", bound="float | None | Literal[False]")
70
+
71
+
72
+ @overload
73
+ def get_env_float(
74
+ var_name: str, default: None = None
75
+ ) -> float | None | Literal[False]: ...
76
+
77
+
78
+ @overload
79
+ def get_env_float(
80
+ var_name: str, default: DF_FLOAT_T
81
+ ) -> DF_FLOAT_T | float | Literal[False]: ...
82
+
83
+
84
+ def get_env_float(
85
+ var_name: str, default: DF_FLOAT_T = False # type: ignore[assignment]
86
+ ) -> DF_FLOAT_T | float | Literal[False]:
87
+ value = os.getenv(var_name)
88
+ if value is None:
89
+ return default
90
+ try:
91
+ return float(value)
92
+ except ValueError:
93
+ return False
94
+
95
+
96
+ DF_STR_T = TypeVar("DF_STR_T", bound="Optional[str]")
97
+
98
+
99
+ @overload
100
+ def get_env_str(var_name: str, default: None = None) -> str | None: ...
101
+
102
+
103
+ @overload
104
+ def get_env_str(var_name: str, default: DF_STR_T) -> DF_STR_T | str: ...
105
+
106
+
107
+ def get_env_str(var_name: str, default: DF_STR_T = None) -> DF_STR_T | str: # type: ignore[assignment]
108
+ value = os.getenv(var_name)
109
+ if value is None:
110
+ return default
111
+ return value
112
+
113
+
114
+ def get_env_list(var_name: str, separator: str = ",") -> list[str]:
115
+ value = os.getenv(var_name, "")
116
+ if not value:
117
+ return []
118
+ return [item.strip() for item in value.split(separator) if item.strip()]
119
+
120
+
121
+ def get_env_dict(
122
+ var_name: str, item_separator: str = ",", key_value_separator: str = "="
123
+ ) -> dict[str, str]:
124
+ value = os.getenv(var_name, "")
125
+ result: dict[str, str] = {}
126
+ if not value:
127
+ return result
128
+ items = [item.strip() for item in value.split(item_separator) if item.strip()]
129
+ for item in items:
130
+ if key_value_separator in item:
131
+ key, val = item.split(key_value_separator, 1)
132
+ result[key.strip()] = val.strip()
133
+ return result
@@ -370,3 +370,50 @@ class RabbitmqUtils:
370
370
  )
371
371
  except AMQPError as e:
372
372
  logger.warning("AMQP error while deleting queue '%s': %s", queue_name, e)
373
+
374
+ @classmethod
375
+ async def get_dl_queue_message_count(cls, channel: AbstractChannel) -> int:
376
+ """
377
+ Get the message count in the Dead Letter Queue.
378
+ Returns 0 if the queue doesn't exist.
379
+ """
380
+ try:
381
+ await channel.get_queue(cls.DEAD_LETTER_QUEUE)
382
+ # The declaration property contains the message count
383
+ queue_info = await channel.declare_queue(
384
+ cls.DEAD_LETTER_QUEUE, passive=True
385
+ )
386
+ return queue_info.declaration_result.message_count or 0
387
+ except ChannelNotFoundEntity:
388
+ logger.debug("Dead Letter Queue does not exist.")
389
+ return 0
390
+ except ChannelClosed as e:
391
+ logger.error("Channel closed while getting DLQ message count: %s", e)
392
+ raise
393
+ except AMQPError as e:
394
+ logger.error("AMQP error while getting DLQ message count: %s", e)
395
+ raise
396
+
397
+ @classmethod
398
+ async def purge_dl_queue(cls, channel: AbstractChannel) -> int:
399
+ """
400
+ Purge all messages from the Dead Letter Queue.
401
+ Returns the number of messages purged.
402
+ """
403
+ try:
404
+ queue = await channel.get_queue(cls.DEAD_LETTER_QUEUE)
405
+ result = await queue.purge()
406
+ return result.message_count or 0
407
+ except ChannelNotFoundEntity as e:
408
+ logger.error(
409
+ "Dead Letter Queue '%s' does not exist. Error: %s",
410
+ cls.DEAD_LETTER_QUEUE,
411
+ e,
412
+ )
413
+ raise
414
+ except ChannelClosed as e:
415
+ logger.error("Channel closed while purging Dead Letter Queue: %s", e)
416
+ raise
417
+ except AMQPError as e:
418
+ logger.error("AMQP error while purging Dead Letter Queue: %s", e)
419
+ raise
jararaca/utils/retry.py CHANGED
@@ -14,7 +14,7 @@ P = ParamSpec("P")
14
14
  T = TypeVar("T")
15
15
 
16
16
 
17
- class RetryConfig:
17
+ class RetryPolicy:
18
18
  """Configuration for the retry mechanism."""
19
19
 
20
20
  def __init__(
@@ -49,7 +49,7 @@ async def retry_with_backoff(
49
49
  fn: Callable[[], Awaitable[T]],
50
50
  # args: P.args,
51
51
  # kwargs: P.kwargs,
52
- retry_config: Optional[RetryConfig] = None,
52
+ retry_policy: RetryPolicy,
53
53
  on_retry_callback: Optional[Callable[[int, E, float], None]] = None,
54
54
  retry_exceptions: tuple[type[E], ...] = (),
55
55
  ) -> T:
@@ -70,30 +70,28 @@ async def retry_with_backoff(
70
70
  Raises:
71
71
  The last exception encountered if all retries fail
72
72
  """
73
- if retry_config is None:
74
- retry_config = RetryConfig()
75
73
 
76
74
  last_exception = None
77
- delay = retry_config.initial_delay
75
+ delay = retry_policy.initial_delay
78
76
 
79
- for retry_count in range(retry_config.max_retries + 1):
77
+ for retry_count in range(retry_policy.max_retries + 1):
80
78
  try:
81
79
  return await fn()
82
80
  except retry_exceptions as e:
83
81
  last_exception = e
84
82
 
85
- if retry_count >= retry_config.max_retries:
83
+ if retry_count >= retry_policy.max_retries:
86
84
  logger.error(
87
- "Max retries (%s) exceeded: %s", retry_config.max_retries, e
85
+ "Max retries (%s) exceeded: %s", retry_policy.max_retries, e
88
86
  )
89
87
  raise
90
88
 
91
89
  # Calculate next delay with exponential backoff
92
90
  if retry_count > 0: # Don't increase delay on the first failure
93
- delay = min(delay * retry_config.backoff_factor, retry_config.max_delay)
91
+ delay = min(delay * retry_policy.backoff_factor, retry_policy.max_delay)
94
92
 
95
93
  # Apply jitter if configured (±25% randomness)
96
- if retry_config.jitter:
94
+ if retry_policy.jitter:
97
95
  jitter_amount = delay * 0.25
98
96
  delay = delay + random.uniform(-jitter_amount, jitter_amount)
99
97
  # Ensure delay doesn't go negative due to jitter
@@ -102,7 +100,7 @@ async def retry_with_backoff(
102
100
  logger.warning(
103
101
  "Retry %s/%s after error: %s. Retrying in %.2fs",
104
102
  retry_count + 1,
105
- retry_config.max_retries,
103
+ retry_policy.max_retries,
106
104
  e,
107
105
  delay,
108
106
  )
@@ -120,7 +118,7 @@ async def retry_with_backoff(
120
118
 
121
119
 
122
120
  def with_retry(
123
- retry_config: Optional[RetryConfig] = None,
121
+ retry_policy: RetryPolicy,
124
122
  retry_exceptions: tuple[type[Exception], ...] = (Exception,),
125
123
  ) -> Callable[[Callable[P, Awaitable[T]]], Callable[P, Awaitable[T]]]:
126
124
  """
@@ -139,7 +137,7 @@ def with_retry(
139
137
  async def wrapper(*args: P.args, **kwargs: P.kwargs) -> T:
140
138
  return await retry_with_backoff(
141
139
  lambda: fn(*args, **kwargs),
142
- retry_config=retry_config,
140
+ retry_policy=retry_policy,
143
141
  retry_exceptions=retry_exceptions,
144
142
  )
145
143
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jararaca
3
- Version: 0.4.0a5
3
+ Version: 0.4.0a19
4
4
  Summary: A simple and fast API framework for Python
5
5
  Home-page: https://github.com/LuscasLeo/jararaca
6
6
  License: GPL-3.0-or-later
@@ -27,6 +27,7 @@ Requires-Dist: opentelemetry-exporter-otlp-proto-http (>=1.27.0,<2.0.0) ; extra
27
27
  Requires-Dist: opentelemetry-sdk (>=1.38.0,<2.0.0) ; extra == "opentelemetry"
28
28
  Requires-Dist: redis (>=5.0.8,<6.0.0)
29
29
  Requires-Dist: sqlalchemy (>=2.0.34,<3.0.0)
30
+ Requires-Dist: tenacity (>=9.1.2,<10.0.0)
30
31
  Requires-Dist: types-croniter (>=3.0.3.20240731,<4.0.0.0)
31
32
  Requires-Dist: types-redis (>=4.6.0.20240903,<5.0.0.0)
32
33
  Requires-Dist: urllib3 (>=2.3.0,<3.0.0)
@@ -1,39 +1,45 @@
1
1
  LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
2
2
  README.md,sha256=YmCngjU8llW0l7L3tuXkkfr8qH7V9aBMgfp2jEzeiKg,3517
3
- pyproject.toml,sha256=6jMgRAWhjfhZ5goF4FKs_7m7HvWINhQcdlzRo4oVJo0,2886
4
- jararaca/__init__.py,sha256=tEXFfSdr_ahivoaiUDUlkxTnx1FfzQ5TJhxKWlpBy4A,25017
3
+ pyproject.toml,sha256=DLhkvvNfXjZ_DqJ4hts9V9pkbhITI4UxoPsnfTMl1rE,2907
4
+ jararaca/__init__.py,sha256=VjN2kPJanGCbFZjEohOJashOwrGjdI_fiF0g7VUeFoI,25114
5
5
  jararaca/__main__.py,sha256=Yw9bIf6ycd3_9klbFS9Lpmt9Z5xmtRb2ap75qIlj9j0,153
6
6
  jararaca/broker_backend/__init__.py,sha256=Rqw24Q8jlXc3MDs9hrG6FFJ-9jWFz2Zx_X79JiGxiV8,3614
7
7
  jararaca/broker_backend/mapper.py,sha256=O0PZsJ4fTBRnuyrZzZLDLdTz5QDs8exuZEnG8zxsEkg,782
8
8
  jararaca/broker_backend/redis_broker_backend.py,sha256=zUS9EZ7Pbb7mtlZ9EfDFZYLlTApPxeu1pIgSjhCNhI4,5965
9
- jararaca/cli.py,sha256=DVmLn5avVrGQvLbRvnL8V1MNwanGK7KVmm_wbAPI__s,33015
9
+ jararaca/cli.py,sha256=hJVgxLcBwu5x7o-uulWmUOFp45l63j46bB6oKAJLU_g,54419
10
10
  jararaca/common/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
11
11
  jararaca/core/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
12
- jararaca/core/providers.py,sha256=WNxJnFxrTcSXT-r6T7i43dGfM7Six69H6bat8xc3r6g,520
12
+ jararaca/core/providers.py,sha256=wbBBIt7UswQa2vNO6xXpYrioiFAlPUVtgq8yDv_k_hM,643
13
13
  jararaca/core/uow.py,sha256=A2S1C5P6GsbWF491wMcw7vuAyjLh4mXkGPDRCDOyEAM,3677
14
14
  jararaca/di.py,sha256=5fOBVoOQhd82k-h1oUQ0uuWYJk7R514ET2jHwXoDZPU,162
15
15
  jararaca/files/entity.py.mako,sha256=zdNtKd10vEoLCOv8zHc5ohbnmHOHYTqxagbZ7lZmgLs,3184
16
+ jararaca/helpers/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
17
+ jararaca/helpers/global_scheduler/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
18
+ jararaca/helpers/global_scheduler/config.py,sha256=0_3XIEyxtJ3CgS-fDThB7mLPb3ZkhCI0SGljHwQRPgI,464
19
+ jararaca/helpers/global_scheduler/controller.py,sha256=9cgVxsne9dL5OwWmP6rB62Md8xCf-YnLqWJwBZMK0gA,1309
20
+ jararaca/helpers/global_scheduler/registry.py,sha256=Mq0adcTZxic8sKiPWAwdgJP5tQeDCJjwegAN4Q2jZlo,831
16
21
  jararaca/lifecycle.py,sha256=BhME1-TIAhcXzHGvid-1j0BTWTrB280m_-wsNagmUmY,1983
17
22
  jararaca/messagebus/__init__.py,sha256=dnGdPHg30aqySAaAJPZBXzpzCKb3qvO3yXp3UpqHJqs,142
18
23
  jararaca/messagebus/bus_message_controller.py,sha256=PHQxEK781KjCpNsjHQYS3gxSdeS-XFrq8LnTIIudbz8,1573
19
24
  jararaca/messagebus/consumers/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
20
- jararaca/messagebus/decorators.py,sha256=tJp6NEuE-HDRcNAe57R1yunpPbup7BFkinvo0CbttXk,4712
25
+ jararaca/messagebus/decorators.py,sha256=vkqNJ6LC7B7dxhX0PXrpqQe8ExtgOnQ5ynAgf3q6X6A,8147
21
26
  jararaca/messagebus/implicit_headers.py,sha256=ftuQ8YAw2H_jTeuvfEYHMNGQ_3d16jWlTvqwH1bnR34,1051
22
27
  jararaca/messagebus/interceptors/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
23
- jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py,sha256=qLxs95xXGAuHGkcdIhd4NOTQmJgd_SA6YOVcUGGF_rY,6776
24
- jararaca/messagebus/interceptors/publisher_interceptor.py,sha256=xhcEkKDvU521JJ361q8bFvy2LCUpDK7Pkh41kgY1gBY,1411
28
+ jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py,sha256=2heqAh698-AxuOXgt15x2rIsxWu6_Jljg4K9ohPqwYg,8304
29
+ jararaca/messagebus/interceptors/message_publisher_collector.py,sha256=xO5h_GaVFQdvG2KuHzwu7_4A8JmMNkBDipx73mLkbmg,1936
30
+ jararaca/messagebus/interceptors/publisher_interceptor.py,sha256=TmJflhIqn8Yq9SbxuYny0p0HAj8g3J9IJOo-AxV9fJc,2191
25
31
  jararaca/messagebus/message.py,sha256=St6Xp7HB4gjPlV-5UkZeTEETCMBJTPxXGS6PgeQNEX8,905
26
32
  jararaca/messagebus/publisher.py,sha256=nvhC5IzggOkd78wj4H5yxvu7BzPJoWZxz12YF8S9a1o,2314
27
- jararaca/messagebus/worker.py,sha256=ctZa0fOpz64r-G45J63DKcfmj8oS0SLnMWKfKxLJah8,72965
28
- jararaca/microservice.py,sha256=pLkelTJuSVGe0MAuc70ZuHiD77U7R56dCmd04u_39Oo,12499
33
+ jararaca/messagebus/worker.py,sha256=0rsYYfyTSvPslffjfwtYO_E_t0psEKIeJw_-WRjx8z8,77157
34
+ jararaca/microservice.py,sha256=S_hLyRlOGqmmrbQXnUUKXV_Uo8APJaKS25oRDhFk9zQ,12597
29
35
  jararaca/observability/constants.py,sha256=fbmF5xIuc82MSKYwvJH0x4CPRr4ggAuQzPhEBS6NArE,149
30
36
  jararaca/observability/decorators.py,sha256=JezNh8GpJjdxU9MLnY9A9Fb0329Cw2uR0WGw2pGHBlQ,6626
31
37
  jararaca/observability/fastapi_exception_handler.py,sha256=g_3oiUBs0JILv4ysGtefhI0chW1DRCVSulDgFDWvYYY,1350
32
38
  jararaca/observability/hooks.py,sha256=VSSVx7rUwe1Z0MKlvgQRN1_uyfQd9N1kC9RXHmvekGA,2775
33
39
  jararaca/observability/interceptor.py,sha256=Hj4d8vti-rTGF0qbHzcHBRU2fL2YGEHe_2V13Vk6md0,1584
34
40
  jararaca/observability/providers/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
35
- jararaca/observability/providers/otel.py,sha256=BNhu6ChiOgkMkVCpqD-QFYctdnk-bE15ifj-ny3gHUY,13500
36
- jararaca/persistence/base.py,sha256=WzhkTnsQyF3mSh2MueTyulZpj9udO2d4VBOH9sJDIWQ,2172
41
+ jararaca/observability/providers/otel.py,sha256=G_DPJ7EqMgSywX9itx6yl5DIQ8cn2hvGU25Izzj1ZzA,14096
42
+ jararaca/persistence/base.py,sha256=m0ATYeVSeFA_tvpOrxTCzLIBCLqJOXx-jjGKWqMjgRE,2170
37
43
  jararaca/persistence/exports.py,sha256=OCA8YIZLMM5Fv53ugn49_A5BOJ3s4g7y6bM3_ssSRuw,148
38
44
  jararaca/persistence/interceptors/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
39
45
  jararaca/persistence/interceptors/aiosqa_interceptor.py,sha256=oRbO3-XdAr_Ut3RGTFp4z-sLog5ZbjcwTHXj16NU2KA,7008
@@ -41,9 +47,9 @@ jararaca/persistence/interceptors/constants.py,sha256=1KWx3vHqClMCxS3gSHevfniKz6
41
47
  jararaca/persistence/interceptors/decorators.py,sha256=M-8ZoBF6fSoAqHAx0ebhm8GElKN1xMSNmMCd8q9VPGY,1714
42
48
  jararaca/persistence/session.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
43
49
  jararaca/persistence/sort_filter.py,sha256=Mx6HpUKqfIzSw2rrOPB92eOoaQykkm5ebRoZqzYd7Dk,9312
44
- jararaca/persistence/utilities.py,sha256=i1FJoF0joXtWyviv7unCKhc8tl9XpGisTOjSNzSBRBc,15434
50
+ jararaca/persistence/utilities.py,sha256=18Y8VcDqQTQNl3K2NeKxUf5lY1m5Km16C9afllpQxr4,16610
45
51
  jararaca/presentation/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
46
- jararaca/presentation/decorators.py,sha256=uKybidYGPhPV0pqHDOuXgr-oX5mxKKi9w6GqaIs7C8g,11849
52
+ jararaca/presentation/decorators.py,sha256=FqEwD0Bj1XLL1dq7WRTOy5qQhVH0yMUKZF8w72CQTPs,11858
47
53
  jararaca/presentation/exceptions.py,sha256=RgQ6vzLO76BYrYnQaB81oohxaHSXFVp96lBY1Z28-dQ,659
48
54
  jararaca/presentation/hooks.py,sha256=27dyclONRTBthzsNKLp2rOyPPpgeIGL0wo8Y4tZUX-I,2066
49
55
  jararaca/presentation/http_microservice.py,sha256=1Jy_CRR0FYcH2EUuf0orP5ishKaMyDaKBA92wc8xdKE,619
@@ -58,31 +64,33 @@ jararaca/presentation/websocket/websocket_interceptor.py,sha256=fJeX1_OcHXyc3cui
58
64
  jararaca/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
59
65
  jararaca/reflect/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
60
66
  jararaca/reflect/controller_inspect.py,sha256=qNR6UmXO49X11nIY7f4jxAlhD2wnAl2tD2UE0YgBNHE,2447
61
- jararaca/reflect/decorators.py,sha256=nYKLVj8P3yR0PBzJu5jB0LBCvTf_-S4pO742aJdjE44,7787
67
+ jararaca/reflect/decorators.py,sha256=6YbD9d9Jm22viFJ0OUbk-liYRDPvOggI0iwOEEHAVws,8216
68
+ jararaca/reflect/helpers.py,sha256=fFPXuS3RDbkW6x3O0Jp48NQXddNbFL_PTSXbDOr8TII,416
62
69
  jararaca/reflect/metadata.py,sha256=vbn0WqJwHNSk_pEl8tGhXzjlEknGxeLygT_pevJgoXo,1956
63
70
  jararaca/rpc/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
64
- jararaca/rpc/http/__init__.py,sha256=Coc46WVOOa-rSXncW1DyA5T6U-x5NGHvZfIEeIqNiWI,2482
71
+ jararaca/rpc/http/__init__.py,sha256=YcTekAJtkyA5noQFP0DY1sQSUNdB6srn4mv9sVXV8L8,2488
65
72
  jararaca/rpc/http/backends/__init__.py,sha256=BiYOGf-KI7IlAqBaHBNJ5-C09T4LtiNt6XPHUfVzJhs,252
66
73
  jararaca/rpc/http/backends/httpx.py,sha256=vJCz28tJl7veJbJdc_no36ahi8IszsoCt1QTtip6Pzc,2332
67
74
  jararaca/rpc/http/backends/otel.py,sha256=2LPy8yWDFKekqdb4bQvYawtHMrSUft3P9kihM26vcI8,893
68
- jararaca/rpc/http/decorators.py,sha256=T1IHtbtWa0t4SVGbiiy6P7NVRa_Pt_dm7BTYNj-NqJQ,21515
75
+ jararaca/rpc/http/decorators.py,sha256=kziO7rQnztTEDeS_q7QGZG4Qv7oAyGcLXe4Krl-DwUM,21488
69
76
  jararaca/rpc/http/httpx.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
70
77
  jararaca/scheduler/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
71
- jararaca/scheduler/beat_worker.py,sha256=xycay6ev7wE4_6BpFO7eg9jITL2OtV1H8pVcSDfl80E,27630
78
+ jararaca/scheduler/beat_worker.py,sha256=fxFYDxsWOrMp14vXukDU9i28hxSsBPWW3R0iMoyelJw,27655
72
79
  jararaca/scheduler/decorators.py,sha256=QOetUo_gsirsWIqZ59pTSKfGvm_NLlamEID4w_LiMQo,4234
73
80
  jararaca/scheduler/types.py,sha256=MN6J87UpCO83oM0c2A0GHM_0YlZEaQhL7HUVvPo_PS4,221
74
81
  jararaca/tools/app_config/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
75
82
  jararaca/tools/app_config/decorators.py,sha256=46eWeAkuIc8KUkfDzLlfIm6jH6vNizNaLWhOHg7xszE,484
76
83
  jararaca/tools/app_config/interceptor.py,sha256=hdrvmQqczi7BLeUX35m-XW93WqsgZYvJ7VGh4tL0AoU,2703
77
84
  jararaca/tools/typescript/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
78
- jararaca/tools/typescript/decorators.py,sha256=Q6LxqqZXwtraXrneU1Fz5JRQtXt-E4Unj2c_0OamdNc,3578
79
- jararaca/tools/typescript/interface_parser.py,sha256=X8WYDJAiCNrwCIqxAnVik20a4j876496NwORgmSdZck,69391
85
+ jararaca/tools/typescript/decorators.py,sha256=2HUX1Uc-0sKJLdelIfS8tVwmIbEu3q-3oiypnIveNfk,3598
86
+ jararaca/tools/typescript/interface_parser.py,sha256=HQ1lLBzlbHzPKo47yzvIhjD2G0qGbDnld7aBD4BSZK0,69453
80
87
  jararaca/utils/__init__.py,sha256=fyZParLDQhdP0oBKsAvkffaWxig5YeBnfyoOPuzwbfc,85
81
- jararaca/utils/rabbitmq_utils.py,sha256=_jQBO-V3sV6LKqc6qQCxn00FlY6MYe63jeqjyVXd4no,11412
82
- jararaca/utils/retry.py,sha256=_5t6qNWaOphwxNqdDgWrQP1z0bPwpbRH89zdqKmsvAQ,4799
83
- jararaca-0.4.0a5.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
84
- jararaca-0.4.0a5.dist-info/LICENSES/GPL-3.0-or-later.txt,sha256=-5gWaMGKJ54oX8TYP7oeg2zITdTapzyWl9PP0tispuA,34674
85
- jararaca-0.4.0a5.dist-info/METADATA,sha256=blj4DWmRegNjtaqD07eXFWB2XjU8HJG-BU1P0S7RxsA,5263
86
- jararaca-0.4.0a5.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
87
- jararaca-0.4.0a5.dist-info/entry_points.txt,sha256=WIh3aIvz8LwUJZIDfs4EeH3VoFyCGEk7cWJurW38q0I,45
88
- jararaca-0.4.0a5.dist-info/RECORD,,
88
+ jararaca/utils/env_parse_utils.py,sha256=NPZKPhOdj1fAes1vBAZO23FtAByiIztIYtdBooS39TI,3278
89
+ jararaca/utils/rabbitmq_utils.py,sha256=y0NxsLRgciiKuFabna9c2MdoXXwNy5fJYt-vigL27LE,13212
90
+ jararaca/utils/retry.py,sha256=K64lEtDJC3iF6NTWkZgshojL8TywMCiXEsurtkYRgIA,4699
91
+ jararaca-0.4.0a19.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
92
+ jararaca-0.4.0a19.dist-info/LICENSES/GPL-3.0-or-later.txt,sha256=-5gWaMGKJ54oX8TYP7oeg2zITdTapzyWl9PP0tispuA,34674
93
+ jararaca-0.4.0a19.dist-info/METADATA,sha256=hczF9xaktyBi_I9UmCQSR2bUUPFJ13Sw_gNYcKaqdpc,5306
94
+ jararaca-0.4.0a19.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
95
+ jararaca-0.4.0a19.dist-info/entry_points.txt,sha256=WIh3aIvz8LwUJZIDfs4EeH3VoFyCGEk7cWJurW38q0I,45
96
+ jararaca-0.4.0a19.dist-info/RECORD,,
pyproject.toml CHANGED
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "jararaca"
3
- version = "0.4.0a5"
3
+ version = "0.4.0a19"
4
4
  description = "A simple and fast API framework for Python"
5
5
  authors = ["Lucas S <me@luscasleo.dev>"]
6
6
  readme = "README.md"
@@ -34,6 +34,7 @@ mako = "^1.3.5"
34
34
  watchdog = { version = "^3.0.0", optional = true }
35
35
  frozendict = "^2.4.6"
36
36
  urllib3 = "^2.3.0"
37
+ tenacity = "^9.1.2"
37
38
 
38
39
 
39
40
  [tool.poetry.extras]