py2axum 0.1.0__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 (51) hide show
  1. py2axum/__init__.py +0 -0
  2. py2axum/__main__.py +81 -0
  3. py2axum/body.py +1180 -0
  4. py2axum/codegen.py +493 -0
  5. py2axum/dyn.py +5370 -0
  6. py2axum/frontend.py +812 -0
  7. py2axum/ir.py +180 -0
  8. py2axum/libmap.py +559 -0
  9. py2axum/modules.py +249 -0
  10. py2axum/report.py +234 -0
  11. py2axum/runtime/Cargo.lock +4421 -0
  12. py2axum/runtime/dynrt/aio.rs +224 -0
  13. py2axum/runtime/dynrt/asgi.rs +534 -0
  14. py2axum/runtime/dynrt/auth.rs +335 -0
  15. py2axum/runtime/dynrt/decimal.rs +474 -0
  16. py2axum/runtime/dynrt/dt.rs +484 -0
  17. py2axum/runtime/dynrt/email.rs +276 -0
  18. py2axum/runtime/dynrt/fernet.rs +106 -0
  19. py2axum/runtime/dynrt/files.rs +150 -0
  20. py2axum/runtime/dynrt/google.rs +206 -0
  21. py2axum/runtime/dynrt/http.rs +586 -0
  22. py2axum/runtime/dynrt/ini.rs +141 -0
  23. py2axum/runtime/dynrt/itsd.rs +207 -0
  24. py2axum/runtime/dynrt/jose.rs +422 -0
  25. py2axum/runtime/dynrt/libs.rs +669 -0
  26. py2axum/runtime/dynrt/mail.rs +537 -0
  27. py2axum/runtime/dynrt/methods.rs +1941 -0
  28. py2axum/runtime/dynrt/mod.rs +570 -0
  29. py2axum/runtime/dynrt/ops.rs +1572 -0
  30. py2axum/runtime/dynrt/orm.rs +3747 -0
  31. py2axum/runtime/dynrt/pathio.rs +395 -0
  32. py2axum/runtime/dynrt/pickle.rs +904 -0
  33. py2axum/runtime/dynrt/pyd.rs +1706 -0
  34. py2axum/runtime/dynrt/rds.rs +337 -0
  35. py2axum/runtime/dynrt/resp.rs +482 -0
  36. py2axum/runtime/dynrt/rmq.rs +332 -0
  37. py2axum/runtime/dynrt/stdlib.rs +1526 -0
  38. py2axum/runtime/dynrt/sysmon.rs +121 -0
  39. py2axum/runtime/dynrt/tenacity.rs +570 -0
  40. py2axum/runtime/dynrt/thread.rs +481 -0
  41. py2axum/runtime/dynrt/types.rs +209 -0
  42. py2axum/runtime/dynrt/v.rs +790 -0
  43. py2axum/runtime/dynrt/web.rs +1015 -0
  44. py2axum/runtime/dynrt/webpush.rs +280 -0
  45. py2axum/runtime/rt.rs +826 -0
  46. py2axum-0.1.0.dist-info/METADATA +151 -0
  47. py2axum-0.1.0.dist-info/RECORD +51 -0
  48. py2axum-0.1.0.dist-info/WHEEL +4 -0
  49. py2axum-0.1.0.dist-info/entry_points.txt +2 -0
  50. py2axum-0.1.0.dist-info/licenses/LICENSE +202 -0
  51. py2axum-0.1.0.dist-info/licenses/NOTICE +5 -0
py2axum/__init__.py ADDED
File without changes
py2axum/__main__.py ADDED
@@ -0,0 +1,81 @@
1
+ """py2axum: transpile a FastAPI + SQLAlchemy + Pydantic + aiohttp package to a Rust/axum project.
2
+
3
+ usage: python -m py2axum <python package dir> -o <output dir> [--name crate_name] [--root DIR]
4
+ python -m py2axum <python package dir> --report report.md [--root DIR] (+ report.json)
5
+ """
6
+ from __future__ import annotations
7
+
8
+ import argparse
9
+ import sys
10
+ from pathlib import Path
11
+
12
+ from .codegen import TranspileErrors, generate
13
+ from .frontend import Frontend
14
+ from .ir import TranspileError
15
+
16
+
17
+ def main(argv: list[str] | None = None) -> int:
18
+ ap = argparse.ArgumentParser(prog="py2axum", description=__doc__.splitlines()[0])
19
+ ap.add_argument("package", type=Path, help="directory of the FastAPI application package")
20
+ ap.add_argument("-o", "--out", type=Path, help="output directory for the Rust project")
21
+ ap.add_argument("--root", type=Path, default=None,
22
+ help="import root, like sys.path (default: parent of the package)")
23
+ ap.add_argument("--backend", choices=["auto", "typed", "dyn"], default="auto",
24
+ help="typed: static Rust (narrow subset); dyn: dynamic values (real projects); auto: typed, else dyn")
25
+ ap.add_argument("--python-side", action="append", default=[], metavar="PATH|lifespan",
26
+ help="what stays in a Python process next to the binary (raw routes such as /api/v1/mcp, lifespan)")
27
+ ap.add_argument("--report", type=Path, default=None,
28
+ help="coverage report (Markdown + JSON) instead of generating: never stops at the first error")
29
+ ap.add_argument("--name", default=None, help="crate name (default: <package>_axum)")
30
+ ap.add_argument("--no-stream", action="store_true", help="buffer list responses instead of streaming them")
31
+ args = ap.parse_args(argv)
32
+ if args.report:
33
+ from .report import aggregate, build, write
34
+
35
+ result = build(args.package, args.root, stream=not args.no_stream,
36
+ python_side=tuple(args.python_side) or ("lifespan",))
37
+ write(result, args.report)
38
+ agg = aggregate(result["routes"])
39
+ print(f"report {args.report} (+ .json): {agg['traduites']}/{agg['total']} routes translated", file=sys.stderr)
40
+ return 0
41
+ if args.out is None:
42
+ ap.error("-o/--out is required (or --report)")
43
+
44
+ crate = args.name or f"{args.package.resolve().name}_axum"
45
+ typed_error = None
46
+ if args.backend in {"auto", "typed"}:
47
+ try:
48
+ app = Frontend(args.package, args.root).run()
49
+ generate(app, args.out, str(args.package), crate, stream=not args.no_stream)
50
+ print(
51
+ f"generated {args.out}: {len(app.routes)} routes, {len(app.models)} models, {len(app.schemas)} schemas",
52
+ file=sys.stderr,
53
+ )
54
+ return 0
55
+ except (TranspileError, TranspileErrors) as e:
56
+ typed_error = e
57
+ if args.backend == "typed":
58
+ for err in getattr(e, "errors", [e]):
59
+ print(f"error: {err.render()}", file=sys.stderr)
60
+ return 1
61
+ from . import dyn
62
+
63
+ try:
64
+ fe = Frontend(args.package, args.root)
65
+ gzip = dyn.prepare(fe, set(args.python_side))
66
+ proj = dyn.generate_project(fe, args.out, str(args.package), crate, gzip=gzip)
67
+ except TranspileError as e:
68
+ print(f"error: {e.render()}", file=sys.stderr)
69
+ return 1
70
+ for n in fe.notes:
71
+ print(f"note: {n}", file=sys.stderr)
72
+ print(
73
+ f"generated {args.out} (dyn backend): {len(proj.fns)} functions, {len(proj.models)} models, "
74
+ f"{len(proj.schemas)} schemas" + (f" — typed backend: {typed_error.render()}" if typed_error and args.backend == "auto" and hasattr(typed_error, "render") else ""),
75
+ file=sys.stderr,
76
+ )
77
+ return 0
78
+
79
+
80
+ if __name__ == "__main__":
81
+ sys.exit(main())