nyxa 0.0.1__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 (336) hide show
  1. nyxa/__init__.py +296 -0
  2. nyxa/__main__.py +6 -0
  3. nyxa/_awaitable.py +46 -0
  4. nyxa/_current.py +44 -0
  5. nyxa/_speedups.py +170 -0
  6. nyxa/adapters/__init__.py +72 -0
  7. nyxa/adapters/asgi.py +84 -0
  8. nyxa/adapters/base.py +139 -0
  9. nyxa/adapters/cloudrun.py +103 -0
  10. nyxa/adapters/container.py +254 -0
  11. nyxa/adapters/docker.py +131 -0
  12. nyxa/adapters/fly.py +60 -0
  13. nyxa/adapters/granian.py +94 -0
  14. nyxa/adapters/native.py +85 -0
  15. nyxa/adapters/promotion.py +232 -0
  16. nyxa/adapters/railway.py +46 -0
  17. nyxa/adapters/render.py +39 -0
  18. nyxa/application.py +5 -0
  19. nyxa/asgi.py +16 -0
  20. nyxa/bridge/__init__.py +30 -0
  21. nyxa/bridge/asgi.py +561 -0
  22. nyxa/bridge/base.py +54 -0
  23. nyxa/bridge/blacksheep.py +113 -0
  24. nyxa/bridge/native.py +364 -0
  25. nyxa/bridge/rsgi.py +346 -0
  26. nyxa/bridge/starlette.py +81 -0
  27. nyxa/build/__init__.py +1 -0
  28. nyxa/build/binary.py +106 -0
  29. nyxa/build/bundle.py +501 -0
  30. nyxa/build/classify.py +229 -0
  31. nyxa/build/deps.py +548 -0
  32. nyxa/build/emit_config.py +138 -0
  33. nyxa/build/emit_container.py +78 -0
  34. nyxa/build/emit_discovery.py +179 -0
  35. nyxa/build/emit_macros.py +234 -0
  36. nyxa/build/emit_plans.py +304 -0
  37. nyxa/build/emit_routes.py +343 -0
  38. nyxa/build/frozen.py +193 -0
  39. nyxa/build/manifest.py +150 -0
  40. nyxa/build/suggest.py +118 -0
  41. nyxa/cli/__init__.py +14 -0
  42. nyxa/cli/ai_scaffold.py +172 -0
  43. nyxa/cli/commands/__init__.py +176 -0
  44. nyxa/cli/commands/backup.py +251 -0
  45. nyxa/cli/commands/catalog.py +61 -0
  46. nyxa/cli/commands/database.py +231 -0
  47. nyxa/cli/commands/deploy_promote.py +91 -0
  48. nyxa/cli/commands/project.py +972 -0
  49. nyxa/cli/commands/publish.py +166 -0
  50. nyxa/cli/commands/queue.py +351 -0
  51. nyxa/cli/commands/runtime.py +714 -0
  52. nyxa/cli/commands/scaffold.py +562 -0
  53. nyxa/cli/commands/schedule.py +313 -0
  54. nyxa/cli/commands/utils.py +73 -0
  55. nyxa/cli/commands/workflows.py +102 -0
  56. nyxa/cli/dev.py +204 -0
  57. nyxa/cli/fields.py +292 -0
  58. nyxa/cli/hooks.py +157 -0
  59. nyxa/cli/kits.py +107 -0
  60. nyxa/cli/local_deps.py +173 -0
  61. nyxa/cli/main.py +69 -0
  62. nyxa/cli/make.py +1484 -0
  63. nyxa/cli/new.py +161 -0
  64. nyxa/cli/ops_assist.py +48 -0
  65. nyxa/cli/package.py +275 -0
  66. nyxa/cli/runtime/__init__.py +85 -0
  67. nyxa/cli/runtime/bridge.py +206 -0
  68. nyxa/cli/runtime/process.py +82 -0
  69. nyxa/cli/runtime/ui/__init__.py +7 -0
  70. nyxa/cli/runtime/ui/app.py +58 -0
  71. nyxa/cli/runtime/ui/runner.py +113 -0
  72. nyxa/cli/runtime/ui/screens/__init__.py +7 -0
  73. nyxa/cli/runtime/ui/screens/home.py +416 -0
  74. nyxa/cli/runtime/ui/slash.py +76 -0
  75. nyxa/cli/runtime/ui/widgets/__init__.py +19 -0
  76. nyxa/cli/runtime/ui/widgets/choice_overlay.py +133 -0
  77. nyxa/cli/runtime/ui/widgets/chrome.py +42 -0
  78. nyxa/cli/runtime/ui/widgets/input_bar.py +102 -0
  79. nyxa/cli/runtime/ui/widgets/scrollback.py +60 -0
  80. nyxa/cli/runtime/ui/widgets/slash_menu.py +77 -0
  81. nyxa/cli/runtime/ui/widgets/status_bar.py +114 -0
  82. nyxa/cli/stubs/action.stub +14 -0
  83. nyxa/cli/stubs/agents_md.stub +47 -0
  84. nyxa/cli/stubs/app_provider.stub +14 -0
  85. nyxa/cli/stubs/binary_cargo_toml.stub +7 -0
  86. nyxa/cli/stubs/binary_main_rs.stub +21 -0
  87. nyxa/cli/stubs/command.stub +17 -0
  88. nyxa/cli/stubs/config_app.stub +6 -0
  89. nyxa/cli/stubs/config_csrf.stub +9 -0
  90. nyxa/cli/stubs/config_database.stub +51 -0
  91. nyxa/cli/stubs/config_http.stub +19 -0
  92. nyxa/cli/stubs/config_queue.stub +51 -0
  93. nyxa/cli/stubs/config_workflows.stub +20 -0
  94. nyxa/cli/stubs/conftest.stub +28 -0
  95. nyxa/cli/stubs/controller.home.stub +8 -0
  96. nyxa/cli/stubs/controller.invokable.stub +8 -0
  97. nyxa/cli/stubs/controller.model.crud.stub +31 -0
  98. nyxa/cli/stubs/controller.model.stub +24 -0
  99. nyxa/cli/stubs/controller.resource.stub +20 -0
  100. nyxa/cli/stubs/controller.singleton.stub +13 -0
  101. nyxa/cli/stubs/controller.stub +8 -0
  102. nyxa/cli/stubs/env_example.stub +7 -0
  103. nyxa/cli/stubs/event.stub +14 -0
  104. nyxa/cli/stubs/exception.stub +18 -0
  105. nyxa/cli/stubs/factory.stub +19 -0
  106. nyxa/cli/stubs/fly.toml.stub +19 -0
  107. nyxa/cli/stubs/form_request.bare.stub +21 -0
  108. nyxa/cli/stubs/form_request.pair.stub +25 -0
  109. nyxa/cli/stubs/form_request.store.stub +15 -0
  110. nyxa/cli/stubs/form_request.update.stub +15 -0
  111. nyxa/cli/stubs/gitignore.stub +9 -0
  112. nyxa/cli/stubs/job.stub +22 -0
  113. nyxa/cli/stubs/listener.stub +18 -0
  114. nyxa/cli/stubs/manifest.stub +10 -0
  115. nyxa/cli/stubs/middleware.stub +13 -0
  116. nyxa/cli/stubs/migration.create.fields.stub +24 -0
  117. nyxa/cli/stubs/migration.create.stub +24 -0
  118. nyxa/cli/stubs/migration.stub +17 -0
  119. nyxa/cli/stubs/model.fields.stub +13 -0
  120. nyxa/cli/stubs/model.stub +13 -0
  121. nyxa/cli/stubs/package.config.stub +3 -0
  122. nyxa/cli/stubs/package.init.stub +7 -0
  123. nyxa/cli/stubs/package.lang.stub +1 -0
  124. nyxa/cli/stubs/package.migration.stub +23 -0
  125. nyxa/cli/stubs/package.provider.stub +23 -0
  126. nyxa/cli/stubs/package.pyproject.stub +36 -0
  127. nyxa/cli/stubs/package.routes.stub +5 -0
  128. nyxa/cli/stubs/package.test.stub +17 -0
  129. nyxa/cli/stubs/package.view.stub +2 -0
  130. nyxa/cli/stubs/provider.stub +21 -0
  131. nyxa/cli/stubs/pyproject.stub +12 -0
  132. nyxa/cli/stubs/railway.toml.stub +10 -0
  133. nyxa/cli/stubs/render.yaml.stub +9 -0
  134. nyxa/cli/stubs/routes.stub +6 -0
  135. nyxa/cli/stubs/schedule.stub +18 -0
  136. nyxa/cli/stubs/seeder.stub +13 -0
  137. nyxa/cli/stubs/service.ai.stub +11 -0
  138. nyxa/cli/stubs/service.stub +5 -0
  139. nyxa/cli/stubs/smoke_test.stub +26 -0
  140. nyxa/cli/stubs/test.action.stub +15 -0
  141. nyxa/cli/stubs/test.command.stub +20 -0
  142. nyxa/cli/stubs/test.controller.invokable.stub +25 -0
  143. nyxa/cli/stubs/test.controller.model.crud.stub +42 -0
  144. nyxa/cli/stubs/test.controller.model.stub +42 -0
  145. nyxa/cli/stubs/test.controller.resource.stub +40 -0
  146. nyxa/cli/stubs/test.controller.singleton.stub +30 -0
  147. nyxa/cli/stubs/test.controller.stub +27 -0
  148. nyxa/cli/stubs/test.event.stub +22 -0
  149. nyxa/cli/stubs/test.exception.stub +18 -0
  150. nyxa/cli/stubs/test.job.stub +25 -0
  151. nyxa/cli/stubs/test.listener.stub +33 -0
  152. nyxa/cli/stubs/test.middleware.stub +25 -0
  153. nyxa/cli/stubs/test.provider.stub +24 -0
  154. nyxa/cli/stubs/test.service.stub +16 -0
  155. nyxa/cli/stubs/test.stub +16 -0
  156. nyxa/cli/stubs/test.validator.stub +16 -0
  157. nyxa/cli/stubs/validator.stub +9 -0
  158. nyxa/cli/stubs/workflow.cloudrun.yml.stub +39 -0
  159. nyxa/cli/stubs/workflow.docker.yml.stub +304 -0
  160. nyxa/cli/stubs/workflow.fly.yml.stub +27 -0
  161. nyxa/cli/stubs/workflow.stub +23 -0
  162. nyxa/cli/templates.py +134 -0
  163. nyxa/cli/wizard.py +576 -0
  164. nyxa/command.py +363 -0
  165. nyxa/concurrency.py +97 -0
  166. nyxa/config/__init__.py +41 -0
  167. nyxa/config/config.py +599 -0
  168. nyxa/config/env.py +86 -0
  169. nyxa/config/logging.py +285 -0
  170. nyxa/config/secrets.py +95 -0
  171. nyxa/console/__init__.py +7 -0
  172. nyxa/console/errors.py +30 -0
  173. nyxa/console/input.py +102 -0
  174. nyxa/console/kernel.py +340 -0
  175. nyxa/console/output.py +426 -0
  176. nyxa/console/parser.py +121 -0
  177. nyxa/console/signature.py +222 -0
  178. nyxa/container.py +24 -0
  179. nyxa/context.py +779 -0
  180. nyxa/contracts.py +276 -0
  181. nyxa/controller.py +130 -0
  182. nyxa/core/__init__.py +6 -0
  183. nyxa/core/application.py +1542 -0
  184. nyxa/core/container.py +781 -0
  185. nyxa/core/direct.py +321 -0
  186. nyxa/core/discovery.py +168 -0
  187. nyxa/core/ignitor.py +306 -0
  188. nyxa/core/maintenance.py +134 -0
  189. nyxa/core/manifest.py +210 -0
  190. nyxa/core/plugins.py +261 -0
  191. nyxa/core/serve.py +700 -0
  192. nyxa/core/settings.py +115 -0
  193. nyxa/core/telemetry.py +104 -0
  194. nyxa/db/__init__.py +109 -0
  195. nyxa/db/builder.py +914 -0
  196. nyxa/db/casts.py +178 -0
  197. nyxa/db/collection.py +605 -0
  198. nyxa/db/connection.py +565 -0
  199. nyxa/db/drivers/__init__.py +43 -0
  200. nyxa/db/drivers/base.py +140 -0
  201. nyxa/db/drivers/mysql.py +351 -0
  202. nyxa/db/drivers/postgres.py +338 -0
  203. nyxa/db/drivers/sqlite.py +273 -0
  204. nyxa/db/errors.py +73 -0
  205. nyxa/db/events.py +125 -0
  206. nyxa/db/factory.py +323 -0
  207. nyxa/db/grammar.py +707 -0
  208. nyxa/db/manager.py +328 -0
  209. nyxa/db/migrations.py +383 -0
  210. nyxa/db/model.py +1597 -0
  211. nyxa/db/pagination.py +142 -0
  212. nyxa/db/plan.py +128 -0
  213. nyxa/db/provider.py +7 -0
  214. nyxa/db/query.py +612 -0
  215. nyxa/db/relations.py +1084 -0
  216. nyxa/db/schema.py +308 -0
  217. nyxa/db/seeder.py +105 -0
  218. nyxa/db/sync.py +357 -0
  219. nyxa/db/traits.py +105 -0
  220. nyxa/db/vectors.py +92 -0
  221. nyxa/dev/__init__.py +7 -0
  222. nyxa/dev/access.py +53 -0
  223. nyxa/dev/introspect.py +377 -0
  224. nyxa/dev/snapshot.py +436 -0
  225. nyxa/discovery.py +19 -0
  226. nyxa/env.py +5 -0
  227. nyxa/errors.py +245 -0
  228. nyxa/events.py +748 -0
  229. nyxa/exceptions.py +131 -0
  230. nyxa/helpers/__init__.py +195 -0
  231. nyxa/helpers/ambient.py +826 -0
  232. nyxa/helpers/benchmark.py +36 -0
  233. nyxa/helpers/bounded.py +232 -0
  234. nyxa/helpers/core.py +876 -0
  235. nyxa/helpers/dates.py +46 -0
  236. nyxa/helpers/payload.py +99 -0
  237. nyxa/helpers/pipeline.py +115 -0
  238. nyxa/helpers/timebox.py +54 -0
  239. nyxa/http/__init__.py +105 -0
  240. nyxa/http/context.py +541 -0
  241. nyxa/http/ctx_snapshot.py +146 -0
  242. nyxa/http/exceptions.py +228 -0
  243. nyxa/http/headers.py +68 -0
  244. nyxa/http/multipart.py +168 -0
  245. nyxa/http/params.py +416 -0
  246. nyxa/http/request.py +671 -0
  247. nyxa/http/response.py +969 -0
  248. nyxa/http/streaming.py +93 -0
  249. nyxa/http/streams.py +144 -0
  250. nyxa/http/websocket.py +194 -0
  251. nyxa/ignitor.py +6 -0
  252. nyxa/logging.py +9 -0
  253. nyxa/manifest.py +5 -0
  254. nyxa/middleware/__init__.py +75 -0
  255. nyxa/middleware/access_log.py +80 -0
  256. nyxa/middleware/context.py +40 -0
  257. nyxa/middleware/cors.py +172 -0
  258. nyxa/middleware/csrf.py +287 -0
  259. nyxa/middleware/discovery.py +58 -0
  260. nyxa/middleware/gzip.py +128 -0
  261. nyxa/middleware/https_redirect.py +54 -0
  262. nyxa/middleware/phase.py +222 -0
  263. nyxa/middleware/pipeline.py +264 -0
  264. nyxa/middleware/registry.py +75 -0
  265. nyxa/middleware/trusted_host.py +71 -0
  266. nyxa/monitoring/__init__.py +15 -0
  267. nyxa/monitoring/alerts.py +173 -0
  268. nyxa/monitoring/errors.py +79 -0
  269. nyxa/openapi.py +243 -0
  270. nyxa/playground.py +334 -0
  271. nyxa/playground_actions.py +228 -0
  272. nyxa/playground_terminal.py +324 -0
  273. nyxa/plugins.py +5 -0
  274. nyxa/plugins_catalog.py +182 -0
  275. nyxa/process.py +1351 -0
  276. nyxa/providers/__init__.py +24 -0
  277. nyxa/providers/base.py +440 -0
  278. nyxa/providers/core.py +392 -0
  279. nyxa/providers/database.py +88 -0
  280. nyxa/providers/queue.py +148 -0
  281. nyxa/providers/schedule.py +70 -0
  282. nyxa/providers/workflows.py +75 -0
  283. nyxa/py.typed +0 -0
  284. nyxa/pytest_plugin.py +55 -0
  285. nyxa/queue/__init__.py +118 -0
  286. nyxa/queue/driver.py +528 -0
  287. nyxa/queue/drivers/__init__.py +8 -0
  288. nyxa/queue/drivers/memory.py +381 -0
  289. nyxa/queue/drivers/sync.py +128 -0
  290. nyxa/queue/events.py +293 -0
  291. nyxa/queue/job.py +622 -0
  292. nyxa/queue/listener.py +95 -0
  293. nyxa/queue/manager.py +757 -0
  294. nyxa/queue/middleware.py +81 -0
  295. nyxa/queue/provider.py +7 -0
  296. nyxa/queue/stores/__init__.py +17 -0
  297. nyxa/queue/stores/db.py +320 -0
  298. nyxa/queue/testing.py +186 -0
  299. nyxa/queue/worker.py +547 -0
  300. nyxa/routing/__init__.py +44 -0
  301. nyxa/routing/ambient.py +930 -0
  302. nyxa/routing/compiler.py +188 -0
  303. nyxa/routing/plan.py +1491 -0
  304. nyxa/routing/refs.py +115 -0
  305. nyxa/routing/route.py +958 -0
  306. nyxa/routing/router.py +1494 -0
  307. nyxa/routing/static.py +122 -0
  308. nyxa/routing/tree.py +347 -0
  309. nyxa/rsgi.py +13 -0
  310. nyxa/scheduling/__init__.py +49 -0
  311. nyxa/scheduling/cron.py +162 -0
  312. nyxa/scheduling/runner.py +296 -0
  313. nyxa/scheduling/schedule.py +618 -0
  314. nyxa/scheduling/store.py +221 -0
  315. nyxa/security.py +332 -0
  316. nyxa/server.py +259 -0
  317. nyxa/services.py +111 -0
  318. nyxa/testing/__init__.py +876 -0
  319. nyxa/testing/browser.py +172 -0
  320. nyxa/testing/jobs.py +209 -0
  321. nyxa/types.py +252 -0
  322. nyxa/upgrade/__init__.py +1 -0
  323. nyxa/upgrade/codemods.py +190 -0
  324. nyxa/warmup.py +27 -0
  325. nyxa/workflows/__init__.py +53 -0
  326. nyxa/workflows/events.py +72 -0
  327. nyxa/workflows/executor.py +353 -0
  328. nyxa/workflows/manager.py +182 -0
  329. nyxa/workflows/store.py +240 -0
  330. nyxa/workflows/workflow.py +211 -0
  331. nyxa/wsgi.py +230 -0
  332. nyxa-0.0.1.dist-info/METADATA +317 -0
  333. nyxa-0.0.1.dist-info/RECORD +336 -0
  334. nyxa-0.0.1.dist-info/WHEEL +4 -0
  335. nyxa-0.0.1.dist-info/entry_points.txt +6 -0
  336. nyxa-0.0.1.dist-info/licenses/LICENSE +21 -0
nyxa/__init__.py ADDED
@@ -0,0 +1,296 @@
1
+ """Nyxa — a standalone backend framework for Python."""
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ if TYPE_CHECKING:
6
+ # Declared for static analyzers; the real bindings resolve lazily via
7
+ # ``__getattr__`` below so ``import nyxa`` stays near-free.
8
+ from nyxa.command import Command
9
+ from nyxa.config.config import define_config
10
+ from nyxa.config.env import Env
11
+ from nyxa.context import Context
12
+ from nyxa.controller import Controller, Middleware
13
+ from nyxa.core.application import Application
14
+ from nyxa.core.container import (
15
+ CircularDependencyError,
16
+ Container,
17
+ ContainerError,
18
+ Inject,
19
+ Provider,
20
+ ResolutionError,
21
+ Scope,
22
+ )
23
+ from nyxa.db.collection import Collection
24
+ from nyxa.db.factory import Factory
25
+ from nyxa.db.manager import DB, Schema
26
+ from nyxa.db.migrations import Migration
27
+ from nyxa.db.model import Model
28
+ from nyxa.db.seeder import Seeder
29
+ from nyxa.db.traits import SoftDeletes
30
+ from nyxa.errors import NyxaError
31
+ from nyxa.events import Event, EventEmitter, Listener
32
+ from nyxa.exceptions import ExceptionHandler, HttpExceptionHandler
33
+ from nyxa.http.context import HttpContext, get_request, use
34
+ from nyxa.http.exceptions import (
35
+ BadRequestException,
36
+ ConflictException,
37
+ ForbiddenException,
38
+ HttpException,
39
+ InternalServerErrorException,
40
+ MethodNotAllowedException,
41
+ ModelNotFound,
42
+ NotFoundException,
43
+ ServiceUnavailableException,
44
+ TooManyRequestsException,
45
+ UnauthorizedException,
46
+ ValidationException,
47
+ abort,
48
+ )
49
+ from nyxa.http.params import Body, Cookie, Files, Form, Header, Ip, Path, Query
50
+ from nyxa.http.request import Request
51
+ from nyxa.http.response import Response, ResponseBuilder, use_response
52
+ from nyxa.http.streaming import sse_event, sse_stream
53
+ from nyxa.http.websocket import Ws, WsClosed
54
+ from nyxa.middleware import MiddlewareRegistry
55
+ from nyxa.process import Process
56
+ from nyxa.providers import ServiceProvider
57
+ from nyxa.routing import Route, RouteError, Router
58
+ from nyxa.routing.ambient import router
59
+ from nyxa.testing import TestClient
60
+
61
+
62
+ def _package_version() -> str:
63
+ """Return the installed ``nyxa`` distribution version.
64
+
65
+ Source of truth is ``packages/nyxa/pyproject.toml`` (stamped by
66
+ ``.github/sync_version.py`` on release). Falls back when the package
67
+ metadata is not on ``sys.path`` yet (raw source tree).
68
+ """
69
+ from importlib.metadata import PackageNotFoundError, version
70
+
71
+ try:
72
+ return version("nyxa")
73
+ except PackageNotFoundError:
74
+ from pathlib import Path
75
+ from tomllib import loads
76
+
77
+ try:
78
+ manifest = loads((Path(__file__).resolve().parents[2] / "pyproject.toml").read_text())
79
+ return str(manifest["project"]["version"])
80
+ except (KeyError, OSError):
81
+ return "0.0.0+local"
82
+
83
+
84
+ __version__ = _package_version()
85
+
86
+
87
+ __all__ = [
88
+ "DB",
89
+ "Application",
90
+ "BadRequestException",
91
+ "Body",
92
+ "CircularDependencyError",
93
+ "Collection",
94
+ "Command",
95
+ "ConflictException",
96
+ "Container",
97
+ "ContainerError",
98
+ "Context",
99
+ "Controller",
100
+ "Cookie",
101
+ "Env",
102
+ "Event",
103
+ "EventEmitter",
104
+ "ExceptionHandler",
105
+ "Factory",
106
+ "Files",
107
+ "ForbiddenException",
108
+ "Form",
109
+ "Header",
110
+ "HttpContext",
111
+ "HttpException",
112
+ "HttpExceptionHandler",
113
+ "Inject",
114
+ "InternalServerErrorException",
115
+ "Ip",
116
+ "Listener",
117
+ "MethodNotAllowedException",
118
+ "Middleware",
119
+ "MiddlewareRegistry",
120
+ "Migration",
121
+ "Model",
122
+ "ModelNotFound",
123
+ "NotFoundException",
124
+ "NyxaError",
125
+ "Path",
126
+ "Process",
127
+ "Provider",
128
+ "Query",
129
+ "Request",
130
+ "ResolutionError",
131
+ "Response",
132
+ "ResponseBuilder",
133
+ "Route",
134
+ "RouteError",
135
+ "Router",
136
+ "Schema",
137
+ "Scope",
138
+ "Seeder",
139
+ "ServiceProvider",
140
+ "ServiceUnavailableException",
141
+ "SoftDeletes",
142
+ "TestClient",
143
+ "TooManyRequestsException",
144
+ "UnauthorizedException",
145
+ "ValidationException",
146
+ "Ws",
147
+ "WsClosed",
148
+ "__version__",
149
+ "abort",
150
+ "define_config",
151
+ "get_request",
152
+ "router",
153
+ "sse_event",
154
+ "sse_stream",
155
+ "use",
156
+ "use_response",
157
+ ]
158
+
159
+ # Every public name → the module that defines it. ``import nyxa`` pays for
160
+ # nothing but this module object; a name imports its backing module on first
161
+ # access and caches the result in ``globals()``.
162
+ _LAZY = {
163
+ "Application": "nyxa.core.application",
164
+ "Command": "nyxa.command",
165
+ "Context": "nyxa.context",
166
+ "define_config": "nyxa.config.config",
167
+ "CircularDependencyError": "nyxa.core.container",
168
+ "Container": "nyxa.core.container",
169
+ "ContainerError": "nyxa.core.container",
170
+ "Inject": "nyxa.core.container",
171
+ "Provider": "nyxa.core.container",
172
+ "ResolutionError": "nyxa.core.container",
173
+ "Scope": "nyxa.core.container",
174
+ "Controller": "nyxa.controller",
175
+ "Middleware": "nyxa.controller",
176
+ "Env": "nyxa.config.env",
177
+ "Event": "nyxa.events",
178
+ "EventEmitter": "nyxa.events",
179
+ "Listener": "nyxa.events",
180
+ "NyxaError": "nyxa.errors",
181
+ "ExceptionHandler": "nyxa.exceptions",
182
+ "HttpExceptionHandler": "nyxa.exceptions",
183
+ "BadRequestException": "nyxa.http.exceptions",
184
+ "ConflictException": "nyxa.http.exceptions",
185
+ "ForbiddenException": "nyxa.http.exceptions",
186
+ "HttpException": "nyxa.http.exceptions",
187
+ "InternalServerErrorException": "nyxa.http.exceptions",
188
+ "MethodNotAllowedException": "nyxa.http.exceptions",
189
+ "ModelNotFound": "nyxa.http.exceptions",
190
+ "NotFoundException": "nyxa.http.exceptions",
191
+ "ServiceUnavailableException": "nyxa.http.exceptions",
192
+ "TooManyRequestsException": "nyxa.http.exceptions",
193
+ "UnauthorizedException": "nyxa.http.exceptions",
194
+ "ValidationException": "nyxa.http.exceptions",
195
+ "abort": "nyxa.http.exceptions",
196
+ "Body": "nyxa.http.params",
197
+ "Cookie": "nyxa.http.params",
198
+ "Files": "nyxa.http.params",
199
+ "Form": "nyxa.http.params",
200
+ "Header": "nyxa.http.params",
201
+ "Ip": "nyxa.http.params",
202
+ "Path": "nyxa.http.params",
203
+ "Query": "nyxa.http.params",
204
+ "HttpContext": "nyxa.http.context",
205
+ "get_request": "nyxa.http.context",
206
+ "use": "nyxa.http.context",
207
+ "Request": "nyxa.http.request",
208
+ "Response": "nyxa.http.response",
209
+ "ResponseBuilder": "nyxa.http.response",
210
+ "use_response": "nyxa.http.response",
211
+ "sse_event": "nyxa.http.streaming",
212
+ "sse_stream": "nyxa.http.streaming",
213
+ "Ws": "nyxa.http.websocket",
214
+ "WsClosed": "nyxa.http.websocket",
215
+ "MiddlewareRegistry": "nyxa.middleware",
216
+ "Process": "nyxa.process",
217
+ "ServiceProvider": "nyxa.providers",
218
+ "Route": "nyxa.routing",
219
+ "RouteError": "nyxa.routing",
220
+ "Router": "nyxa.routing",
221
+ "router": "nyxa.routing.ambient",
222
+ "TestClient": "nyxa.testing",
223
+ "Collection": "nyxa.db.collection",
224
+ "DB": "nyxa.db.manager",
225
+ "Schema": "nyxa.db.manager",
226
+ "Factory": "nyxa.db.factory",
227
+ "Migration": "nyxa.db.migrations",
228
+ "Model": "nyxa.db.model",
229
+ "Seeder": "nyxa.db.seeder",
230
+ "SoftDeletes": "nyxa.db.traits",
231
+ }
232
+
233
+ # Submodules reachable as attributes (``nyxa.db`` without an explicit
234
+ # ``import nyxa.db``) — resolved lazily the same way.
235
+ _MODULES = frozenset(
236
+ {
237
+ "adapters",
238
+ "application",
239
+ "asgi",
240
+ "bridge",
241
+ "build",
242
+ "cli",
243
+ "command",
244
+ "config",
245
+ "console",
246
+ "container",
247
+ "context",
248
+ "contracts",
249
+ "core",
250
+ "controller",
251
+ "db",
252
+ "discovery",
253
+ "env",
254
+ "errors",
255
+ "events",
256
+ "exceptions",
257
+ "helpers",
258
+ "http",
259
+ "ignitor",
260
+ "logging",
261
+ "manifest",
262
+ "middleware",
263
+ "openapi",
264
+ "plugins",
265
+ "process",
266
+ "providers",
267
+ "pytest_plugin",
268
+ "queue",
269
+ "routing",
270
+ "rsgi",
271
+ "scheduling",
272
+ "security",
273
+ "server",
274
+ "testing",
275
+ "types",
276
+ "workflows",
277
+ "wsgi",
278
+ }
279
+ )
280
+
281
+
282
+ # Any required — PEP 562 lazy re-export: the resolved type is unknowable at the
283
+ # signature level (dynamic-attribute carve-out).
284
+ def __getattr__(name: str) -> Any: # noqa: ANN401 — see comment above
285
+ """Lazy public surface — names and submodules import on first access."""
286
+ import importlib
287
+
288
+ module = _LAZY.get(name)
289
+ if module is not None:
290
+ value = getattr(importlib.import_module(module), name)
291
+ elif name in _MODULES:
292
+ value = importlib.import_module(f"nyxa.{name}")
293
+ else:
294
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
295
+ globals()[name] = value
296
+ return value
nyxa/__main__.py ADDED
@@ -0,0 +1,6 @@
1
+ """``python -m nyxa`` — delegates to the console entry point."""
2
+
3
+ from nyxa.cli import entrypoint
4
+
5
+ if __name__ == "__main__":
6
+ entrypoint()
nyxa/_awaitable.py ADDED
@@ -0,0 +1,46 @@
1
+ """Fast awaitable probe for hot paths.
2
+
3
+ ``inspect.isawaitable`` falls through to an ABC ``isinstance`` for every value
4
+ that is not a coroutine, which dominates the cost of the common case (a
5
+ handler returned a plain model, dict or ``None``). Awaitability is a property
6
+ of the *type* (the one exception, generator-based coroutines, is excluded), so
7
+ negative answers are memoized per type.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import inspect
13
+ from collections.abc import Awaitable
14
+ from types import CoroutineType, GeneratorType
15
+ from typing import TypeGuard
16
+
17
+ _NOT_AWAITABLE: set[type] = {type(None), bool, int, float, str, bytes, dict, list, tuple}
18
+ _NOT_AWAITABLE_MAX = 4096
19
+
20
+
21
+ def is_awaitable(obj: object) -> TypeGuard[Awaitable[object]]:
22
+ """Whether ``await obj`` is valid — same answer as :func:`inspect.isawaitable`.
23
+
24
+ Args:
25
+ obj: Any handler/listener/hook result.
26
+
27
+ Returns:
28
+ ``True`` for coroutines, futures and other awaitables.
29
+
30
+ Example:
31
+ >>> is_awaitable(1), is_awaitable(None)
32
+ (False, False)
33
+ """
34
+ kind = type(obj)
35
+ if kind is CoroutineType:
36
+ return True
37
+ if kind in _NOT_AWAITABLE:
38
+ return False
39
+ if inspect.isawaitable(obj):
40
+ return True
41
+ if kind is not GeneratorType and len(_NOT_AWAITABLE) < _NOT_AWAITABLE_MAX:
42
+ _NOT_AWAITABLE.add(kind)
43
+ return False
44
+
45
+
46
+ __all__ = ["is_awaitable"]
nyxa/_current.py ADDED
@@ -0,0 +1,44 @@
1
+ """Process-local reference to the most recently created Application.
2
+
3
+ Lets module-level helpers that have no app handle — bare
4
+ ``Job.dispatch(...)`` and the ``DB``/``Schema`` facades are the canonical
5
+ cases — reach the lazily bound managers without importing feature stacks
6
+ at boot. ``tick()`` orders app construction against facade bindings so
7
+ "most recently bound wins" keeps working across lazy creation.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import weakref
13
+ from typing import TYPE_CHECKING
14
+
15
+ if TYPE_CHECKING:
16
+ from nyxa.core.application import Application
17
+
18
+ _app: weakref.ReferenceType[Application] | None = None
19
+ _app_seq = 0
20
+ _tick = 0
21
+
22
+
23
+ def tick() -> int:
24
+ """Monotonic sequence — bump on app creation and facade binds."""
25
+ global _tick
26
+ _tick += 1
27
+ return _tick
28
+
29
+
30
+ def set_app(app: Application) -> None:
31
+ """Record ``app`` as the current application."""
32
+ global _app, _app_seq
33
+ _app = weakref.ref(app)
34
+ _app_seq = tick()
35
+
36
+
37
+ def get_app() -> Application | None:
38
+ """The most recently created live application, or ``None``."""
39
+ return _app() if _app is not None else None
40
+
41
+
42
+ def app_seq() -> int:
43
+ """The sequence at which the current app was created."""
44
+ return _app_seq
nyxa/_speedups.py ADDED
@@ -0,0 +1,170 @@
1
+ """Bundled native accelerators behind pure-Python references.
2
+
3
+ ``nyxa-speedups`` is a separate compiled distribution. Each helper here has a
4
+ Python reference implementation with identical results; the native version
5
+ handles the common inputs and returns ``None`` for anything else (non-ASCII,
6
+ quoted cookies, unusual header items), which falls back to the reference.
7
+ Set ``NYXA_NO_SPEEDUPS=1`` to force the Python versions.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import importlib
13
+ import os
14
+ from collections.abc import Callable, Iterable, Mapping
15
+ from http.cookies import SimpleCookie
16
+ from types import ModuleType
17
+ from urllib.parse import parse_qsl
18
+
19
+ from nyxa.types import FormValue, NativeHeaderIndex, NativeMatcher
20
+
21
+
22
+ def _load() -> ModuleType | None:
23
+ if os.environ.get("NYXA_NO_SPEEDUPS"):
24
+ return None
25
+ try:
26
+ return importlib.import_module("nyxa_speedups")
27
+ except ImportError:
28
+ return None
29
+
30
+
31
+ native: ModuleType | None = _load()
32
+ """The ``nyxa_speedups`` module, or ``None`` when absent or disabled."""
33
+
34
+
35
+ def py_parse_query(qs: str) -> dict[str, str]:
36
+ """Reference: query-string parameters, last value wins, blanks kept."""
37
+ return dict(parse_qsl(qs, keep_blank_values=True))
38
+
39
+
40
+ def py_parse_cookies(header: str) -> dict[str, str]:
41
+ """Reference: ``Cookie`` header as ``SimpleCookie`` reads it."""
42
+ jar = SimpleCookie(header)
43
+ return {k: morsel.value for k, morsel in jar.items()}
44
+
45
+
46
+ def py_parse_query_multi(qs: str) -> dict[str, str | list[str]]:
47
+ """Reference: ``parse_qsl`` with repeated keys collapsed into lists."""
48
+ out: dict[str, str | list[str]] = {}
49
+ for k, v in parse_qsl(qs, keep_blank_values=True):
50
+ if k in out:
51
+ existing = out[k]
52
+ if isinstance(existing, list):
53
+ existing.append(v)
54
+ else:
55
+ out[k] = [existing, v]
56
+ else:
57
+ out[k] = v
58
+ return out
59
+
60
+
61
+ def _with_fallback[T, R](fast: Callable[[T], R | None], reference: Callable[[T], R]) -> Callable[[T], R]:
62
+ """Wrap ``fast`` so a ``None`` result re-runs through ``reference``."""
63
+
64
+ def parse(value: T) -> R:
65
+ result = fast(value)
66
+ return result if result is not None else reference(value)
67
+
68
+ parse.__doc__ = reference.__doc__
69
+ return parse
70
+
71
+
72
+ if native is not None:
73
+ parse_query: Callable[[str], dict[str, str]] = _with_fallback(native.parse_query, py_parse_query)
74
+ parse_cookies: Callable[[str], dict[str, str]] = _with_fallback(native.parse_cookies, py_parse_cookies)
75
+ parse_query_multi: Callable[[str], dict[str, str | list[str]]] = _with_fallback(
76
+ native.parse_query_multi, py_parse_query_multi
77
+ )
78
+ else:
79
+ parse_query = py_parse_query
80
+ parse_cookies = py_parse_cookies
81
+ parse_query_multi = py_parse_query_multi
82
+
83
+ Matcher: type[NativeMatcher] | None = native.Matcher if native is not None else None
84
+ """Native route matcher class (see ``RouteTree``), or ``None``."""
85
+
86
+ scan_headers: Callable[[Iterable[tuple[bytes, bytes]]], tuple[bytes | None, bool] | None] | None = (
87
+ native.scan_headers if native is not None else None
88
+ )
89
+ """``(x-request-id, declares_body)`` over ASGI headers, ``None`` to fall back; or ``None``."""
90
+
91
+ encode_headers: Callable[[dict[str, str]], list[tuple[bytes, bytes]] | None] | None = (
92
+ native.encode_headers if native is not None else None
93
+ )
94
+ """ASGI response header list for ASCII headers, ``None`` to fall back; or ``None``."""
95
+
96
+ parse_multipart: (
97
+ Callable[
98
+ [bytes, bytes, int, int, int | None],
99
+ tuple[dict[str, FormValue], list[tuple[str, str, str, bytes]]] | None,
100
+ ]
101
+ | None
102
+ ) = getattr(native, "parse_multipart", None) if native is not None else None
103
+ """Multipart boundary scanner — ``(fields, file_parts)`` or ``None`` to fall back."""
104
+
105
+ header_index: Callable[[Iterable[tuple[bytes, bytes]]], NativeHeaderIndex | None] | None = (
106
+ getattr(native, "header_index", None) if native is not None else None
107
+ )
108
+ """Build a ``HeaderIndex`` over raw ASGI header pairs, ``None`` to fall back; or ``None``."""
109
+
110
+ flatten_headers: Callable[[dict[str, str | list[str]]], list[tuple[str, str]] | None] | None = (
111
+ getattr(native, "flatten_headers", None) if native is not None else None
112
+ )
113
+ """``header_items`` equivalent, ``None`` to fall back; or ``None``."""
114
+
115
+ normalize_headers: Callable[[dict[str, str | list[str]], dict[str, object]], tuple[()] | None] | None = (
116
+ getattr(native, "normalize_headers", None) if native is not None else None
117
+ )
118
+ """Default-header merge into a response's dict in place, ``None`` to fall back; or ``None``."""
119
+
120
+ native_sign_cookie: Callable[[str, str, bool], str] | None = (
121
+ getattr(native, "sign_cookie", None) if native is not None else None
122
+ )
123
+ """Fused ``<b64>.<hmac>`` signer, or ``None`` when the wheel is absent."""
124
+
125
+ native_verify_cookie: Callable[[str, str, float | None], str | None] | None = (
126
+ getattr(native, "verify_cookie", None) if native is not None else None
127
+ )
128
+ """Fused signed-cookie verify, ``None`` on invalid or unusual input; or ``None``."""
129
+
130
+ url_build: Callable[[str, Mapping[str, object], Mapping[str, str], Mapping[str, str]], str | None] | None = (
131
+ getattr(native, "url_build", None) if native is not None else None
132
+ )
133
+ """Route URL substitution + constraint checks, ``None`` to fall back; or ``None``."""
134
+
135
+ validate_plan: (
136
+ Callable[
137
+ [dict[str, list[tuple[int, list[str], int]]], dict[str, object]],
138
+ dict[str, dict[str, list[int]]] | None,
139
+ ]
140
+ | None
141
+ ) = getattr(native, "validate_plan", None) if native is not None else None
142
+ """Native evaluation of a compiled validation plan's pure rules; or ``None``."""
143
+
144
+ native_rule_ids: dict[str, int] = dict(getattr(native, "NATIVE_RULE_IDS", {})) if native is not None else {}
145
+ """rule name → plan id for the native-evaluable pure rules; empty when absent."""
146
+
147
+
148
+ def py_paginate_to_json(rows: list[dict[str, object]], meta: Mapping[str, object]) -> bytes:
149
+ """Reference: ``{data, meta}`` envelope via orjson (plain JSON scalars only)."""
150
+ import orjson
151
+
152
+ return orjson.dumps({"data": rows, "meta": dict(meta)})
153
+
154
+
155
+ def _native_paginate_to_json(rows: list[dict[str, object]], meta: Mapping[str, object]) -> bytes | None:
156
+ """Call the Rust encoder; ``None`` means fall back to Python."""
157
+ if native is None:
158
+ return None
159
+ fn = getattr(native, "paginate_to_json", None)
160
+ if fn is None:
161
+ return None
162
+ return fn(rows, dict(meta))
163
+
164
+
165
+ paginate_to_json: Callable[[list[dict[str, object]], Mapping[str, object]], bytes] = (
166
+ (lambda rows, meta: _native_paginate_to_json(rows, meta) or py_paginate_to_json(rows, meta))
167
+ if native is not None
168
+ else py_paginate_to_json
169
+ )
170
+ """``{data, meta}`` JSON bytes — native when installed, else orjson."""
@@ -0,0 +1,72 @@
1
+ """Deployment adapters — the platform contract and the built-ins."""
2
+
3
+ from typing import TYPE_CHECKING, Any
4
+
5
+ if TYPE_CHECKING:
6
+ from nyxa.adapters.asgi import AsgiAdapter
7
+ from nyxa.adapters.base import (
8
+ Adapter,
9
+ AdapterError,
10
+ Capabilities,
11
+ collect_adapters,
12
+ required_capabilities,
13
+ spawn,
14
+ )
15
+ from nyxa.adapters.cloudrun import CloudRunAdapter
16
+ from nyxa.adapters.container import ContainerAdapter
17
+ from nyxa.adapters.docker import DockerAdapter
18
+ from nyxa.adapters.fly import FlyAdapter
19
+ from nyxa.adapters.granian import GranianAdapter
20
+ from nyxa.adapters.native import NativeAdapter
21
+ from nyxa.adapters.railway import RailwayAdapter
22
+ from nyxa.adapters.render import RenderAdapter
23
+
24
+ __all__ = [
25
+ "Adapter",
26
+ "AdapterError",
27
+ "AsgiAdapter",
28
+ "Capabilities",
29
+ "CloudRunAdapter",
30
+ "ContainerAdapter",
31
+ "DockerAdapter",
32
+ "FlyAdapter",
33
+ "GranianAdapter",
34
+ "NativeAdapter",
35
+ "RailwayAdapter",
36
+ "RenderAdapter",
37
+ "collect_adapters",
38
+ "required_capabilities",
39
+ "spawn",
40
+ ]
41
+
42
+ _LAZY = {
43
+ "AsgiAdapter": "nyxa.adapters.asgi",
44
+ "Adapter": "nyxa.adapters.base",
45
+ "AdapterError": "nyxa.adapters.base",
46
+ "Capabilities": "nyxa.adapters.base",
47
+ "CloudRunAdapter": "nyxa.adapters.cloudrun",
48
+ "ContainerAdapter": "nyxa.adapters.container",
49
+ "collect_adapters": "nyxa.adapters.base",
50
+ "required_capabilities": "nyxa.adapters.base",
51
+ "spawn": "nyxa.adapters.base",
52
+ "DockerAdapter": "nyxa.adapters.docker",
53
+ "FlyAdapter": "nyxa.adapters.fly",
54
+ "GranianAdapter": "nyxa.adapters.granian",
55
+ "NativeAdapter": "nyxa.adapters.native",
56
+ "RailwayAdapter": "nyxa.adapters.railway",
57
+ "RenderAdapter": "nyxa.adapters.render",
58
+ }
59
+
60
+
61
+ # Any required — PEP 562 lazy re-export: the resolved type is unknowable at the
62
+ # signature level (dynamic-attribute carve-out).
63
+ def __getattr__(name: str) -> Any: # noqa: ANN401 — see comment above
64
+ """Lazy attribute exports — keeps ``import nyxa.adapters`` cheap."""
65
+ module = _LAZY.get(name)
66
+ if module is None:
67
+ raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
68
+ import importlib
69
+
70
+ value = getattr(importlib.import_module(module), name)
71
+ globals()[name] = value
72
+ return value