jararaca 0.3.12a5__tar.gz → 0.3.12a7__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.

Potentially problematic release.


This version of jararaca might be problematic. Click here for more details.

Files changed (88) hide show
  1. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/PKG-INFO +1 -1
  2. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/pyproject.toml +1 -1
  3. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/__init__.py +5 -0
  4. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/cli.py +2 -0
  5. jararaca-0.3.12a7/src/jararaca/tools/typescript/decorators.py +62 -0
  6. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/tools/typescript/interface_parser.py +68 -7
  7. jararaca-0.3.12a7/src/jararaca/utils/__init__.py +0 -0
  8. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/LICENSE +0 -0
  9. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/README.md +0 -0
  10. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/CNAME +0 -0
  11. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/architecture.md +0 -0
  12. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
  13. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
  14. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/assets/tracing_example.png +0 -0
  15. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/http-rpc.md +0 -0
  16. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/index.md +0 -0
  17. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/interceptors.md +0 -0
  18. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/messagebus.md +0 -0
  19. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/retry.md +0 -0
  20. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/scheduler.md +0 -0
  21. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/stylesheets/custom.css +0 -0
  22. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/docs/websocket.md +0 -0
  23. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/__main__.py +0 -0
  24. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/broker_backend/__init__.py +0 -0
  25. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/broker_backend/mapper.py +0 -0
  26. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
  27. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/common/__init__.py +0 -0
  28. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/core/__init__.py +0 -0
  29. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/core/providers.py +0 -0
  30. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/core/uow.py +0 -0
  31. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/di.py +0 -0
  32. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/files/entity.py.mako +0 -0
  33. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/lifecycle.py +0 -0
  34. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/__init__.py +0 -0
  35. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/bus_message_controller.py +0 -0
  36. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/consumers/__init__.py +0 -0
  37. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/decorators.py +0 -0
  38. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
  39. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +0 -0
  40. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
  41. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/message.py +0 -0
  42. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/publisher.py +0 -0
  43. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/messagebus/worker.py +0 -0
  44. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/microservice.py +0 -0
  45. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/observability/decorators.py +0 -0
  46. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/observability/interceptor.py +0 -0
  47. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/observability/providers/__init__.py +0 -0
  48. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/observability/providers/otel.py +0 -0
  49. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/persistence/base.py +0 -0
  50. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/persistence/exports.py +0 -0
  51. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/persistence/interceptors/__init__.py +0 -0
  52. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
  53. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/persistence/session.py +0 -0
  54. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/persistence/sort_filter.py +0 -0
  55. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/persistence/utilities.py +0 -0
  56. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/__init__.py +0 -0
  57. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/decorators.py +0 -0
  58. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/hooks.py +0 -0
  59. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/http_microservice.py +0 -0
  60. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/server.py +0 -0
  61. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/websocket/__init__.py +0 -0
  62. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/websocket/base_types.py +0 -0
  63. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/websocket/context.py +0 -0
  64. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/websocket/decorators.py +0 -0
  65. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/websocket/redis.py +0 -0
  66. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/websocket/types.py +0 -0
  67. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
  68. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/py.typed +0 -0
  69. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/reflect/__init__.py +0 -0
  70. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/reflect/controller_inspect.py +0 -0
  71. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/reflect/metadata.py +0 -0
  72. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/rpc/__init__.py +0 -0
  73. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/rpc/http/__init__.py +0 -0
  74. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/rpc/http/backends/__init__.py +0 -0
  75. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/rpc/http/backends/httpx.py +0 -0
  76. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/rpc/http/backends/otel.py +0 -0
  77. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/rpc/http/decorators.py +0 -0
  78. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/rpc/http/httpx.py +0 -0
  79. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/scheduler/__init__.py +0 -0
  80. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/scheduler/beat_worker.py +0 -0
  81. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/scheduler/decorators.py +0 -0
  82. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/scheduler/types.py +0 -0
  83. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/tools/app_config/__init__.py +0 -0
  84. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/tools/app_config/decorators.py +0 -0
  85. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/tools/app_config/interceptor.py +0 -0
  86. {jararaca-0.3.12a5/src/jararaca/utils → jararaca-0.3.12a7/src/jararaca/tools/typescript}/__init__.py +0 -0
  87. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/utils/rabbitmq_utils.py +0 -0
  88. {jararaca-0.3.12a5 → jararaca-0.3.12a7}/src/jararaca/utils/retry.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: jararaca
3
- Version: 0.3.12a5
3
+ Version: 0.3.12a7
4
4
  Summary: A simple and fast API framework for Python
5
5
  Home-page: https://github.com/LuscasLeo/jararaca
6
6
  Author: Lucas S
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "jararaca"
3
- version = "0.3.12a5"
3
+ version = "0.3.12a7"
4
4
  description = "A simple and fast API framework for Python"
5
5
  authors = ["Lucas S <me@luscasleo.dev>"]
6
6
  readme = "README.md"
@@ -160,6 +160,7 @@ if TYPE_CHECKING:
160
160
  from .presentation.websocket.websocket_interceptor import WebSocketInterceptor
161
161
  from .scheduler.decorators import ScheduledAction
162
162
  from .tools.app_config.interceptor import AppConfigurationInterceptor
163
+ from .tools.typescript.decorators import MutationEndpoint, QueryEndpoint
163
164
 
164
165
  __all__ = [
165
166
  "SetMetadata",
@@ -261,6 +262,8 @@ if TYPE_CHECKING:
261
262
  "MessageBusPublisherInterceptor",
262
263
  "RedisWebSocketConnectionBackend",
263
264
  "AppConfigurationInterceptor",
265
+ "QueryEndpoint",
266
+ "MutationEndpoint",
264
267
  "UseMiddleware",
265
268
  "UseDependency",
266
269
  "GlobalHttpErrorHandler",
@@ -473,6 +476,8 @@ _dynamic_imports: "dict[str, tuple[str, str, str | None]]" = {
473
476
  "tools.app_config.interceptor",
474
477
  None,
475
478
  ),
479
+ "QueryEndpoint": (__SPEC_PARENT__, "tools.typescript.decorators", None),
480
+ "MutationEndpoint": (__SPEC_PARENT__, "tools.typescript.decorators", None),
476
481
  "UseMiddleware": (__SPEC_PARENT__, "presentation.decorators", None),
477
482
  "UseDependency": (__SPEC_PARENT__, "presentation.decorators", None),
478
483
  "GlobalHttpErrorHandler": (__SPEC_PARENT__, "rpc.http.decorators", None),
@@ -5,6 +5,7 @@ import multiprocessing
5
5
  import os
6
6
  import sys
7
7
  import time
8
+ import traceback
8
9
  from codecs import StreamWriter
9
10
  from pathlib import Path
10
11
  from typing import Any, Callable
@@ -615,6 +616,7 @@ def generate_interfaces(
615
616
  return content
616
617
  except Exception as e:
617
618
  click.echo(f"Error generating TypeScript interfaces: {e}", file=sys.stderr)
619
+ traceback.print_exc(file=sys.stderr)
618
620
  return ""
619
621
 
620
622
 
@@ -0,0 +1,62 @@
1
+ from typing import Any, Callable, TypeVar, cast
2
+
3
+ DECORATED_FUNC = TypeVar("DECORATED_FUNC", bound=Callable[..., Any])
4
+
5
+
6
+ class QueryEndpoint:
7
+ """
8
+ Decorator to mark a endpoint function as a query endpoint for Typescript generation.
9
+ """
10
+
11
+ METADATA_KEY = "__jararaca_query_endpoint__"
12
+
13
+ def __init__(self, has_infinite_query: bool = False) -> None:
14
+ """
15
+ Initialize the QueryEndpoint decorator.
16
+
17
+ Args:
18
+ has_infinite_query: Whether the query endpoint supports infinite queries.
19
+ Important:
20
+ - Make sure a PaginatedQuery child instance is on the first argument
21
+ - Make sure the endpoint is a Patch (recommended) or Put method
22
+ - Make sure the endpoint returns a Paginated[T]
23
+ """
24
+ self.has_infinite_query = has_infinite_query
25
+
26
+ def __call__(self, func: DECORATED_FUNC) -> DECORATED_FUNC:
27
+ """
28
+ Decorate the function to mark it as a query endpoint.
29
+ """
30
+ setattr(func, self.METADATA_KEY, self)
31
+ return func
32
+
33
+ @staticmethod
34
+ def extract_query_endpoint(func: Any) -> "QueryEndpoint":
35
+ """
36
+ Check if the function is marked as a query endpoint.
37
+ """
38
+ return cast(QueryEndpoint, getattr(func, QueryEndpoint.METADATA_KEY, None))
39
+
40
+
41
+ class MutationEndpoint:
42
+ """
43
+ Decorator to mark a endpoint function as a mutation endpoint for Typescript generation.
44
+ """
45
+
46
+ METADATA_KEY = "__jararaca_mutation_endpoint__"
47
+
48
+ def __init__(self) -> None: ...
49
+
50
+ def __call__(self, func: DECORATED_FUNC) -> DECORATED_FUNC:
51
+ """
52
+ Decorate the function to mark it as a mutation endpoint.
53
+ """
54
+ setattr(func, self.METADATA_KEY, True)
55
+ return func
56
+
57
+ @staticmethod
58
+ def is_mutation(func: Any) -> bool:
59
+ """
60
+ Check if the function is marked as a mutation endpoint.
61
+ """
62
+ return getattr(func, MutationEndpoint.METADATA_KEY, False)
@@ -8,7 +8,7 @@ from datetime import date, datetime, time
8
8
  from decimal import Decimal
9
9
  from enum import Enum
10
10
  from io import StringIO
11
- from types import NoneType, UnionType
11
+ from types import FunctionType, NoneType, UnionType
12
12
  from typing import (
13
13
  IO,
14
14
  Annotated,
@@ -35,6 +35,7 @@ from jararaca.presentation.websocket.decorators import RegisterWebSocketMessage
35
35
  from jararaca.presentation.websocket.websocket_interceptor import (
36
36
  WebSocketMessageWrapper,
37
37
  )
38
+ from jararaca.tools.typescript.decorators import MutationEndpoint, QueryEndpoint
38
39
 
39
40
  CONSTANT_PATTERN = re.compile(r"^[A-Z_]+$")
40
41
 
@@ -67,6 +68,13 @@ def snake_to_camel(snake_str: str) -> str:
67
68
  return components[0] + "".join(x.title() for x in components[1:])
68
69
 
69
70
 
71
+ def pascal_to_camel(pascal_str: str) -> str:
72
+ """Convert a PascalCase string to camelCase."""
73
+ if not pascal_str:
74
+ return pascal_str
75
+ return pascal_str[0].lower() + pascal_str[1:]
76
+
77
+
70
78
  def parse_literal_value(value: Any) -> str:
71
79
  if value is None:
72
80
  return "null"
@@ -354,12 +362,17 @@ def write_microservice_to_typescript_interface(
354
362
  if rest_controller is None:
355
363
  continue
356
364
 
357
- controller_class_str, types = write_rest_controller_to_typescript_interface(
358
- rest_controller, controller
365
+ controller_class_strio, types, hooks_strio = (
366
+ write_rest_controller_to_typescript_interface(
367
+ rest_controller,
368
+ controller,
369
+ )
359
370
  )
360
371
 
361
372
  mapped_types_set.update(types)
362
- rest_controller_buffer.write(controller_class_str)
373
+ rest_controller_buffer.write(controller_class_strio.getvalue())
374
+ if hooks_strio is not None:
375
+ rest_controller_buffer.write(hooks_strio.getvalue())
363
376
 
364
377
  registered = RegisterWebSocketMessage.get(controller)
365
378
 
@@ -376,6 +389,7 @@ def write_microservice_to_typescript_interface(
376
389
 
377
390
  final_buffer.write(
378
391
  """
392
+ import { createClassQueryHooks , createClassMutationHooks, createClassInfiniteQueryHooks, paginationModelByFirstArgPaginationFilter } from "@jararaca/core";
379
393
  export type WebSocketMessageMap = {
380
394
  %s
381
395
  }
@@ -494,11 +508,16 @@ def is_primitive(field_type: Any) -> bool:
494
508
 
495
509
  def write_rest_controller_to_typescript_interface(
496
510
  rest_controller: RestController, controller: type
497
- ) -> tuple[str, set[Any]]:
511
+ ) -> tuple[StringIO, set[Any], StringIO | None]:
512
+
513
+ class_name = controller.__name__
514
+
515
+ decorated_queries: list[tuple[str, FunctionType, QueryEndpoint]] = []
516
+ decorated_mutations: list[tuple[str, FunctionType]] = []
498
517
 
499
518
  class_buffer = StringIO()
500
519
 
501
- class_buffer.write(f"export class {controller.__name__} extends HttpService {{\n")
520
+ class_buffer.write(f"export class {class_name} extends HttpService {{\n")
502
521
 
503
522
  mapped_types: set[Any] = set()
504
523
 
@@ -514,6 +533,11 @@ def write_rest_controller_to_typescript_interface(
514
533
  if return_type is None:
515
534
  return_type = NoneType
516
535
 
536
+ if query_endpoint := QueryEndpoint.extract_query_endpoint(member):
537
+ decorated_queries.append((name, member, query_endpoint))
538
+ if MutationEndpoint.is_mutation(member):
539
+ decorated_mutations.append((name, member))
540
+
517
541
  mapped_types.update(extract_all_envolved_types(return_type))
518
542
 
519
543
  return_value_repr = get_field_type_for_ts(return_type)
@@ -588,7 +612,44 @@ def write_rest_controller_to_typescript_interface(
588
612
 
589
613
  class_buffer.write("}\n")
590
614
 
591
- return class_buffer.getvalue(), mapped_types
615
+ controller_hooks_builder: StringIO | None = None
616
+
617
+ if decorated_queries or decorated_mutations:
618
+ controller_hooks_builder = StringIO()
619
+ controller_hooks_builder.write(
620
+ f"export const {pascal_to_camel(class_name)} = {{\n"
621
+ )
622
+
623
+ if decorated_queries:
624
+ controller_hooks_builder.write(
625
+ f"\t...createClassQueryHooks({class_name},\n"
626
+ )
627
+ for name, member, _ in decorated_queries:
628
+ controller_hooks_builder.write(f'\t\t"{snake_to_camel(name)}",\n')
629
+ controller_hooks_builder.write("\t),\n")
630
+
631
+ if decorated_queries and any(
632
+ query.has_infinite_query for _, _, query in decorated_queries
633
+ ):
634
+ controller_hooks_builder.write(
635
+ f"\t...createClassInfiniteQueryHooks({class_name}, {{\n"
636
+ )
637
+ for name, member, query in decorated_queries:
638
+ if query.has_infinite_query:
639
+ controller_hooks_builder.write(
640
+ f'\t\t"{snake_to_camel(name)}": paginationModelByFirstArgPaginationFilter(),\n'
641
+ )
642
+ controller_hooks_builder.write("\t}),\n")
643
+ if decorated_mutations:
644
+ controller_hooks_builder.write(
645
+ f"\t...createClassMutationHooks({class_name},\n"
646
+ )
647
+ for name, member in decorated_mutations:
648
+ controller_hooks_builder.write(f'\t\t"{snake_to_camel(name)}",\n')
649
+ controller_hooks_builder.write("\t),\n")
650
+ controller_hooks_builder.write("};\n")
651
+
652
+ return class_buffer, mapped_types, controller_hooks_builder
592
653
 
593
654
 
594
655
  EXCLUDED_REQUESTS_TYPES = [Request, Response]
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes