jararaca 0.3.0__tar.gz → 0.3.2__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.
- {jararaca-0.3.0 → jararaca-0.3.2}/PKG-INFO +1 -1
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/scheduler.md +10 -7
- {jararaca-0.3.0 → jararaca-0.3.2}/pyproject.toml +1 -1
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/cli.py +56 -25
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/interceptors/aiopika_publisher_interceptor.py +5 -4
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/tools/typescript/interface_parser.py +66 -40
- {jararaca-0.3.0 → jararaca-0.3.2}/LICENSE +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/README.md +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/CNAME +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/architecture.md +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.jpeg +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/assets/_f04774c9-7e05-4da4-8b17-8be23f6a1475.webp +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/assets/tracing_example.png +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/index.md +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/messagebus.md +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/stylesheets/custom.css +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/docs/websocket.md +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/__main__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/broker_backend/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/broker_backend/mapper.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/broker_backend/redis_broker_backend.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/common/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/core/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/core/providers.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/core/uow.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/di.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/files/entity.py.mako +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/lifecycle.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/bus_message_controller.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/consumers/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/decorators.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/interceptors/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/interceptors/publisher_interceptor.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/message.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/publisher.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/worker.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/worker_v2.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/microservice.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/observability/decorators.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/observability/interceptor.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/observability/providers/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/observability/providers/otel.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/base.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/exports.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/interceptors/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/session.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/sort_filter.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/utilities.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/decorators.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/hooks.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/http_microservice.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/server.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/base_types.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/context.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/decorators.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/redis.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/types.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/websocket_interceptor.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/py.typed +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/rpc/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/rpc/http/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/rpc/http/backends/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/rpc/http/backends/httpx.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/rpc/http/backends/otel.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/rpc/http/decorators.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/rpc/http/httpx.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/scheduler/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/scheduler/decorators.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/scheduler/scheduler.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/scheduler/scheduler_v2.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/scheduler/types.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/tools/app_config/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/tools/app_config/decorators.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/tools/app_config/interceptor.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/tools/metadata.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/utils/__init__.py +0 -0
- {jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/utils/rabbitmq_utils.py +0 -0
|
@@ -21,7 +21,7 @@ graph TD
|
|
|
21
21
|
A[Microservice] --> B[Scheduler System]
|
|
22
22
|
B --> C[Basic Scheduler]
|
|
23
23
|
B --> D[Enhanced Scheduler V2]
|
|
24
|
-
|
|
24
|
+
|
|
25
25
|
C --> E[Local Task Execution]
|
|
26
26
|
D --> F[Message Broker]
|
|
27
27
|
F --> G[Workers]
|
|
@@ -39,12 +39,13 @@ You can define scheduled tasks using the `@ScheduledAction` decorator:
|
|
|
39
39
|
```python
|
|
40
40
|
from jararaca import ScheduledAction
|
|
41
41
|
|
|
42
|
+
|
|
42
43
|
class TasksController:
|
|
43
44
|
@ScheduledAction("*/5 * * * *") # Run every 5 minutes
|
|
44
45
|
async def scheduled_task(self):
|
|
45
46
|
# Your task implementation
|
|
46
47
|
print("This runs every 5 minutes")
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
@ScheduledAction("0 */2 * * *", allow_overlap=False, timeout=60)
|
|
49
50
|
async def heavy_task(self):
|
|
50
51
|
# A heavier task that shouldn't overlap
|
|
@@ -85,6 +86,7 @@ app = Microservice(
|
|
|
85
86
|
|
|
86
87
|
# Run the scheduler
|
|
87
88
|
from jararaca.scheduler.scheduler import Scheduler
|
|
89
|
+
|
|
88
90
|
scheduler = Scheduler(app, interval=1)
|
|
89
91
|
scheduler.run()
|
|
90
92
|
```
|
|
@@ -128,7 +130,7 @@ sequenceDiagram
|
|
|
128
130
|
participant B as Message Broker
|
|
129
131
|
participant R as Redis Backend
|
|
130
132
|
participant W as Worker
|
|
131
|
-
|
|
133
|
+
|
|
132
134
|
S->>R: Check last execution time
|
|
133
135
|
R-->>S: Return last execution time
|
|
134
136
|
S->>S: Determine if task should run
|
|
@@ -148,19 +150,20 @@ The V2 scheduler also supports delayed messages:
|
|
|
148
150
|
from jararaca import use_publisher
|
|
149
151
|
from jararaca.scheduler.types import DelayedMessageData
|
|
150
152
|
|
|
153
|
+
|
|
151
154
|
# Schedule a message to be published at a future time
|
|
152
155
|
async def schedule_reminder():
|
|
153
156
|
message = ReminderMessage(
|
|
154
157
|
user_id="123",
|
|
155
158
|
message="Don't forget your appointment!"
|
|
156
159
|
)
|
|
157
|
-
|
|
160
|
+
|
|
158
161
|
# Current time + 1 hour in seconds
|
|
159
162
|
dispatch_time = int(time.time()) + 3600
|
|
160
|
-
|
|
163
|
+
|
|
161
164
|
# Get publisher
|
|
162
165
|
publisher = use_publisher()
|
|
163
|
-
|
|
166
|
+
|
|
164
167
|
# Schedule delayed message
|
|
165
168
|
await publisher.publish_delayed(
|
|
166
169
|
message,
|
|
@@ -213,4 +216,4 @@ jararaca scheduler_v2 APP_PATH [OPTIONS]
|
|
|
213
216
|
|
|
214
217
|
## Conclusion
|
|
215
218
|
|
|
216
|
-
The Jararaca scheduler system provides a powerful, flexible way to implement periodic tasks in your applications. With two implementations to choose from, you can select the one that best fits your application's requirements, from simple local scheduling to complex distributed task execution.
|
|
219
|
+
The Jararaca scheduler system provides a powerful, flexible way to implement periodic tasks in your applications. With two implementations to choose from, you can select the one that best fits your application's requirements, from simple local scheduling to complex distributed task execution.
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import importlib
|
|
2
2
|
import importlib.resources
|
|
3
|
+
import multiprocessing
|
|
3
4
|
import os
|
|
4
5
|
import sys
|
|
5
6
|
import time
|
|
6
7
|
from codecs import StreamWriter
|
|
8
|
+
from pathlib import Path
|
|
7
9
|
from typing import Any
|
|
8
10
|
from urllib.parse import urlparse, urlunsplit
|
|
9
11
|
|
|
@@ -265,6 +267,30 @@ def scheduler_v2(
|
|
|
265
267
|
scheduler.run()
|
|
266
268
|
|
|
267
269
|
|
|
270
|
+
def generate_interfaces(app_path: str, file_path: str) -> None:
|
|
271
|
+
try:
|
|
272
|
+
app = find_microservice_by_module_path(app_path)
|
|
273
|
+
content = write_microservice_to_typescript_interface(app)
|
|
274
|
+
|
|
275
|
+
with open(file_path, "w", encoding="utf-8") as file:
|
|
276
|
+
# Save current position
|
|
277
|
+
file.tell()
|
|
278
|
+
|
|
279
|
+
# Reset file to beginning
|
|
280
|
+
file.seek(0)
|
|
281
|
+
file.truncate()
|
|
282
|
+
|
|
283
|
+
# Write new content
|
|
284
|
+
file.write(content)
|
|
285
|
+
file.flush()
|
|
286
|
+
|
|
287
|
+
print(
|
|
288
|
+
f"Generated TypeScript interfaces at {time.strftime('%H:%M:%S')} at {str(Path(file_path).absolute())}"
|
|
289
|
+
)
|
|
290
|
+
except Exception as e:
|
|
291
|
+
print(f"Error generating TypeScript interfaces: {e}", file=sys.stderr)
|
|
292
|
+
|
|
293
|
+
|
|
268
294
|
@cli.command()
|
|
269
295
|
@click.argument(
|
|
270
296
|
"app_path",
|
|
@@ -272,7 +298,7 @@ def scheduler_v2(
|
|
|
272
298
|
)
|
|
273
299
|
@click.argument(
|
|
274
300
|
"file_path",
|
|
275
|
-
type=click.
|
|
301
|
+
type=click.Path(file_okay=True, dir_okay=False),
|
|
276
302
|
)
|
|
277
303
|
@click.option(
|
|
278
304
|
"--watch",
|
|
@@ -283,32 +309,11 @@ def scheduler_v2(
|
|
|
283
309
|
type=click.Path(exists=True, file_okay=False, dir_okay=True),
|
|
284
310
|
default="src",
|
|
285
311
|
)
|
|
286
|
-
def gen_tsi(app_path: str, file_path:
|
|
312
|
+
def gen_tsi(app_path: str, file_path: str, watch: bool, src_dir: str) -> None:
|
|
287
313
|
"""Generate TypeScript interfaces from a Python microservice."""
|
|
288
314
|
|
|
289
|
-
# Generate typescript interfaces
|
|
290
|
-
def generate_interfaces() -> None:
|
|
291
|
-
try:
|
|
292
|
-
app = find_microservice_by_module_path(app_path)
|
|
293
|
-
content = write_microservice_to_typescript_interface(app)
|
|
294
|
-
|
|
295
|
-
# Save current position
|
|
296
|
-
file_path.tell()
|
|
297
|
-
|
|
298
|
-
# Reset file to beginning
|
|
299
|
-
file_path.seek(0)
|
|
300
|
-
file_path.truncate()
|
|
301
|
-
|
|
302
|
-
# Write new content
|
|
303
|
-
file_path.write(content)
|
|
304
|
-
file_path.flush()
|
|
305
|
-
|
|
306
|
-
print(f"Generated TypeScript interfaces at {time.strftime('%H:%M:%S')}")
|
|
307
|
-
except Exception as e:
|
|
308
|
-
print(f"Error generating TypeScript interfaces: {e}", file=sys.stderr)
|
|
309
|
-
|
|
310
315
|
# Initial generation
|
|
311
|
-
generate_interfaces()
|
|
316
|
+
generate_interfaces(app_path, file_path)
|
|
312
317
|
|
|
313
318
|
# If watch mode is not enabled, exit
|
|
314
319
|
if not watch:
|
|
@@ -334,7 +339,33 @@ def gen_tsi(app_path: str, file_path: StreamWriter, watch: bool, src_dir: str) -
|
|
|
334
339
|
)
|
|
335
340
|
if not event.is_directory and src_path.endswith(".py"):
|
|
336
341
|
print(f"File changed: {src_path}")
|
|
337
|
-
|
|
342
|
+
# Create a completely detached process to ensure classes are reloaded
|
|
343
|
+
process = multiprocessing.get_context("spawn").Process(
|
|
344
|
+
target=generate_interfaces,
|
|
345
|
+
args=(app_path, file_path),
|
|
346
|
+
daemon=False, # Non-daemon to ensure it completes
|
|
347
|
+
)
|
|
348
|
+
process.start()
|
|
349
|
+
# Don't join to keep it detached from main process
|
|
350
|
+
|
|
351
|
+
def _run_generator_in_separate_process(
|
|
352
|
+
self, app_path: str, file_path: str
|
|
353
|
+
) -> None:
|
|
354
|
+
# Using Python executable to start a completely new process
|
|
355
|
+
# This ensures all modules are freshly imported
|
|
356
|
+
generate_interfaces(app_path, file_path)
|
|
357
|
+
# cmd = [
|
|
358
|
+
# sys.executable,
|
|
359
|
+
# "-c",
|
|
360
|
+
# (
|
|
361
|
+
# f"import sys; sys.path.extend({sys.path}); "
|
|
362
|
+
# f"from jararaca.cli import generate_interfaces; "
|
|
363
|
+
# f"generate_interfaces('{app_path}', '{file_path}')"
|
|
364
|
+
# ),
|
|
365
|
+
# ]
|
|
366
|
+
# import subprocess
|
|
367
|
+
|
|
368
|
+
# subprocess.run(cmd, check=False)
|
|
338
369
|
|
|
339
370
|
# Set up observer
|
|
340
371
|
observer = Observer()
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
from contextlib import asynccontextmanager
|
|
2
3
|
from datetime import datetime, timedelta
|
|
3
4
|
from datetime import tzinfo as _TzInfo
|
|
@@ -29,10 +30,10 @@ class AIOPikaMessagePublisher(MessagePublisher):
|
|
|
29
30
|
self.message_broker_backend = message_broker_backend
|
|
30
31
|
|
|
31
32
|
async def publish(self, message: IMessage, topic: str) -> None:
|
|
32
|
-
exchange = await self.channel.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
exchange = await self.channel.get_exchange(self.exchange_name, ensure=False)
|
|
34
|
+
if not exchange:
|
|
35
|
+
logging.warning(f"Exchange {self.exchange_name} not found")
|
|
36
|
+
return
|
|
36
37
|
routing_key = f"{topic}."
|
|
37
38
|
await exchange.publish(
|
|
38
39
|
aio_pika.Message(body=message.model_dump_json().encode()),
|
|
@@ -193,10 +193,11 @@ def parse_type_to_typescript_interface(
|
|
|
193
193
|
mapped_types.update(inherited_classes)
|
|
194
194
|
|
|
195
195
|
if Enum in inherited_classes:
|
|
196
|
+
enum_values = sorted([(x._name_, x.value) for x in basemodel_type])
|
|
196
197
|
return (
|
|
197
198
|
set(),
|
|
198
199
|
f"export enum {basemodel_type.__name__} {{\n"
|
|
199
|
-
+ "\n ".join([f'\t{
|
|
200
|
+
+ "\n ".join([f'\t{name} = "{value}",' for name, value in enum_values])
|
|
200
201
|
+ "\n}\n",
|
|
201
202
|
)
|
|
202
203
|
|
|
@@ -222,31 +223,39 @@ def parse_type_to_typescript_interface(
|
|
|
222
223
|
extends_expression = (
|
|
223
224
|
" extends %s"
|
|
224
225
|
% ", ".join(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
226
|
+
sorted(
|
|
227
|
+
[
|
|
228
|
+
(
|
|
229
|
+
"%s" % get_field_type_for_ts(inherited_class)
|
|
230
|
+
if not inherited_classes_consts_conflict[inherited_class]
|
|
231
|
+
else "Omit<%s, %s>"
|
|
232
|
+
% (
|
|
233
|
+
get_field_type_for_ts(inherited_class),
|
|
234
|
+
" | ".join(
|
|
235
|
+
sorted(
|
|
236
|
+
[
|
|
237
|
+
'"%s"' % field_name
|
|
238
|
+
for field_name in inherited_classes_consts_conflict[
|
|
239
|
+
inherited_class
|
|
240
|
+
]
|
|
241
|
+
]
|
|
242
|
+
)
|
|
243
|
+
),
|
|
244
|
+
)
|
|
238
245
|
)
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
246
|
+
for inherited_class in valid_inherited_classes
|
|
247
|
+
],
|
|
248
|
+
key=lambda x: str(x),
|
|
249
|
+
)
|
|
242
250
|
)
|
|
243
251
|
if len(valid_inherited_classes) > 0
|
|
244
252
|
else ""
|
|
245
253
|
)
|
|
246
254
|
|
|
247
255
|
if is_generic_type(basemodel_type):
|
|
256
|
+
generic_args = get_generic_args(basemodel_type)
|
|
248
257
|
string_builder.write(
|
|
249
|
-
f"export interface {basemodel_type.__name__}<{', '.join([arg.__name__ for arg in
|
|
258
|
+
f"export interface {basemodel_type.__name__}<{', '.join(sorted([arg.__name__ for arg in generic_args]))}>{extends_expression} {{\n"
|
|
250
259
|
)
|
|
251
260
|
else:
|
|
252
261
|
string_builder.write(
|
|
@@ -254,12 +263,12 @@ def parse_type_to_typescript_interface(
|
|
|
254
263
|
)
|
|
255
264
|
|
|
256
265
|
if hasattr(basemodel_type, "__annotations__"):
|
|
257
|
-
#
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
for field_name, field in
|
|
266
|
+
# Sort fields for consistent output
|
|
267
|
+
annotation_items = sorted(
|
|
268
|
+
basemodel_type.__annotations__.items(), key=lambda x: x[0]
|
|
269
|
+
)
|
|
270
|
+
|
|
271
|
+
for field_name, field in annotation_items:
|
|
263
272
|
if field_name in cls_consts:
|
|
264
273
|
continue
|
|
265
274
|
|
|
@@ -277,8 +286,11 @@ def parse_type_to_typescript_interface(
|
|
|
277
286
|
mapped_types.update(extract_all_envolved_types(field))
|
|
278
287
|
mapped_types.add(field)
|
|
279
288
|
|
|
280
|
-
## Loop over computed fields
|
|
281
|
-
members =
|
|
289
|
+
## Loop over computed fields - sort them for consistent output
|
|
290
|
+
members = sorted(
|
|
291
|
+
inspect.getmembers(basemodel_type, lambda a: isinstance(a, property)),
|
|
292
|
+
key=lambda x: x[0],
|
|
293
|
+
)
|
|
282
294
|
for field_name, field in members:
|
|
283
295
|
if hasattr(field, "fget"):
|
|
284
296
|
module_func_name = field.fget.__module__ + "." + field.fget.__qualname__
|
|
@@ -359,11 +371,13 @@ export type WebSocketMessageMap = {
|
|
|
359
371
|
}
|
|
360
372
|
"""
|
|
361
373
|
% "\n".join(
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
374
|
+
sorted(
|
|
375
|
+
[
|
|
376
|
+
f'\t"{message.MESSAGE_ID}": {message.__name__};'
|
|
377
|
+
for registers in websocket_registries
|
|
378
|
+
for message in registers.message_types
|
|
379
|
+
]
|
|
380
|
+
)
|
|
367
381
|
)
|
|
368
382
|
)
|
|
369
383
|
|
|
@@ -477,7 +491,12 @@ def write_rest_controller_to_typescript_interface(
|
|
|
477
491
|
|
|
478
492
|
mapped_types: set[Any] = set()
|
|
479
493
|
|
|
480
|
-
|
|
494
|
+
# Sort members for consistent output
|
|
495
|
+
member_items = sorted(
|
|
496
|
+
inspect.getmembers(controller, predicate=inspect.isfunction), key=lambda x: x[0]
|
|
497
|
+
)
|
|
498
|
+
|
|
499
|
+
for name, member in member_items:
|
|
481
500
|
if (mapping := HttpMapping.get_http_mapping(member)) is not None:
|
|
482
501
|
return_type = member.__annotations__.get("return")
|
|
483
502
|
|
|
@@ -514,17 +533,24 @@ def write_rest_controller_to_typescript_interface(
|
|
|
514
533
|
)
|
|
515
534
|
class_buffer.write(f"\t\t\tpath: `/{final_path}`,\n")
|
|
516
535
|
|
|
536
|
+
# Sort headers
|
|
537
|
+
header_params = sorted(
|
|
538
|
+
[param for param in arg_params_spec if param.type_ == "header"],
|
|
539
|
+
key=lambda x: x.name,
|
|
540
|
+
)
|
|
517
541
|
class_buffer.write("\t\t\theaders: {\n")
|
|
518
|
-
for param in
|
|
519
|
-
|
|
520
|
-
class_buffer.write(f'\t\t\t\t"{param.name}": {param.name},\n')
|
|
521
|
-
|
|
542
|
+
for param in header_params:
|
|
543
|
+
class_buffer.write(f'\t\t\t\t"{param.name}": {param.name},\n')
|
|
522
544
|
class_buffer.write("\t\t\t},\n")
|
|
523
|
-
class_buffer.write("\t\t\tquery: {\n")
|
|
524
545
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
546
|
+
# Sort query params
|
|
547
|
+
query_params = sorted(
|
|
548
|
+
[param for param in arg_params_spec if param.type_ == "query"],
|
|
549
|
+
key=lambda x: x.name,
|
|
550
|
+
)
|
|
551
|
+
class_buffer.write("\t\t\tquery: {\n")
|
|
552
|
+
for param in query_params:
|
|
553
|
+
class_buffer.write(f'\t\t\t\t"{param.name}": {param.name},\n')
|
|
528
554
|
class_buffer.write("\t\t\t},\n")
|
|
529
555
|
|
|
530
556
|
if (
|
|
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
|
{jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/messagebus/interceptors/publisher_interceptor.py
RENAMED
|
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
|
{jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/persistence/interceptors/aiosqa_interceptor.py
RENAMED
|
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
|
{jararaca-0.3.0 → jararaca-0.3.2}/src/jararaca/presentation/websocket/websocket_interceptor.py
RENAMED
|
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
|