omlish 0.0.0.dev423__py3-none-any.whl → 0.0.0.dev484__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.

Potentially problematic release.


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

Files changed (464) hide show
  1. omlish/{.manifests.json → .omlish-manifests.json} +12 -0
  2. omlish/__about__.py +21 -18
  3. omlish/argparse/all.py +17 -9
  4. omlish/argparse/cli.py +16 -3
  5. omlish/argparse/utils.py +21 -0
  6. omlish/asyncs/all.py +0 -13
  7. omlish/asyncs/asyncio/rlock.py +110 -0
  8. omlish/asyncs/asyncio/subprocesses.py +2 -2
  9. omlish/asyncs/asyncio/sync.py +43 -0
  10. omlish/asyncs/asyncio/utils.py +2 -0
  11. omlish/asyncs/ioproxy/proxy.py +1 -1
  12. omlish/asyncs/sync.py +25 -0
  13. omlish/bootstrap/_marshal.py +1 -1
  14. omlish/bootstrap/diag.py +12 -21
  15. omlish/bootstrap/main.py +2 -5
  16. omlish/bootstrap/sys.py +27 -28
  17. omlish/c3.py +4 -1
  18. omlish/cexts/include/omlish/omlish.hh +1 -0
  19. omlish/collections/__init__.py +13 -1
  20. omlish/collections/attrregistry.py +210 -0
  21. omlish/collections/cache/impl.py +3 -2
  22. omlish/collections/identity.py +1 -0
  23. omlish/collections/mappings.py +28 -0
  24. omlish/collections/trie.py +5 -1
  25. omlish/collections/utils.py +77 -0
  26. omlish/concurrent/__init__.py +0 -11
  27. omlish/concurrent/all.py +18 -0
  28. omlish/concurrent/futures.py +25 -0
  29. omlish/concurrent/threadlets.py +1 -1
  30. omlish/configs/processing/flattening.py +1 -1
  31. omlish/configs/processing/merging.py +8 -6
  32. omlish/configs/types.py +1 -1
  33. omlish/daemons/__init__.py +70 -0
  34. omlish/daemons/daemon.py +2 -2
  35. omlish/daemons/launching.py +2 -2
  36. omlish/daemons/reparent.py +2 -3
  37. omlish/daemons/spawning.py +2 -3
  38. omlish/dataclasses/__init__.py +5 -5
  39. omlish/dataclasses/errors.py +1 -1
  40. omlish/dataclasses/impl/api/classes/decorator.py +3 -0
  41. omlish/dataclasses/impl/api/classes/make.py +4 -1
  42. omlish/dataclasses/impl/concerns/doc.py +1 -1
  43. omlish/dataclasses/impl/concerns/repr.py +15 -2
  44. omlish/dataclasses/impl/configs.py +97 -36
  45. omlish/dataclasses/impl/generation/compilation.py +21 -19
  46. omlish/dataclasses/impl/generation/globals.py +1 -0
  47. omlish/dataclasses/impl/generation/ops.py +1 -0
  48. omlish/dataclasses/impl/generation/processor.py +105 -24
  49. omlish/dataclasses/impl/processing/base.py +8 -0
  50. omlish/dataclasses/impl/processing/driving.py +8 -8
  51. omlish/dataclasses/specs.py +34 -2
  52. omlish/dataclasses/tools/as_.py +0 -12
  53. omlish/dataclasses/tools/modifiers.py +5 -0
  54. omlish/dataclasses/tools/static.py +1 -1
  55. omlish/diag/_pycharm/runhack.py +1 -1
  56. omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
  57. omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
  58. omlish/diag/{ps.py → cmds/ps.py} +6 -6
  59. omlish/diag/procfs.py +4 -4
  60. omlish/diag/pycharm.py +16 -2
  61. omlish/diag/pydevd.py +58 -40
  62. omlish/diag/replserver/console.py +3 -3
  63. omlish/diag/replserver/server.py +2 -2
  64. omlish/dispatch/__init__.py +18 -12
  65. omlish/dispatch/methods.py +50 -140
  66. omlish/dom/rendering.py +1 -1
  67. omlish/formats/dotenv.py +8 -8
  68. omlish/formats/json/stream/__init__.py +18 -3
  69. omlish/formats/json/stream/building.py +2 -2
  70. omlish/formats/json/stream/lexing.py +401 -67
  71. omlish/formats/json/stream/parsing.py +32 -10
  72. omlish/formats/json/stream/rendering.py +6 -6
  73. omlish/formats/json/stream/utils.py +132 -30
  74. omlish/formats/json5/literals.py +7 -4
  75. omlish/formats/json5/parsing.py +33 -79
  76. omlish/formats/json5/stream.py +77 -0
  77. omlish/formats/logfmt.py +8 -2
  78. omlish/funcs/genmachine.py +2 -2
  79. omlish/funcs/guard.py +225 -0
  80. omlish/graphs/dot/rendering.py +1 -1
  81. omlish/http/all.py +122 -53
  82. omlish/http/asgi.py +2 -2
  83. omlish/http/clients/__init__.py +0 -34
  84. omlish/http/clients/asyncs.py +153 -0
  85. omlish/http/clients/base.py +63 -122
  86. omlish/http/clients/coro/sync.py +171 -0
  87. omlish/http/clients/default.py +209 -30
  88. omlish/http/clients/executor.py +56 -0
  89. omlish/http/clients/httpx.py +78 -13
  90. omlish/http/clients/middleware.py +181 -0
  91. omlish/http/clients/sync.py +151 -0
  92. omlish/http/clients/syncasync.py +49 -0
  93. omlish/http/clients/urllib.py +8 -5
  94. omlish/http/coro/client/{client.py → connection.py} +43 -37
  95. omlish/http/coro/client/headers.py +5 -5
  96. omlish/http/coro/client/response.py +37 -38
  97. omlish/http/coro/client/status.py +4 -4
  98. omlish/http/coro/{client/io.py → io.py} +19 -2
  99. omlish/http/coro/server/fdio.py +10 -9
  100. omlish/http/coro/server/server.py +14 -41
  101. omlish/http/coro/server/sockets.py +7 -6
  102. omlish/http/flasky/__init__.py +40 -0
  103. omlish/http/flasky/_compat.py +2 -0
  104. omlish/http/flasky/api.py +82 -0
  105. omlish/http/flasky/app.py +203 -0
  106. omlish/http/flasky/cvs.py +59 -0
  107. omlish/http/flasky/requests.py +20 -0
  108. omlish/http/flasky/responses.py +23 -0
  109. omlish/http/flasky/routes.py +23 -0
  110. omlish/http/flasky/types.py +15 -0
  111. omlish/http/handlers.py +3 -2
  112. omlish/http/headers.py +69 -35
  113. omlish/http/sse.py +1 -1
  114. omlish/http/urls.py +67 -0
  115. omlish/inject/__init__.py +173 -126
  116. omlish/inject/_dataclasses.py +4986 -0
  117. omlish/inject/binder.py +10 -49
  118. omlish/inject/elements.py +27 -0
  119. omlish/inject/{utils.py → helpers/constfn.py} +3 -3
  120. omlish/inject/{tags.py → helpers/id.py} +2 -2
  121. omlish/inject/helpers/multis.py +143 -0
  122. omlish/inject/helpers/wrappers.py +54 -0
  123. omlish/inject/impl/elements.py +52 -22
  124. omlish/inject/impl/injector.py +76 -49
  125. omlish/inject/impl/inspect.py +11 -1
  126. omlish/inject/impl/maysync.py +43 -0
  127. omlish/inject/impl/multis.py +10 -7
  128. omlish/inject/impl/privates.py +8 -8
  129. omlish/inject/impl/providers.py +23 -34
  130. omlish/inject/impl/providersmap.py +43 -0
  131. omlish/inject/impl/proxy.py +0 -2
  132. omlish/inject/impl/scopes.py +19 -23
  133. omlish/inject/impl/sync.py +41 -0
  134. omlish/inject/injector.py +37 -8
  135. omlish/inject/inspect.py +35 -0
  136. omlish/inject/listeners.py +4 -4
  137. omlish/inject/managed.py +54 -18
  138. omlish/inject/maysync.py +27 -0
  139. omlish/inject/multis.py +8 -0
  140. omlish/inject/overrides.py +3 -3
  141. omlish/inject/privates.py +6 -0
  142. omlish/inject/providers.py +8 -1
  143. omlish/inject/scopes.py +40 -12
  144. omlish/inject/sync.py +49 -0
  145. omlish/io/buffers.py +119 -1
  146. omlish/io/readers.py +29 -0
  147. omlish/iterators/__init__.py +28 -20
  148. omlish/iterators/transforms.py +204 -0
  149. omlish/lang/__init__.py +240 -129
  150. omlish/lang/_asyncs.cc +186 -0
  151. omlish/lang/asyncs.py +67 -43
  152. omlish/lang/{attrs.py → attrstorage.py} +15 -15
  153. omlish/lang/cached/property.py +2 -2
  154. omlish/lang/casing.py +11 -0
  155. omlish/lang/classes/bindable.py +2 -3
  156. omlish/lang/classes/restrict.py +8 -0
  157. omlish/lang/classes/simple.py +26 -4
  158. omlish/lang/collections.py +1 -1
  159. omlish/lang/contextmanagers.py +59 -9
  160. omlish/lang/functions.py +31 -33
  161. omlish/lang/imports/_capture.cc +103 -0
  162. omlish/lang/imports/capture.py +902 -0
  163. omlish/lang/imports/lazy.py +0 -25
  164. omlish/lang/imports/proxy.py +559 -0
  165. omlish/lang/iterables.py +2 -2
  166. omlish/lang/lazyglobals.py +49 -14
  167. omlish/lang/maybes.py +2 -1
  168. omlish/lang/maysync.py +2 -2
  169. omlish/lang/params.py +17 -0
  170. omlish/lang/recursion.py +0 -1
  171. omlish/lang/resources.py +1 -1
  172. omlish/lang/sequences.py +124 -0
  173. omlish/lifecycles/contextmanagers.py +1 -2
  174. omlish/lifecycles/controller.py +1 -2
  175. omlish/lite/abstract.py +54 -24
  176. omlish/lite/asyncs.py +146 -0
  177. omlish/lite/attrops.py +415 -0
  178. omlish/lite/cached.py +57 -1
  179. omlish/lite/contextmanagers.py +4 -4
  180. omlish/lite/dataclasses.py +55 -0
  181. omlish/lite/inject.py +5 -4
  182. omlish/lite/marshal.py +1 -0
  183. omlish/lite/maybes.py +10 -2
  184. omlish/lite/maysync.py +22 -5
  185. omlish/lite/pycharm.py +1 -1
  186. omlish/lite/strings.py +0 -7
  187. omlish/lite/timing.py +6 -3
  188. omlish/lite/typing.py +6 -0
  189. omlish/logs/_amalg.py +8 -0
  190. omlish/logs/all.py +59 -31
  191. omlish/logs/base.py +204 -0
  192. omlish/logs/contexts.py +171 -0
  193. omlish/logs/formatters.py +13 -0
  194. omlish/logs/infos.py +377 -0
  195. omlish/logs/levels.py +97 -0
  196. omlish/logs/modules.py +13 -0
  197. omlish/logs/protocols.py +32 -0
  198. omlish/logs/standard.py +20 -15
  199. omlish/logs/std/configs.py +29 -0
  200. omlish/logs/{filters.py → std/filters.py} +1 -1
  201. omlish/logs/std/formatters.py +25 -0
  202. omlish/logs/std/handlers.py +19 -0
  203. omlish/logs/{json.py → std/json.py} +2 -2
  204. omlish/logs/std/loggers.py +48 -0
  205. omlish/logs/{proxy.py → std/proxy.py} +3 -3
  206. omlish/logs/std/records.py +671 -0
  207. omlish/logs/typed/bindings.py +108 -37
  208. omlish/logs/typed/types.py +17 -1
  209. omlish/logs/typed/values.py +2 -2
  210. omlish/logs/utils.py +60 -4
  211. omlish/logs/warnings.py +8 -0
  212. omlish/manifests/loading.py +8 -1
  213. omlish/marshal/__init__.py +54 -22
  214. omlish/marshal/_dataclasses.py +2774 -0
  215. omlish/marshal/base/configs.py +12 -0
  216. omlish/marshal/base/contexts.py +36 -21
  217. omlish/marshal/base/funcs.py +8 -11
  218. omlish/marshal/base/options.py +8 -0
  219. omlish/marshal/base/registries.py +146 -44
  220. omlish/marshal/base/types.py +40 -16
  221. omlish/marshal/composite/iterables.py +33 -20
  222. omlish/marshal/composite/literals.py +20 -18
  223. omlish/marshal/composite/mappings.py +36 -23
  224. omlish/marshal/composite/maybes.py +29 -19
  225. omlish/marshal/composite/newtypes.py +16 -16
  226. omlish/marshal/composite/optionals.py +14 -14
  227. omlish/marshal/composite/special.py +15 -15
  228. omlish/marshal/composite/unions/literals.py +93 -0
  229. omlish/marshal/composite/unions/primitives.py +103 -0
  230. omlish/marshal/factories/invalidate.py +18 -68
  231. omlish/marshal/factories/method.py +26 -0
  232. omlish/marshal/factories/moduleimport/factories.py +22 -65
  233. omlish/marshal/factories/multi.py +13 -25
  234. omlish/marshal/factories/recursive.py +42 -56
  235. omlish/marshal/factories/typecache.py +29 -74
  236. omlish/marshal/factories/typemap.py +42 -43
  237. omlish/marshal/objects/dataclasses.py +129 -106
  238. omlish/marshal/objects/marshal.py +18 -14
  239. omlish/marshal/objects/namedtuples.py +48 -42
  240. omlish/marshal/objects/unmarshal.py +19 -15
  241. omlish/marshal/polymorphism/marshal.py +9 -11
  242. omlish/marshal/polymorphism/metadata.py +16 -5
  243. omlish/marshal/polymorphism/standard.py +13 -1
  244. omlish/marshal/polymorphism/unions.py +15 -105
  245. omlish/marshal/polymorphism/unmarshal.py +9 -10
  246. omlish/marshal/singular/enums.py +14 -18
  247. omlish/marshal/standard.py +10 -6
  248. omlish/marshal/trivial/any.py +1 -1
  249. omlish/marshal/trivial/forbidden.py +21 -26
  250. omlish/math/fixed.py +2 -2
  251. omlish/metadata.py +23 -1
  252. omlish/os/atomics.py +2 -2
  253. omlish/os/forkhooks.py +4 -0
  254. omlish/os/journald.py +3 -3
  255. omlish/os/pidfiles/pinning.py +2 -2
  256. omlish/reflect/ops.py +9 -0
  257. omlish/reflect/types.py +44 -8
  258. omlish/secrets/marshal.py +1 -1
  259. omlish/secrets/secrets.py +6 -3
  260. omlish/sockets/addresses.py +1 -1
  261. omlish/sockets/server/handlers.py +2 -2
  262. omlish/sockets/server/server.py +4 -3
  263. omlish/sockets/server/ssl.py +2 -2
  264. omlish/specs/jmespath/__init__.py +12 -3
  265. omlish/specs/jmespath/_dataclasses.py +2893 -0
  266. omlish/specs/jmespath/ast.py +1 -1
  267. omlish/specs/jsonrpc/__init__.py +13 -0
  268. omlish/specs/jsonrpc/_marshal.py +32 -23
  269. omlish/specs/jsonrpc/conns.py +10 -7
  270. omlish/specs/jsonschema/_marshal.py +1 -1
  271. omlish/specs/jsonschema/keywords/__init__.py +7 -0
  272. omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
  273. omlish/specs/openapi/_marshal.py +31 -22
  274. omlish/sql/__init__.py +15 -20
  275. omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
  276. omlish/sql/queries/_marshal.py +3 -3
  277. omlish/sql/queries/params.py +1 -1
  278. omlish/sql/queries/rendering.py +1 -1
  279. omlish/sql/tabledefs/_marshal.py +1 -1
  280. omlish/subprocesses/all.py +135 -0
  281. omlish/subprocesses/base.py +8 -3
  282. omlish/subprocesses/editor.py +1 -1
  283. omlish/sync.py +181 -20
  284. omlish/term/alt.py +60 -0
  285. omlish/term/confirm.py +8 -8
  286. omlish/term/pager.py +235 -0
  287. omlish/term/terminfo.py +935 -0
  288. omlish/term/termstate.py +67 -0
  289. omlish/term/vt100/terminal.py +0 -3
  290. omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
  291. omlish/testing/pytest/plugins/skips.py +2 -5
  292. omlish/testing/unittest/main.py +3 -3
  293. omlish/text/docwrap/__init__.py +3 -0
  294. omlish/text/docwrap/__main__.py +11 -0
  295. omlish/text/docwrap/api.py +83 -0
  296. omlish/text/docwrap/cli.py +86 -0
  297. omlish/text/docwrap/groups.py +84 -0
  298. omlish/text/docwrap/lists.py +167 -0
  299. omlish/text/docwrap/parts.py +146 -0
  300. omlish/text/docwrap/reflowing.py +106 -0
  301. omlish/text/docwrap/rendering.py +151 -0
  302. omlish/text/docwrap/utils.py +11 -0
  303. omlish/text/docwrap/wrapping.py +59 -0
  304. omlish/text/filecache.py +2 -2
  305. omlish/text/lorem.py +6 -0
  306. omlish/text/parts.py +2 -2
  307. omlish/text/textwrap.py +51 -0
  308. omlish/typedvalues/__init__.py +1 -1
  309. omlish/typedvalues/marshal.py +85 -59
  310. omlish/typedvalues/values.py +2 -1
  311. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/METADATA +36 -38
  312. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/RECORD +323 -385
  313. omlish/asyncs/bluelet/LICENSE +0 -6
  314. omlish/asyncs/bluelet/all.py +0 -67
  315. omlish/asyncs/bluelet/api.py +0 -23
  316. omlish/asyncs/bluelet/core.py +0 -178
  317. omlish/asyncs/bluelet/events.py +0 -79
  318. omlish/asyncs/bluelet/files.py +0 -80
  319. omlish/asyncs/bluelet/runner.py +0 -417
  320. omlish/asyncs/bluelet/sockets.py +0 -216
  321. omlish/asyncs/bridge.py +0 -359
  322. omlish/asyncs/utils.py +0 -18
  323. omlish/dataclasses/impl/generation/mangling.py +0 -18
  324. omlish/defs.py +0 -216
  325. omlish/dispatch/_dispatch2.py +0 -69
  326. omlish/dispatch/_dispatch3.py +0 -108
  327. omlish/dynamic.py +0 -219
  328. omlish/formats/json/Json.g4 +0 -77
  329. omlish/formats/json/_antlr/JsonLexer.py +0 -109
  330. omlish/formats/json/_antlr/JsonListener.py +0 -61
  331. omlish/formats/json/_antlr/JsonParser.py +0 -457
  332. omlish/formats/json/_antlr/JsonVisitor.py +0 -42
  333. omlish/formats/json5/Json5.g4 +0 -168
  334. omlish/formats/json5/_antlr/Json5Lexer.py +0 -354
  335. omlish/formats/json5/_antlr/Json5Listener.py +0 -79
  336. omlish/formats/json5/_antlr/Json5Parser.py +0 -617
  337. omlish/formats/json5/_antlr/Json5Visitor.py +0 -52
  338. omlish/funcs/match.py +0 -227
  339. omlish/io/trampoline.py +0 -289
  340. omlish/lang/imports/proxyinit.py +0 -665
  341. omlish/lite/logs.py +0 -4
  342. omlish/lite/reprs.py +0 -85
  343. omlish/logs/abc.py +0 -319
  344. omlish/logs/callers.py +0 -67
  345. omlish/logs/color.py +0 -27
  346. omlish/logs/configs.py +0 -29
  347. omlish/logs/handlers.py +0 -17
  348. omlish/logs/protocol.py +0 -218
  349. omlish/logs/timing.py +0 -58
  350. omlish/marshal/factories/match.py +0 -34
  351. omlish/marshal/factories/simple.py +0 -28
  352. omlish/specs/irc/messages/base.py +0 -49
  353. omlish/specs/irc/messages/formats.py +0 -92
  354. omlish/specs/irc/messages/messages.py +0 -774
  355. omlish/specs/irc/messages/parsing.py +0 -98
  356. omlish/specs/irc/numerics/formats.py +0 -97
  357. omlish/specs/irc/numerics/numerics.py +0 -865
  358. omlish/specs/irc/numerics/types.py +0 -59
  359. omlish/specs/irc/protocol/LICENSE +0 -11
  360. omlish/specs/irc/protocol/__init__.py +0 -61
  361. omlish/specs/irc/protocol/consts.py +0 -6
  362. omlish/specs/irc/protocol/errors.py +0 -30
  363. omlish/specs/irc/protocol/message.py +0 -21
  364. omlish/specs/irc/protocol/nuh.py +0 -55
  365. omlish/specs/irc/protocol/parsing.py +0 -158
  366. omlish/specs/irc/protocol/rendering.py +0 -153
  367. omlish/specs/irc/protocol/tags.py +0 -102
  368. omlish/specs/irc/protocol/utils.py +0 -30
  369. omlish/specs/proto/Protobuf3.g4 +0 -396
  370. omlish/specs/proto/__init__.py +0 -0
  371. omlish/specs/proto/_antlr/Protobuf3Lexer.py +0 -340
  372. omlish/specs/proto/_antlr/Protobuf3Listener.py +0 -448
  373. omlish/specs/proto/_antlr/Protobuf3Parser.py +0 -3909
  374. omlish/specs/proto/_antlr/Protobuf3Visitor.py +0 -257
  375. omlish/specs/proto/_antlr/__init__.py +0 -0
  376. omlish/specs/proto/nodes.py +0 -54
  377. omlish/specs/proto/parsing.py +0 -97
  378. omlish/sql/parsing/Minisql.g4 +0 -292
  379. omlish/sql/parsing/__init__.py +0 -0
  380. omlish/sql/parsing/_antlr/MinisqlLexer.py +0 -322
  381. omlish/sql/parsing/_antlr/MinisqlListener.py +0 -511
  382. omlish/sql/parsing/_antlr/MinisqlParser.py +0 -3763
  383. omlish/sql/parsing/_antlr/MinisqlVisitor.py +0 -292
  384. omlish/sql/parsing/_antlr/__init__.py +0 -0
  385. omlish/sql/parsing/parsing.py +0 -119
  386. omlish/text/antlr/__init__.py +0 -3
  387. omlish/text/antlr/_runtime/BufferedTokenStream.py +0 -305
  388. omlish/text/antlr/_runtime/CommonTokenFactory.py +0 -64
  389. omlish/text/antlr/_runtime/CommonTokenStream.py +0 -90
  390. omlish/text/antlr/_runtime/FileStream.py +0 -30
  391. omlish/text/antlr/_runtime/InputStream.py +0 -90
  392. omlish/text/antlr/_runtime/IntervalSet.py +0 -183
  393. omlish/text/antlr/_runtime/LICENSE.txt +0 -28
  394. omlish/text/antlr/_runtime/LL1Analyzer.py +0 -176
  395. omlish/text/antlr/_runtime/Lexer.py +0 -332
  396. omlish/text/antlr/_runtime/ListTokenSource.py +0 -147
  397. omlish/text/antlr/_runtime/Parser.py +0 -583
  398. omlish/text/antlr/_runtime/ParserInterpreter.py +0 -173
  399. omlish/text/antlr/_runtime/ParserRuleContext.py +0 -189
  400. omlish/text/antlr/_runtime/PredictionContext.py +0 -632
  401. omlish/text/antlr/_runtime/Recognizer.py +0 -150
  402. omlish/text/antlr/_runtime/RuleContext.py +0 -230
  403. omlish/text/antlr/_runtime/StdinStream.py +0 -14
  404. omlish/text/antlr/_runtime/Token.py +0 -158
  405. omlish/text/antlr/_runtime/TokenStreamRewriter.py +0 -258
  406. omlish/text/antlr/_runtime/Utils.py +0 -36
  407. omlish/text/antlr/_runtime/__init__.py +0 -2
  408. omlish/text/antlr/_runtime/_all.py +0 -24
  409. omlish/text/antlr/_runtime/_pygrun.py +0 -174
  410. omlish/text/antlr/_runtime/atn/ATN.py +0 -135
  411. omlish/text/antlr/_runtime/atn/ATNConfig.py +0 -162
  412. omlish/text/antlr/_runtime/atn/ATNConfigSet.py +0 -215
  413. omlish/text/antlr/_runtime/atn/ATNDeserializationOptions.py +0 -27
  414. omlish/text/antlr/_runtime/atn/ATNDeserializer.py +0 -449
  415. omlish/text/antlr/_runtime/atn/ATNSimulator.py +0 -50
  416. omlish/text/antlr/_runtime/atn/ATNState.py +0 -267
  417. omlish/text/antlr/_runtime/atn/ATNType.py +0 -20
  418. omlish/text/antlr/_runtime/atn/LexerATNSimulator.py +0 -573
  419. omlish/text/antlr/_runtime/atn/LexerAction.py +0 -301
  420. omlish/text/antlr/_runtime/atn/LexerActionExecutor.py +0 -146
  421. omlish/text/antlr/_runtime/atn/ParserATNSimulator.py +0 -1664
  422. omlish/text/antlr/_runtime/atn/PredictionMode.py +0 -502
  423. omlish/text/antlr/_runtime/atn/SemanticContext.py +0 -333
  424. omlish/text/antlr/_runtime/atn/Transition.py +0 -271
  425. omlish/text/antlr/_runtime/atn/__init__.py +0 -4
  426. omlish/text/antlr/_runtime/dfa/DFA.py +0 -136
  427. omlish/text/antlr/_runtime/dfa/DFASerializer.py +0 -76
  428. omlish/text/antlr/_runtime/dfa/DFAState.py +0 -129
  429. omlish/text/antlr/_runtime/dfa/__init__.py +0 -4
  430. omlish/text/antlr/_runtime/error/DiagnosticErrorListener.py +0 -111
  431. omlish/text/antlr/_runtime/error/ErrorListener.py +0 -75
  432. omlish/text/antlr/_runtime/error/ErrorStrategy.py +0 -712
  433. omlish/text/antlr/_runtime/error/Errors.py +0 -176
  434. omlish/text/antlr/_runtime/error/__init__.py +0 -4
  435. omlish/text/antlr/_runtime/tree/Chunk.py +0 -33
  436. omlish/text/antlr/_runtime/tree/ParseTreeMatch.py +0 -121
  437. omlish/text/antlr/_runtime/tree/ParseTreePattern.py +0 -75
  438. omlish/text/antlr/_runtime/tree/ParseTreePatternMatcher.py +0 -377
  439. omlish/text/antlr/_runtime/tree/RuleTagToken.py +0 -53
  440. omlish/text/antlr/_runtime/tree/TokenTagToken.py +0 -50
  441. omlish/text/antlr/_runtime/tree/Tree.py +0 -194
  442. omlish/text/antlr/_runtime/tree/Trees.py +0 -114
  443. omlish/text/antlr/_runtime/tree/__init__.py +0 -2
  444. omlish/text/antlr/_runtime/xpath/XPath.py +0 -278
  445. omlish/text/antlr/_runtime/xpath/XPathLexer.py +0 -98
  446. omlish/text/antlr/_runtime/xpath/__init__.py +0 -4
  447. omlish/text/antlr/delimit.py +0 -109
  448. omlish/text/antlr/dot.py +0 -41
  449. omlish/text/antlr/errors.py +0 -14
  450. omlish/text/antlr/input.py +0 -96
  451. omlish/text/antlr/parsing.py +0 -54
  452. omlish/text/antlr/runtime.py +0 -102
  453. omlish/text/antlr/utils.py +0 -38
  454. /omlish/{asyncs/bluelet → cexts}/__init__.py +0 -0
  455. /omlish/{formats/json/_antlr → diag/cmds}/__init__.py +0 -0
  456. /omlish/{formats/json5/_antlr → http/clients/coro}/__init__.py +0 -0
  457. /omlish/{specs/irc → inject/helpers}/__init__.py +0 -0
  458. /omlish/{specs/irc/messages → logs/std}/__init__.py +0 -0
  459. /omlish/logs/{noisy.py → std/noisy.py} +0 -0
  460. /omlish/{specs/irc/numerics → marshal/composite/unions}/__init__.py +0 -0
  461. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/WHEEL +0 -0
  462. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/entry_points.txt +0 -0
  463. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/licenses/LICENSE +0 -0
  464. {omlish-0.0.0.dev423.dist-info → omlish-0.0.0.dev484.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,902 @@
1
+ """
2
+ Insufficient alt impls:
3
+ - `sys.meta_path`:
4
+ - need access to the `fromlist` and `level` arguments passed to `__import__`
5
+ - need to return fake modules to the import operation which are not added to `sys.modules`
6
+ - `sys.addaudithook`: cannot prevent import or inject result
7
+ - `sys.settrace` / bytecode tracing: same
8
+ - jit bytecode rewriting: slower than just importing everything
9
+
10
+ Possible alt impls:
11
+ - aot static analysis, codegen, compare, if valid skip ctxmgr body and inject proxies, otherwise warn and run
12
+ - or just gen code inline, if ta.TYPE_CHECKING: .... else: # @omlish-generate-auto-proxy-import/init
13
+ - generate classic `foo = _lang.proxy_import('.foo', __package__)` blocks
14
+ """
15
+ import builtins
16
+ import contextlib
17
+ import functools
18
+ import importlib.util
19
+ import sys
20
+ import threading
21
+ import types
22
+ import typing as ta
23
+
24
+
25
+ ##
26
+
27
+
28
+ class ImportCaptureError(Exception):
29
+ pass
30
+
31
+
32
+ class ImportCaptureErrors:
33
+ def __new__(cls, *args, **kwargs): # noqa
34
+ raise TypeError
35
+
36
+ class HookError(ImportCaptureError):
37
+ pass
38
+
39
+ class AttrError(ImportCaptureError):
40
+ def __init__(self, module: str | None, name: str) -> None:
41
+ super().__init__()
42
+
43
+ self.module = module
44
+ self.name = name
45
+
46
+ def __repr__(self) -> str:
47
+ return f'{self.__class__.__qualname__}(module={self.module!r}, name={self.name!r})'
48
+
49
+ class ImportError(ImportCaptureError): # noqa
50
+ def __init__(
51
+ self,
52
+ name: str,
53
+ *,
54
+ level: int | None = None,
55
+ from_list: ta.Sequence[str] | None,
56
+ ) -> None:
57
+ super().__init__()
58
+
59
+ self.name = name
60
+ self.level = level
61
+ self.from_list = from_list
62
+
63
+ def __repr__(self) -> str:
64
+ return ''.join([
65
+ f'{self.__class__.__qualname__}(',
66
+ f'name={self.name!r}',
67
+ *([f', level={self.level!r}'] if self.level is not None else []),
68
+ *([f', from_list={self.from_list!r}'] if self.from_list is not None else []),
69
+ ')',
70
+ ])
71
+
72
+ class ImportStarForbiddenError(ImportError):
73
+ pass
74
+
75
+ class UncapturedImportForbiddenError(ImportError):
76
+ pass
77
+
78
+ class UnreferencedImportsError(ImportCaptureError):
79
+ def __init__(self, unreferenced: ta.Sequence[str]) -> None:
80
+ super().__init__()
81
+
82
+ self.unreferenced = unreferenced
83
+
84
+ def __repr__(self) -> str:
85
+ return f'{self.__class__.__qualname__}(unreferenced={self.unreferenced!r})'
86
+
87
+ class CaptureInProgressError(ImportCaptureError):
88
+ pass
89
+
90
+
91
+ ##
92
+
93
+
94
+ class _ImportCaptureHook:
95
+ def __init__(
96
+ self,
97
+ *,
98
+ package: str | None = None,
99
+ forbid_uncaptured_imports: bool = False,
100
+ ) -> None:
101
+ super().__init__()
102
+
103
+ self._package = package
104
+ self._forbid_uncaptured_imports = forbid_uncaptured_imports
105
+
106
+ self._modules_by_name: dict[str, _ImportCaptureHook._Module] = {}
107
+ self._modules_by_module_obj: dict[types.ModuleType, _ImportCaptureHook._Module] = {}
108
+
109
+ #
110
+
111
+ class _Module:
112
+ def __init__(
113
+ self,
114
+ name: str,
115
+ getattr_handler: ta.Callable[['_ImportCaptureHook._Module', str], ta.Any],
116
+ *,
117
+ parent: ta.Optional['_ImportCaptureHook._Module'] = None,
118
+ ) -> None:
119
+ super().__init__()
120
+
121
+ if name.startswith('.'):
122
+ raise ImportCaptureError
123
+
124
+ self.name = name
125
+ self.parent = parent
126
+
127
+ self.base_name = name.rpartition('.')[2]
128
+ self.root: _ImportCaptureHook._Module = parent.root if parent is not None else self # noqa
129
+
130
+ self.children: dict[str, _ImportCaptureHook._Module] = {}
131
+ self.descendants: set[_ImportCaptureHook._Module] = set()
132
+
133
+ self.module_obj = types.ModuleType(f'<{self.__class__.__qualname__}: {name}>')
134
+ self.module_obj.__file__ = None
135
+ self.module_obj.__getattr__ = functools.partial(getattr_handler, self) # type: ignore[method-assign] # noqa
136
+ self.initial_module_dict = dict(self.module_obj.__dict__)
137
+
138
+ self.explicit = False
139
+ self.immediate = False
140
+
141
+ def __repr__(self) -> str:
142
+ return f'{self.__class__.__name__}<{self.name}{"!" if self.immediate else "+" if self.explicit else ""}>'
143
+
144
+ def set_explicit(self) -> None:
145
+ cur: _ImportCaptureHook._Module | None = self
146
+ while cur is not None and not cur.explicit:
147
+ cur.explicit = True
148
+ cur = cur.parent
149
+
150
+ #
151
+
152
+ @property
153
+ def _modules(self) -> ta.Sequence[_Module]:
154
+ return sorted(self._modules_by_name.values(), key=lambda m: m.name)
155
+
156
+ def _get_or_make_module(self, name: str) -> _Module:
157
+ try:
158
+ return self._modules_by_name[name]
159
+ except KeyError:
160
+ pass
161
+
162
+ parent: _ImportCaptureHook._Module | None = None
163
+ if '.' in name:
164
+ rest, _, attr = name.rpartition('.')
165
+ parent = self._get_or_make_module(rest)
166
+ if attr in parent.children:
167
+ raise ImportCaptureErrors.AttrError(rest, attr)
168
+
169
+ module = _ImportCaptureHook._Module(
170
+ name,
171
+ self._handle_module_getattr,
172
+ parent=parent,
173
+ )
174
+ self._modules_by_name[name] = module
175
+ self._modules_by_module_obj[module.module_obj] = module
176
+
177
+ if parent is not None:
178
+ parent.children[module.base_name] = module
179
+ setattr(parent.module_obj, module.base_name, module.module_obj)
180
+ parent.root.descendants.add(module)
181
+
182
+ return module
183
+
184
+ def _make_child_module(self, module: _Module, attr: str) -> _Module:
185
+ if attr in module.children:
186
+ raise ImportCaptureErrors.AttrError(module.name, attr)
187
+
188
+ return self._get_or_make_module(f'{module.name}.{attr}')
189
+
190
+ #
191
+
192
+ def _handle_module_getattr(self, module: _Module, attr: str) -> ta.Any:
193
+ if not module.explicit:
194
+ raise ImportCaptureErrors.AttrError(module.name, attr)
195
+
196
+ return self._make_child_module(module, attr).module_obj
197
+
198
+ def _handle_import(
199
+ self,
200
+ name: str,
201
+ *,
202
+ from_list: ta.Sequence[str] | None,
203
+ ) -> types.ModuleType:
204
+ module = self._get_or_make_module(name)
205
+
206
+ if from_list is None:
207
+ module.set_explicit()
208
+ module.root.immediate = True
209
+ return module.root.module_obj
210
+
211
+ else:
212
+ for attr in from_list:
213
+ if attr == '*':
214
+ raise ImportCaptureErrors.ImportStarForbiddenError(module.name, from_list=from_list)
215
+
216
+ if (cm := module.children.get(attr)) is None:
217
+ cm = self._make_child_module(module, attr)
218
+ cm.set_explicit()
219
+ cm.immediate = True
220
+ continue
221
+
222
+ x = getattr(module.module_obj, attr)
223
+ if x is not cm.module_obj or x not in self._modules_by_module_obj:
224
+ raise ImportCaptureErrors.AttrError(module.name, attr)
225
+
226
+ return module.module_obj
227
+
228
+ #
229
+
230
+ _MOD_SELF_ATTR: ta.ClassVar[str] = '__import_capture__'
231
+
232
+ def _intercept_import(
233
+ self,
234
+ name: str,
235
+ *,
236
+ globals: ta.Mapping[str, ta.Any] | None = None, # noqa
237
+ from_list: ta.Sequence[str] | None = None,
238
+ level: int = 0,
239
+ ) -> types.ModuleType | None:
240
+ if not (
241
+ globals is not None and
242
+ globals.get(self._MOD_SELF_ATTR) is self
243
+ ):
244
+ return None
245
+
246
+ if level:
247
+ if not self._package:
248
+ raise ImportCaptureError
249
+ name = importlib.util.resolve_name(('.' * level) + name, self._package)
250
+
251
+ return self._handle_import(
252
+ name,
253
+ from_list=from_list,
254
+ )
255
+
256
+ @ta.final
257
+ @contextlib.contextmanager
258
+ def hook_context(
259
+ self,
260
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
261
+ ) -> ta.Iterator[None]:
262
+ if self._MOD_SELF_ATTR in mod_globals:
263
+ raise ImportCaptureErrors.HookError
264
+
265
+ mod_globals[self._MOD_SELF_ATTR] = self
266
+
267
+ try:
268
+ with self._hook_context(mod_globals):
269
+ yield
270
+
271
+ finally:
272
+ if mod_globals[self._MOD_SELF_ATTR] is not self:
273
+ raise ImportCaptureErrors.HookError
274
+
275
+ del mod_globals[self._MOD_SELF_ATTR]
276
+
277
+ # @abc.abstractmethod
278
+ def _hook_context(
279
+ self,
280
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
281
+ ) -> ta.ContextManager[None]:
282
+ raise NotImplementedError
283
+
284
+ #
285
+
286
+ def verify_state(
287
+ self,
288
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
289
+ ) -> None:
290
+ for m in self._modules_by_name.values():
291
+ if m.immediate and not m.explicit:
292
+ raise ImportCaptureError
293
+
294
+ if not m.explicit and m.children:
295
+ raise ImportCaptureError
296
+
297
+ for a, o in m.module_obj.__dict__.items():
298
+ try:
299
+ i = m.initial_module_dict[a]
300
+
301
+ except KeyError:
302
+ if o is not m.children[a].module_obj:
303
+ raise ImportCaptureErrors.AttrError(m.name, a) from None
304
+
305
+ else:
306
+ if o != i:
307
+ raise ImportCaptureErrors.AttrError(m.name, a)
308
+
309
+ #
310
+
311
+ def build_captured(
312
+ self,
313
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
314
+ *,
315
+ collect_unreferenced: bool = False,
316
+ ) -> 'ImportCapture.Captured':
317
+ rem_explicit_mods: set[_ImportCaptureHook._Module] = set()
318
+ if collect_unreferenced:
319
+ rem_explicit_mods.update(
320
+ m for m in self._modules_by_name.values()
321
+ if m.immediate
322
+ and m.parent is not None # No good way to tell if user did `import a.b.c` or `import a.b.c as c`
323
+ )
324
+
325
+ #
326
+
327
+ dct: dict[_ImportCaptureHook._Module, list[tuple[str | None, str]]] = {}
328
+
329
+ for attr, obj in mod_globals.items():
330
+ if isinstance(obj, _ImportCaptureHook._Module):
331
+ raise ImportCaptureErrors.AttrError(None, attr) from None
332
+
333
+ elif isinstance(obj, types.ModuleType):
334
+ try:
335
+ m = self._modules_by_module_obj[obj]
336
+ except KeyError:
337
+ continue
338
+
339
+ if m.explicit:
340
+ dct.setdefault(m, []).append((None, attr))
341
+ if m in rem_explicit_mods:
342
+ # Remove everything reachable from this root *except* items imported immediately, such as
343
+ # `from x import y` - those still need to be immediately reachable.
344
+ rem_explicit_mods -= {dm for dm in m.descendants if not dm.immediate}
345
+ rem_explicit_mods.remove(m)
346
+
347
+ else:
348
+ p = m.parent
349
+ if p is None or not p.explicit:
350
+ raise ImportCaptureError
351
+ dct.setdefault(p, []).append((m.base_name, attr))
352
+
353
+ #
354
+
355
+ mods: dict[str, ImportCapture.Module] = {}
356
+
357
+ def build_import_module(m: _ImportCaptureHook._Module) -> ImportCapture.Module:
358
+ children: dict[str, ImportCapture.Module] = {}
359
+ attrs: list[str] = []
360
+ for cm in sorted(m.children.values(), key=lambda cm: cm.name):
361
+ if not cm.explicit:
362
+ attrs.append(cm.base_name)
363
+ else:
364
+ children[cm.base_name] = build_import_module(cm)
365
+
366
+ mod = ImportCapture.Module(
367
+ m.name,
368
+ children or None,
369
+ attrs or None,
370
+ )
371
+
372
+ if m.parent is None:
373
+ mod.parent = None
374
+ for c in children.values():
375
+ c.parent = mod
376
+
377
+ mods[mod.name] = mod
378
+ return mod
379
+
380
+ root_mods: dict[str, ImportCapture.Module] = {
381
+ m.base_name: build_import_module(m)
382
+ for m in self._modules_by_name.values()
383
+ if m.parent is None
384
+ }
385
+
386
+ mods = dict(sorted(mods.items(), key=lambda t: t[0]))
387
+ root_mods = dict(sorted(root_mods.items(), key=lambda t: t[0]))
388
+
389
+ #
390
+
391
+ imps: list[ImportCapture.Import] = []
392
+
393
+ for m, ts in sorted(dct.items(), key=lambda t: t[0].name):
394
+ imps.append(ImportCapture.Import(
395
+ mods[m.name],
396
+ [r for l, r in ts if l is None] or None,
397
+ [(l, r) for l, r in ts if l is not None] or None,
398
+ ))
399
+
400
+ #
401
+
402
+ unreferenced: list[str] | None = None
403
+ if collect_unreferenced and rem_explicit_mods:
404
+ unreferenced = sorted(m.name for m in rem_explicit_mods)
405
+
406
+ return ImportCapture.Captured(
407
+ {i.module.name: i for i in imps},
408
+
409
+ mods,
410
+ root_mods,
411
+
412
+ unreferenced,
413
+ )
414
+
415
+
416
+ #
417
+
418
+
419
+ class _AbstractBuiltinsImportCaptureHook(_ImportCaptureHook):
420
+ def __init__(
421
+ self,
422
+ *,
423
+ _frame: types.FrameType | None = None,
424
+ **kwargs: ta.Any,
425
+ ) -> None:
426
+ super().__init__(**kwargs)
427
+
428
+ def _new_import(
429
+ self,
430
+ old_import,
431
+ name,
432
+ globals=None, # noqa
433
+ locals=None, # noqa
434
+ fromlist=None,
435
+ level=0,
436
+ ):
437
+ if (im := self._intercept_import(
438
+ name,
439
+ globals=globals,
440
+ from_list=fromlist,
441
+ level=level,
442
+ )) is not None:
443
+ return im
444
+
445
+ if self._forbid_uncaptured_imports:
446
+ raise ImportCaptureErrors.UncapturedImportForbiddenError(
447
+ name,
448
+ level=level,
449
+ from_list=fromlist,
450
+ )
451
+
452
+ return old_import(
453
+ name,
454
+ globals=globals,
455
+ locals=locals,
456
+ fromlist=fromlist,
457
+ level=level,
458
+ )
459
+
460
+
461
+ #
462
+
463
+
464
+ class _UnsafeGlobalBuiltinsImportCaptureHook(_AbstractBuiltinsImportCaptureHook):
465
+ @contextlib.contextmanager
466
+ def _hook_context(
467
+ self,
468
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
469
+ ) -> ta.Iterator[None]:
470
+ old_import = builtins.__import__
471
+ new_import = functools.partial(self._new_import, old_import)
472
+
473
+ builtins.__import__ = new_import
474
+
475
+ try:
476
+ yield
477
+
478
+ finally:
479
+ if builtins.__import__ is not new_import:
480
+ raise ImportCaptureErrors.HookError
481
+
482
+ builtins.__import__ = old_import
483
+
484
+
485
+ class _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook(_AbstractBuiltinsImportCaptureHook):
486
+ class _AlreadyPatchedError(Exception):
487
+ pass
488
+
489
+ @ta.final
490
+ class _Patch:
491
+ __lock: ta.ClassVar[threading.Lock] = threading.Lock()
492
+
493
+ def __init__(self, old_import):
494
+ self.__old_import = old_import
495
+ self.__hooks = {}
496
+ self.__uninstalled = False
497
+
498
+ @classmethod
499
+ def _add_hook(cls, mod_globals, new_import) -> '_SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._Patch':
500
+ gi = id(mod_globals)
501
+ for _ in range(1_000):
502
+ try:
503
+ with cls.__lock:
504
+ x: ta.Any = builtins.__import__
505
+ p: _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._Patch
506
+ if x.__class__ is cls:
507
+ p = x
508
+ if p.__uninstalled: # noqa
509
+ raise _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._AlreadyPatchedError # noqa
510
+ else:
511
+ p = cls(x)
512
+ builtins.__import__ = p
513
+ p.__hooks[gi] = (mod_globals, new_import)
514
+ return p
515
+ except _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._AlreadyPatchedError:
516
+ pass
517
+ raise ImportCaptureErrors.HookError('Failed to install builtins hook')
518
+
519
+ def _remove_hook(self, mod_globals, *, no_raise=False):
520
+ gi = id(mod_globals)
521
+ with self.__lock:
522
+ tg, _ = self.__hooks[gi]
523
+ del self.__hooks[gi]
524
+ if not self.__uninstalled and not self.__hooks:
525
+ self.__uninstalled = True
526
+ if builtins.__import__ is not self:
527
+ if not no_raise:
528
+ # TODO: warn?
529
+ raise ImportCaptureErrors.HookError('Unexpected builtins hook')
530
+ else:
531
+ builtins.__import__ = self.__old_import
532
+ if tg is not mod_globals:
533
+ if not no_raise:
534
+ # TODO: warn?
535
+ raise ImportCaptureErrors.HookError('Mismatched globals')
536
+
537
+ def __call__(
538
+ self,
539
+ name,
540
+ globals=None, # noqa
541
+ locals=None, # noqa
542
+ fromlist=None,
543
+ level=0,
544
+ ):
545
+ if globals is not None and (tup := self.__hooks.get(id(globals))) is not None:
546
+ tg, tf = tup
547
+ if tg is globals:
548
+ return tf(
549
+ self.__old_import,
550
+ name,
551
+ globals=globals,
552
+ locals=locals,
553
+ fromlist=fromlist,
554
+ level=level,
555
+ )
556
+ else:
557
+ self._remove_hook(tg, no_raise=True)
558
+
559
+ return self.__old_import(
560
+ name,
561
+ globals=globals,
562
+ locals=locals,
563
+ fromlist=fromlist,
564
+ level=level,
565
+ )
566
+
567
+ @contextlib.contextmanager
568
+ def _hook_context(
569
+ self,
570
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
571
+ ) -> ta.Iterator[None]:
572
+ patch = _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook._Patch._add_hook(mod_globals, self._new_import) # noqa
573
+
574
+ try:
575
+ yield
576
+
577
+ finally:
578
+ patch._remove_hook(mod_globals) # noqa
579
+
580
+
581
+ #
582
+
583
+
584
+ _cext_: ta.Any
585
+
586
+
587
+ def _cext() -> ta.Any:
588
+ global _cext_
589
+ try:
590
+ return _cext_
591
+ except NameError:
592
+ pass
593
+
594
+ cext: ta.Any
595
+ try:
596
+ from . import _capture as cext # type: ignore
597
+ except ImportError:
598
+ cext = None
599
+
600
+ _cext_ = cext
601
+ return cext
602
+
603
+
604
+ class _FrameBuiltinsImportCaptureHook(_AbstractBuiltinsImportCaptureHook):
605
+ def __init__(
606
+ self,
607
+ *,
608
+ _frame: types.FrameType,
609
+ **kwargs: ta.Any,
610
+ ) -> None:
611
+ super().__init__(**kwargs)
612
+
613
+ self._frame = _frame
614
+
615
+ @classmethod
616
+ def _set_frame_builtins(
617
+ cls,
618
+ frame: types.FrameType,
619
+ new_builtins: dict[str, ta.Any],
620
+ ) -> bool:
621
+ return _cext()._set_frame_builtins(frame, frame.f_builtins, new_builtins) # noqa
622
+
623
+ @contextlib.contextmanager
624
+ def _hook_context(
625
+ self,
626
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
627
+ ) -> ta.Iterator[None]:
628
+ old_builtins = self._frame.f_builtins
629
+ old_import = old_builtins['__import__']
630
+ new_import = functools.partial(self._new_import, old_import)
631
+
632
+ new_builtins = dict(old_builtins)
633
+ new_builtins['__import__'] = new_import
634
+ if not self._set_frame_builtins(self._frame, new_builtins):
635
+ raise ImportCaptureErrors.HookError
636
+
637
+ try:
638
+ yield
639
+
640
+ finally:
641
+ if self._frame.f_builtins is not new_builtins:
642
+ raise ImportCaptureErrors.HookError
643
+
644
+ if not self._set_frame_builtins(self._frame, old_builtins):
645
+ raise ImportCaptureErrors.HookError
646
+
647
+
648
+ #
649
+
650
+
651
+ _CAPTURE_IMPLS: ta.Mapping[str, type[_AbstractBuiltinsImportCaptureHook]] = {
652
+ 'cext': _FrameBuiltinsImportCaptureHook,
653
+ 'somewhat_safe': _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook,
654
+ 'unsafe': _UnsafeGlobalBuiltinsImportCaptureHook,
655
+ }
656
+
657
+
658
+ def _new_import_capture_hook(
659
+ mod_globals: ta.MutableMapping[str, ta.Any], # noqa
660
+ *,
661
+ stack_offset: int = 0,
662
+ capture_impl: str | None = None,
663
+ **kwargs: ta.Any,
664
+ ) -> '_ImportCaptureHook':
665
+ if '_frame' not in kwargs:
666
+ frame: types.FrameType | None = sys._getframe(1 + stack_offset) # noqa
667
+ if frame is None or frame.f_globals is not mod_globals:
668
+ raise ImportCaptureError("Can't find importing frame")
669
+ kwargs['_frame'] = frame
670
+
671
+ kwargs.setdefault('package', mod_globals.get('__package__'))
672
+
673
+ cls: type[_AbstractBuiltinsImportCaptureHook]
674
+ if capture_impl is not None:
675
+ cls = _CAPTURE_IMPLS[capture_impl]
676
+ elif _cext() is not None:
677
+ cls = _FrameBuiltinsImportCaptureHook
678
+ else:
679
+ cls = _SomewhatThreadSafeGlobalBuiltinsImportCaptureHook
680
+
681
+ return cls(**kwargs)
682
+
683
+
684
+ ##
685
+
686
+
687
+ ImportCaptureModuleKind: ta.TypeAlias = ta.Literal[
688
+ 'parent',
689
+ 'terminal',
690
+ 'leaf',
691
+ ]
692
+
693
+
694
+ class ImportCapture:
695
+ @ta.final
696
+ class Module:
697
+ def __init__(
698
+ self,
699
+ name: str,
700
+ children: ta.Mapping[str, 'ImportCapture.Module'] | None = None,
701
+ attrs: ta.Sequence[str] | None = None,
702
+ ) -> None:
703
+ self.name = name
704
+ self.children = children
705
+ self.attrs = attrs
706
+
707
+ self.base_name = name.rpartition('.')[2]
708
+
709
+ if not self.children and not self.attrs:
710
+ self.kind = 'leaf'
711
+ elif not self.children or all(c.kind == 'leaf' for c in self.children.values()):
712
+ self.kind = 'terminal'
713
+ else:
714
+ self.kind = 'parent'
715
+
716
+ parent: ta.Optional['ImportCapture.Module']
717
+
718
+ kind: ImportCaptureModuleKind
719
+
720
+ def __repr__(self) -> str:
721
+ return ''.join([
722
+ f'{self.__class__.__name__}(',
723
+ f'{self.name!r}',
724
+ f', :{self.kind}',
725
+ *([f', children=[{", ".join(map(repr, self.children))}]'] if self.children else []),
726
+ *([f', attrs={self.attrs!r}'] if self.attrs else []),
727
+ ')',
728
+ ])
729
+
730
+ _root: 'ImportCapture.Module'
731
+
732
+ @property
733
+ def root(self) -> 'ImportCapture.Module':
734
+ try:
735
+ return self._root
736
+ except AttributeError:
737
+ pass
738
+
739
+ root = self
740
+ while root.parent is not None:
741
+ root = root.parent
742
+ self._root = root
743
+ return root
744
+
745
+ @ta.final
746
+ class Import:
747
+ def __init__(
748
+ self,
749
+ module: 'ImportCapture.Module',
750
+ as_: ta.Sequence[str] | None,
751
+ attrs: ta.Sequence[tuple[str, str]] | None, # ('foo', 'bar') -> `import foo as bar` - explicitly not a dict # noqa
752
+ ) -> None:
753
+ self.module = module
754
+ self.as_ = as_
755
+ self.attrs = attrs
756
+
757
+ def __repr__(self) -> str:
758
+ return ''.join([
759
+ f'{self.__class__.__name__}(',
760
+ f'{self.module.name!r}',
761
+ *([f', as_={self.as_!r}'] if self.as_ else []),
762
+ *([f', attrs={self.attrs!r}'] if self.attrs else []),
763
+ ')',
764
+ ])
765
+
766
+ @ta.final
767
+ class Captured:
768
+ def __init__(
769
+ self,
770
+
771
+ imports: ta.Mapping[str, 'ImportCapture.Import'],
772
+
773
+ modules: ta.Mapping[str, 'ImportCapture.Module'],
774
+ root_modules: ta.Mapping[str, 'ImportCapture.Module'],
775
+
776
+ unreferenced: ta.Sequence[str] | None,
777
+ ) -> None:
778
+ self.imports = imports
779
+
780
+ self.modules = modules
781
+ self.root_modules = root_modules
782
+
783
+ self.unreferenced = unreferenced
784
+
785
+ @property
786
+ def attrs(self) -> ta.Iterator[str]:
787
+ for pi in self.imports.values():
788
+ if pi.as_:
789
+ yield from pi.as_
790
+ if pi.attrs:
791
+ for _, a in pi.attrs:
792
+ yield a
793
+
794
+ EMPTY_CAPTURED: ta.ClassVar[Captured] = Captured(
795
+ {},
796
+ {},
797
+ {},
798
+ None,
799
+ )
800
+
801
+ #
802
+
803
+ def __init__(
804
+ self,
805
+ mod_globals: ta.MutableMapping[str, ta.Any],
806
+ *,
807
+ _hook: _ImportCaptureHook,
808
+
809
+ disable: bool = False,
810
+ ) -> None:
811
+ super().__init__()
812
+
813
+ self._mod_globals = mod_globals
814
+ self._hook = _hook
815
+
816
+ self._disabled = disable
817
+
818
+ @property
819
+ def disabled(self) -> bool:
820
+ return self._disabled
821
+
822
+ #
823
+
824
+ class _Result(ta.NamedTuple):
825
+ captured: 'ImportCapture.Captured'
826
+
827
+ _result_: _Result | None = None
828
+
829
+ @property
830
+ def _result(self) -> _Result:
831
+ if (rs := self._result_) is None:
832
+ raise ImportCaptureErrors.CaptureInProgressError
833
+ return rs
834
+
835
+ @property
836
+ def is_complete(self) -> bool:
837
+ return self._result_ is not None
838
+
839
+ @property
840
+ def captured(self) -> Captured:
841
+ return self._result.captured
842
+
843
+ #
844
+
845
+ @contextlib.contextmanager
846
+ def capture(
847
+ self,
848
+ *,
849
+ unreferenced_callback: ta.Callable[[ta.Sequence[str]], None] | None = None,
850
+ raise_unreferenced: bool = False,
851
+ ) -> ta.Iterator[ta.Self]:
852
+ if self._result_ is not None:
853
+ raise ImportCaptureError('capture already complete')
854
+
855
+ if self._disabled:
856
+ self._result_ = ImportCapture._Result(
857
+ ImportCapture.EMPTY_CAPTURED,
858
+ )
859
+ yield self
860
+ return
861
+
862
+ with self._hook.hook_context(self._mod_globals):
863
+ yield self
864
+
865
+ self._hook.verify_state(self._mod_globals)
866
+
867
+ blt = self._hook.build_captured(
868
+ self._mod_globals,
869
+ collect_unreferenced=unreferenced_callback is not None or raise_unreferenced,
870
+ )
871
+
872
+ if blt.unreferenced:
873
+ if unreferenced_callback:
874
+ unreferenced_callback(blt.unreferenced)
875
+ if raise_unreferenced:
876
+ raise ImportCaptureErrors.UnreferencedImportsError(blt.unreferenced)
877
+
878
+ for a in blt.attrs:
879
+ del self._mod_globals[a]
880
+
881
+ self._result_ = ImportCapture._Result(
882
+ blt,
883
+ )
884
+
885
+ #
886
+
887
+ def update_exports(self) -> None:
888
+ cap = self._result.captured
889
+
890
+ try:
891
+ al: ta.Any = self._mod_globals['__all__']
892
+ except KeyError:
893
+ al = self._mod_globals['__all__'] = [k for k in self._mod_globals if not k.startswith('_')]
894
+ else:
895
+ if not isinstance(al, ta.MutableSequence):
896
+ al = self._mod_globals['__all__'] = list(al)
897
+
898
+ al_s = set(al)
899
+ for a in cap.attrs:
900
+ if a not in al_s:
901
+ al.append(a)
902
+ al_s.add(a)