omlish 0.0.0.dev22__tar.gz → 0.0.0.dev23__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.
Files changed (310) hide show
  1. {omlish-0.0.0.dev22/omlish.egg-info → omlish-0.0.0.dev23}/PKG-INFO +1 -1
  2. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/__about__.py +10 -3
  3. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/bridge.py +3 -0
  4. omlish-0.0.0.dev23/omlish/bootstrap/__init__.py +42 -0
  5. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/base.py +3 -1
  6. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/diag.py +48 -1
  7. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/main.py +2 -1
  8. omlish-0.0.0.dev23/omlish/bootstrap/marshal.py +18 -0
  9. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/check.py +123 -33
  10. omlish-0.0.0.dev23/omlish/diag/asts.py +132 -0
  11. omlish-0.0.0.dev23/omlish/diag/pycharm.py +80 -0
  12. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/docker.py +3 -0
  13. omlish-0.0.0.dev23/omlish/genmachine.py +58 -0
  14. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/__init__.py +4 -0
  15. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/base64.py +4 -0
  16. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/primitives.py +6 -0
  17. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/standard.py +4 -0
  18. omlish-0.0.0.dev23/omlish/marshal/unions.py +101 -0
  19. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/matchfns.py +3 -3
  20. omlish-0.0.0.dev23/omlish/sql/__init__.py +27 -0
  21. omlish-0.0.0.dev23/omlish/sql/qualifiedname.py +82 -0
  22. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23/omlish.egg-info}/PKG-INFO +1 -1
  23. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/SOURCES.txt +6 -0
  24. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/pyproject.toml +1 -1
  25. omlish-0.0.0.dev22/omlish/bootstrap/__init__.py +0 -3
  26. omlish-0.0.0.dev22/omlish/sql/__init__.py +0 -9
  27. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/LICENSE +0 -0
  28. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/MANIFEST.in +0 -0
  29. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/README.rst +0 -0
  30. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/__init__.py +0 -0
  31. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/argparse.py +0 -0
  32. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/__init__.py +0 -0
  33. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/anyio.py +0 -0
  34. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/asyncio.py +0 -0
  35. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/asyncs.py +0 -0
  36. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/flavors.py +0 -0
  37. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/trio.py +0 -0
  38. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/asyncs/trio_asyncio.py +0 -0
  39. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/__main__.py +0 -0
  40. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/harness.py +0 -0
  41. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/bootstrap/sys.py +0 -0
  42. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/c3.py +0 -0
  43. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/cached.py +0 -0
  44. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/__init__.py +0 -0
  45. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/_abc.py +0 -0
  46. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/_io_abc.py +0 -0
  47. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/__init__.py +0 -0
  48. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/descriptor.py +0 -0
  49. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/impl.py +0 -0
  50. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/cache/types.py +0 -0
  51. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/coerce.py +0 -0
  52. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/exceptions.py +0 -0
  53. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/frozen.py +0 -0
  54. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/identity.py +0 -0
  55. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/indexed.py +0 -0
  56. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/mappings.py +0 -0
  57. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/ordered.py +0 -0
  58. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/persistent.py +0 -0
  59. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/skiplist.py +0 -0
  60. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/sorted.py +0 -0
  61. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/treap.py +0 -0
  62. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/treapmap.py +0 -0
  63. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/unmodifiable.py +0 -0
  64. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/collections/utils.py +0 -0
  65. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/__init__.py +0 -0
  66. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/executors.py +0 -0
  67. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/futures.py +0 -0
  68. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/concurrent/threadlets.py +0 -0
  69. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/__init__.py +0 -0
  70. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/classes.py +0 -0
  71. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/flattening.py +0 -0
  72. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/configs/strings.py +0 -0
  73. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/__init__.py +0 -0
  74. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/__init__.py +0 -0
  75. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/api.py +0 -0
  76. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/as_.py +0 -0
  77. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/copy.py +0 -0
  78. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/descriptors.py +0 -0
  79. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/exceptions.py +0 -0
  80. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/fields.py +0 -0
  81. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/frozen.py +0 -0
  82. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/hashing.py +0 -0
  83. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/init.py +0 -0
  84. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/internals.py +0 -0
  85. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/main.py +0 -0
  86. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/metaclass.py +0 -0
  87. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/metadata.py +0 -0
  88. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/order.py +0 -0
  89. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/params.py +0 -0
  90. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/processing.py +0 -0
  91. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/reflect.py +0 -0
  92. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/replace.py +0 -0
  93. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/repr.py +0 -0
  94. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/simple.py +0 -0
  95. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/slots.py +0 -0
  96. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/impl/utils.py +0 -0
  97. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dataclasses/utils.py +0 -0
  98. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/datetimes.py +0 -0
  99. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/defs.py +0 -0
  100. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/__init__.py +0 -0
  101. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/procfs.py +0 -0
  102. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/procstats.py +0 -0
  103. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/ps.py +0 -0
  104. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/pydevd.py +0 -0
  105. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/__init__.py +0 -0
  106. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/__main__.py +0 -0
  107. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/console.py +0 -0
  108. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/replserver/server.py +0 -0
  109. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/diag/threads.py +0 -0
  110. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/__init__.py +0 -0
  111. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/_dispatch2.py +0 -0
  112. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/_dispatch3.py +0 -0
  113. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/dispatch.py +0 -0
  114. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/functions.py +0 -0
  115. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dispatch/methods.py +0 -0
  116. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/dynamic.py +0 -0
  117. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/fnpairs.py +0 -0
  118. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/__init__.py +0 -0
  119. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/dotenv.py +0 -0
  120. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/json.py +0 -0
  121. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/props.py +0 -0
  122. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/formats/yaml.py +0 -0
  123. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/__init__.py +0 -0
  124. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dags.py +0 -0
  125. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/domination.py +0 -0
  126. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/__init__.py +0 -0
  127. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/items.py +0 -0
  128. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/rendering.py +0 -0
  129. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/dot/utils.py +0 -0
  130. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/graphs/trees.py +0 -0
  131. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/__init__.py +0 -0
  132. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/asgi.py +0 -0
  133. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/collections.py +0 -0
  134. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/consts.py +0 -0
  135. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/cookies.py +0 -0
  136. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/dates.py +0 -0
  137. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/encodings.py +0 -0
  138. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/json.py +0 -0
  139. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/sessions.py +0 -0
  140. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/http/wsgi.py +0 -0
  141. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/__init__.py +0 -0
  142. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/binder.py +0 -0
  143. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/bindings.py +0 -0
  144. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/eagers.py +0 -0
  145. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/elements.py +0 -0
  146. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/exceptions.py +0 -0
  147. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/__init__.py +0 -0
  148. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/bindings.py +0 -0
  149. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/elements.py +0 -0
  150. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/injector.py +0 -0
  151. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/inspect.py +0 -0
  152. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/multis.py +0 -0
  153. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/origins.py +0 -0
  154. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/privates.py +0 -0
  155. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/providers.py +0 -0
  156. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/proxy.py +0 -0
  157. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/impl/scopes.py +0 -0
  158. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/injector.py +0 -0
  159. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/inspect.py +0 -0
  160. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/keys.py +0 -0
  161. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/listeners.py +0 -0
  162. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/managed.py +0 -0
  163. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/multis.py +0 -0
  164. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/origins.py +0 -0
  165. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/overrides.py +0 -0
  166. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/privates.py +0 -0
  167. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/providers.py +0 -0
  168. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/scopes.py +0 -0
  169. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/types.py +0 -0
  170. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/inject/utils.py +0 -0
  171. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/iterators.py +0 -0
  172. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/__init__.py +0 -0
  173. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/cached.py +0 -0
  174. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/__init__.py +0 -0
  175. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/abstract.py +0 -0
  176. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/restrict.py +0 -0
  177. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/simple.py +0 -0
  178. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/classes/virtual.py +0 -0
  179. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/clsdct.py +0 -0
  180. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/cmp.py +0 -0
  181. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/contextmanagers.py +0 -0
  182. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/descriptors.py +0 -0
  183. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/exceptions.py +0 -0
  184. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/functions.py +0 -0
  185. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/imports.py +0 -0
  186. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/iterables.py +0 -0
  187. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/maybes.py +0 -0
  188. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/objects.py +0 -0
  189. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/resolving.py +0 -0
  190. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/strings.py +0 -0
  191. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/sys.py +0 -0
  192. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/timeouts.py +0 -0
  193. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lang/typing.py +0 -0
  194. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/libc.py +0 -0
  195. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/__init__.py +0 -0
  196. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/abstract.py +0 -0
  197. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/base.py +0 -0
  198. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/contextmanagers.py +0 -0
  199. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/controller.py +0 -0
  200. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/manager.py +0 -0
  201. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/states.py +0 -0
  202. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lifecycles/transitions.py +0 -0
  203. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/__init__.py +0 -0
  204. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/cached.py +0 -0
  205. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/check.py +0 -0
  206. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/contextmanagers.py +0 -0
  207. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/json.py +0 -0
  208. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/logs.py +0 -0
  209. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/marshal.py +0 -0
  210. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/reflect.py +0 -0
  211. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/runtime.py +0 -0
  212. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/secrets.py +0 -0
  213. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/strings.py +0 -0
  214. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/lite/subprocesses.py +0 -0
  215. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/__init__.py +0 -0
  216. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/_abc.py +0 -0
  217. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/configs.py +0 -0
  218. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/formatters.py +0 -0
  219. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/handlers.py +0 -0
  220. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/noisy.py +0 -0
  221. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/logs/utils.py +0 -0
  222. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/any.py +0 -0
  223. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/base.py +0 -0
  224. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/dataclasses.py +0 -0
  225. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/datetimes.py +0 -0
  226. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/enums.py +0 -0
  227. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/exceptions.py +0 -0
  228. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/factories.py +0 -0
  229. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/forbidden.py +0 -0
  230. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/global_.py +0 -0
  231. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/helpers.py +0 -0
  232. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/iterables.py +0 -0
  233. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/mappings.py +0 -0
  234. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/maybes.py +0 -0
  235. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/naming.py +0 -0
  236. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/numbers.py +0 -0
  237. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/objects.py +0 -0
  238. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/optionals.py +0 -0
  239. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/polymorphism.py +0 -0
  240. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/registries.py +0 -0
  241. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/utils.py +0 -0
  242. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/uuids.py +0 -0
  243. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/marshal/values.py +0 -0
  244. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/math.py +0 -0
  245. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/multiprocessing.py +0 -0
  246. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/os.py +0 -0
  247. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/__init__.py +0 -0
  248. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/isinstance.py +0 -0
  249. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/ops.py +0 -0
  250. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/subst.py +0 -0
  251. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/reflect/types.py +0 -0
  252. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/runmodule.py +0 -0
  253. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/__init__.py +0 -0
  254. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/crypto.py +0 -0
  255. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/marshal.py +0 -0
  256. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/openssl.py +0 -0
  257. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/passwords.py +0 -0
  258. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/secrets.py +0 -0
  259. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/secrets/subprocesses.py +0 -0
  260. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/__init__.py +0 -0
  261. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/__init__.py +0 -0
  262. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/__init__.py +0 -0
  263. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/base.py +0 -0
  264. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/core.py +0 -0
  265. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/metadata.py +0 -0
  266. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/parse.py +0 -0
  267. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/render.py +0 -0
  268. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/keywords/validation.py +0 -0
  269. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/schemas/__init__.py +0 -0
  270. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/schemas/draft202012/__init__.py +0 -0
  271. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/schemas/draft202012/vocabularies/__init__.py +0 -0
  272. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/specs/jsonschema/types.py +0 -0
  273. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/_abc.py +0 -0
  274. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/asyncs.py +0 -0
  275. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/dbs.py +0 -0
  276. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/duckdb.py +0 -0
  277. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/exprs.py +0 -0
  278. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/secrets.py +0 -0
  279. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sql/sqlean.py +0 -0
  280. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/stats.py +0 -0
  281. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/sync.py +0 -0
  282. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/term.py +0 -0
  283. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/__init__.py +0 -0
  284. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/__init__.py +0 -0
  285. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/helpers.py +0 -0
  286. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/inject/__init__.py +0 -0
  287. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/inject/harness.py +0 -0
  288. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/marks.py +0 -0
  289. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/__init__.py +0 -0
  290. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/_registry.py +0 -0
  291. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/asyncs.py +0 -0
  292. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/depskip.py +0 -0
  293. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/logging.py +0 -0
  294. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/managermarks.py +0 -0
  295. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/pydevd.py +0 -0
  296. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/repeat.py +0 -0
  297. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/skips.py +0 -0
  298. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/spacing.py +0 -0
  299. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/switches.py +0 -0
  300. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/pytest/plugins/utils.py +0 -0
  301. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/testing/testing.py +0 -0
  302. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/__init__.py +0 -0
  303. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/delimit.py +0 -0
  304. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/glyphsplit.py +0 -0
  305. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/indent.py +0 -0
  306. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish/text/parts.py +0 -0
  307. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/dependency_links.txt +0 -0
  308. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/requires.txt +0 -0
  309. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/omlish.egg-info/top_level.txt +0 -0
  310. {omlish-0.0.0.dev22 → omlish-0.0.0.dev23}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev22
3
+ Version: 0.0.0.dev23
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev22'
2
- __revision__ = '3d902899000237758f62e46319a8da3bccd2d447'
1
+ __version__ = '0.0.0.dev23'
2
+ __revision__ = '1d019b6879a9552ea31622e40f50d260d6b08824'
3
3
 
4
4
 
5
5
  #
@@ -80,7 +80,11 @@ class Project(ProjectBase):
80
80
  'sqlalchemy[asyncio] ~= 2.0',
81
81
 
82
82
  'pg8000 ~= 1.31',
83
+ # 'psycopg2 ~= 2.9',
84
+
83
85
  'pymysql ~= 1.1',
86
+ # 'mysql-connector-python ~= 9.0',
87
+ # 'mysqlclient ~= 2.2',
84
88
 
85
89
  'aiomysql ~= 0.2',
86
90
  'aiosqlite ~= 0.20',
@@ -110,7 +114,10 @@ class SetuptoolsBase:
110
114
  include_package_data = False
111
115
 
112
116
  find_packages = {
113
- 'exclude': ['*.tests', '*.tests.*'],
117
+ 'exclude': [
118
+ '*.tests',
119
+ '*.tests.*',
120
+ ],
114
121
  }
115
122
 
116
123
 
@@ -8,6 +8,9 @@ KEEP THE SPACE SHUTTLE FLYING.
8
8
 
9
9
  TODO:
10
10
  - reuse greenlet if nested somehow?
11
+
12
+ See:
13
+ - https://greenback.readthedocs.io/en/latest/
11
14
  """
12
15
  import itertools
13
16
  import sys
@@ -0,0 +1,42 @@
1
+ from .base import ( # noqa
2
+ Bootstrap,
3
+ ContextBootstrap,
4
+ SimpleBootstrap,
5
+ )
6
+
7
+ from .diag import ( # noqa
8
+ CheckBootstrap,
9
+ CprofileBootstrap,
10
+ PycharmBootstrap,
11
+ ThreadDumpBootstrap,
12
+ TimebombBootstrap,
13
+ )
14
+
15
+ from .harness import ( # noqa
16
+ bootstrap,
17
+ )
18
+
19
+ from .sys import ( # noqa
20
+ CwdBootstrap,
21
+ EnvBootstrap,
22
+ FaulthandlerBootstrap,
23
+ FdsBootstrap,
24
+ GcBootstrap,
25
+ GcDebugFlag,
26
+ ImportBootstrap,
27
+ LogBootstrap,
28
+ NiceBootstrap,
29
+ PidfileBootstrap,
30
+ PrctlBootstrap,
31
+ PrintPidBootstrap,
32
+ RlimitBootstrap,
33
+ SetuidBootstrap,
34
+ )
35
+
36
+
37
+ ##
38
+
39
+
40
+ from ..lang.imports import _register_conditional_import # noqa
41
+
42
+ _register_conditional_import('..marshal', '.marshal', __package__)
@@ -2,6 +2,8 @@ import abc
2
2
  import dataclasses as dc
3
3
  import typing as ta
4
4
 
5
+ from omlish import lang
6
+
5
7
 
6
8
  BootstrapConfigT = ta.TypeVar('BootstrapConfigT', bound='Bootstrap.Config')
7
9
 
@@ -9,7 +11,7 @@ BootstrapConfigT = ta.TypeVar('BootstrapConfigT', bound='Bootstrap.Config')
9
11
  ##
10
12
 
11
13
 
12
- class Bootstrap(abc.ABC, ta.Generic[BootstrapConfigT]):
14
+ class Bootstrap(abc.ABC, lang.PackageSealed, ta.Generic[BootstrapConfigT]):
13
15
  @dc.dataclass(frozen=True)
14
16
  class Config(abc.ABC): # noqa
15
17
  pass
@@ -5,28 +5,56 @@ import signal
5
5
  import sys
6
6
  import typing as ta
7
7
 
8
+ from .. import check
8
9
  from .. import lang
9
10
  from .base import Bootstrap
10
11
  from .base import ContextBootstrap
12
+ from .base import SimpleBootstrap
11
13
 
12
14
 
13
15
  if ta.TYPE_CHECKING:
14
16
  import cProfile # noqa
15
17
  import pstats
16
18
 
19
+ from ..diag import pycharm as diagpc
17
20
  from ..diag import threads as diagt
18
21
 
19
22
  else:
20
23
  cProfile = lang.proxy_import('cProfile') # noqa
21
24
  pstats = lang.proxy_import('pstats')
22
25
 
26
+ diagpc = lang.proxy_import('..diag.pycharm', __package__)
23
27
  diagt = lang.proxy_import('..diag.threads', __package__)
24
28
 
25
29
 
26
30
  ##
27
31
 
28
32
 
29
- class ProfilingBootstrap(ContextBootstrap['ProfilingBootstrap.Config']):
33
+ class CheckBootstrap(ContextBootstrap['CheckBootstrap.Config']):
34
+ @dc.dataclass(frozen=True)
35
+ class Config(Bootstrap.Config):
36
+ breakpoint: bool = False
37
+
38
+ @staticmethod
39
+ def _breakpoint(exc: Exception) -> None: # noqa
40
+ breakpoint() # noqa
41
+
42
+ @contextlib.contextmanager
43
+ def enter(self) -> ta.Iterator[None]:
44
+ if not self._config.breakpoint:
45
+ return
46
+
47
+ check.register_on_raise(CheckBootstrap._breakpoint)
48
+ try:
49
+ yield
50
+ finally:
51
+ check.unregister_on_raise(CheckBootstrap._breakpoint)
52
+
53
+
54
+ ##
55
+
56
+
57
+ class CprofileBootstrap(ContextBootstrap['CprofileBootstrap.Config']):
30
58
  @dc.dataclass(frozen=True)
31
59
  class Config(Bootstrap.Config):
32
60
  enable: bool = False
@@ -128,3 +156,22 @@ class TimebombBootstrap(ContextBootstrap['TimebombBootstrap.Config']):
128
156
  yield
129
157
  finally:
130
158
  tbt.stop_nowait()
159
+
160
+
161
+ ##
162
+
163
+
164
+ class PycharmBootstrap(SimpleBootstrap['PycharmBootstrap.Config']):
165
+ @dc.dataclass(frozen=True)
166
+ class Config(Bootstrap.Config):
167
+ debug_host: ta.Optional[str] = None
168
+ debug_port: ta.Optional[int] = None
169
+ debug_version: ta.Optional[str] = None
170
+
171
+ def run(self) -> None:
172
+ if self._config.debug_port is not None:
173
+ diagpc.pycharm_remote_debugger_attach(
174
+ self._config.debug_host,
175
+ self._config.debug_port,
176
+ version=self._config.debug_version,
177
+ )
@@ -156,8 +156,9 @@ def _main() -> int:
156
156
  with bootstrap(*cfgs):
157
157
  tgt = args.target
158
158
 
159
+ sys.argv = [tgt, *(args.args or ())]
160
+
159
161
  if args.module:
160
- sys.argv = [tgt, *(args.args or ())]
161
162
  runpy._run_module_as_main(tgt) # type: ignore # noqa
162
163
 
163
164
  else:
@@ -0,0 +1,18 @@
1
+ from .. import lang
2
+ from .. import marshal as msh
3
+ from .base import Bootstrap
4
+ from .harness import BOOTSTRAP_TYPES_BY_NAME
5
+
6
+
7
+ @lang.cached_function
8
+ def _install_standard_marshalling() -> None:
9
+ cfgs_poly = msh.Polymorphism(
10
+ Bootstrap.Config,
11
+ [msh.Impl(b.Config, n) for n, b in BOOTSTRAP_TYPES_BY_NAME.items()],
12
+ )
13
+
14
+ msh.STANDARD_MARSHALER_FACTORIES[0:0] = [msh.PolymorphismMarshalerFactory(cfgs_poly)]
15
+ msh.STANDARD_UNMARSHALER_FACTORIES[0:0] = [msh.PolymorphismUnmarshalerFactory(cfgs_poly)]
16
+
17
+
18
+ _install_standard_marshalling()
@@ -3,6 +3,7 @@ TODO:
3
3
  - def maybe(v: lang.Maybe[T])
4
4
  """
5
5
  import collections
6
+ import threading
6
7
  import typing as ta
7
8
 
8
9
 
@@ -21,6 +22,62 @@ _callable = callable
21
22
  ##
22
23
 
23
24
 
25
+ _CONFIG_LOCK = threading.RLock()
26
+
27
+
28
+ OnRaiseFn: ta.TypeAlias = ta.Callable[[Exception], None]
29
+ _ON_RAISE: ta.Sequence[OnRaiseFn] = []
30
+
31
+
32
+ def register_on_raise(fn: OnRaiseFn) -> None:
33
+ global _ON_RAISE
34
+ with _CONFIG_LOCK:
35
+ _ON_RAISE = [*_ON_RAISE, fn]
36
+
37
+
38
+ def unregister_on_raise(fn: OnRaiseFn) -> None:
39
+ global _ON_RAISE
40
+ with _CONFIG_LOCK:
41
+ _ON_RAISE = [e for e in _ON_RAISE if e != fn]
42
+
43
+
44
+ #
45
+
46
+
47
+ _render_args: ta.Callable[..., str | None] | None = None
48
+
49
+
50
+ def enable_args_rendering() -> bool:
51
+ global _render_args
52
+ if _render_args is not None:
53
+ return True
54
+
55
+ with _CONFIG_LOCK:
56
+ if _render_args is not None:
57
+ return True # type: ignore
58
+
59
+ try:
60
+ from .diag.asts import ArgsRenderer
61
+
62
+ ArgsRenderer.smoketest()
63
+
64
+ except Exception: # noqa
65
+ return False
66
+
67
+ def _real_render_args(fmt: str, *args: ta.Any) -> str | None:
68
+ ra = ArgsRenderer(back=3).render_args(*args)
69
+ if ra is None:
70
+ return None
71
+
72
+ return fmt % tuple(str(a) for a in ra)
73
+
74
+ _render_args = _real_render_args
75
+ return True
76
+
77
+
78
+ #
79
+
80
+
24
81
  def _default_exception_factory(exc_cls: type[Exception], *args, **kwargs) -> Exception:
25
82
  return exc_cls(*args, **kwargs) # noqa
26
83
 
@@ -28,20 +85,45 @@ def _default_exception_factory(exc_cls: type[Exception], *args, **kwargs) -> Exc
28
85
  _EXCEPTION_FACTORY = _default_exception_factory
29
86
 
30
87
 
88
+ class _Args:
89
+ def __init__(self, *args, **kwargs):
90
+ self.args = args
91
+ self.kwargs = kwargs
92
+
93
+
31
94
  def _raise(
32
95
  exception_type: type[Exception],
33
96
  default_message: str,
34
97
  message: Message,
35
- *args: ta.Any,
36
- **kwargs: ta.Any,
98
+ ak: _Args = _Args(),
99
+ *,
100
+ render_fmt: str | None = None,
37
101
  ) -> ta.NoReturn:
102
+ exc_args = ()
38
103
  if _callable(message):
39
- message = ta.cast(ta.Callable, message)(*args, **kwargs)
104
+ message = ta.cast(ta.Callable, message)(*ak.args, **ak.kwargs)
40
105
  if _isinstance(message, tuple):
41
- message, *args = message # type: ignore
106
+ message, *exc_args = message # type: ignore
107
+
42
108
  if message is None:
43
109
  message = default_message
44
- exc = _EXCEPTION_FACTORY(exception_type, message, *args, **kwargs)
110
+
111
+ if render_fmt is not None and _render_args is not None:
112
+ rendered_args = _render_args(render_fmt, *ak.args)
113
+ if rendered_args is not None:
114
+ message = f'{message} : {rendered_args}'
115
+
116
+ exc = _EXCEPTION_FACTORY(
117
+ exception_type,
118
+ message,
119
+ *exc_args,
120
+ *ak.args,
121
+ **ak.kwargs,
122
+ )
123
+
124
+ for fn in _ON_RAISE:
125
+ fn(exc)
126
+
45
127
  raise exc
46
128
 
47
129
 
@@ -60,7 +142,7 @@ def _unpack_isinstance_spec(spec: ta.Any) -> tuple:
60
142
 
61
143
  def isinstance(v: ta.Any, spec: type[T] | tuple, msg: Message = None) -> T: # noqa
62
144
  if not _isinstance(v, _unpack_isinstance_spec(spec)):
63
- _raise(TypeError, 'Must be instance', msg, v, spec)
145
+ _raise(TypeError, 'Must be instance', msg, _Args(v, spec))
64
146
  return v
65
147
 
66
148
 
@@ -73,7 +155,7 @@ def of_isinstance(spec: type[T] | tuple, msg: Message = None) -> ta.Callable[[ta
73
155
 
74
156
  def cast(v: ta.Any, cls: type[T], msg: Message = None) -> T: # noqa
75
157
  if not _isinstance(v, cls):
76
- _raise(TypeError, 'Must be instance', msg, v, cls)
158
+ _raise(TypeError, 'Must be instance', msg, _Args(v, cls))
77
159
  return v
78
160
 
79
161
 
@@ -86,7 +168,7 @@ def of_cast(cls: type[T], msg: Message = None) -> ta.Callable[[T], T]:
86
168
 
87
169
  def not_isinstance(v: T, spec: ta.Any, msg: Message = None) -> T: # noqa
88
170
  if _isinstance(v, _unpack_isinstance_spec(spec)):
89
- _raise(TypeError, 'Must not be instance', msg, v, spec)
171
+ _raise(TypeError, 'Must not be instance', msg, _Args(v, spec))
90
172
  return v
91
173
 
92
174
 
@@ -102,13 +184,13 @@ def of_not_isinstance(spec: ta.Any, msg: Message = None) -> ta.Callable[[T], T]:
102
184
 
103
185
  def issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: # noqa
104
186
  if not _issubclass(v, spec):
105
- _raise(TypeError, 'Must be subclass', msg, v, spec)
187
+ _raise(TypeError, 'Must be subclass', msg, _Args(v, spec))
106
188
  return v
107
189
 
108
190
 
109
191
  def not_issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: # noqa
110
192
  if _issubclass(v, spec):
111
- _raise(TypeError, 'Must not be subclass', msg, v, spec)
193
+ _raise(TypeError, 'Must not be subclass', msg, _Args(v, spec))
112
194
  return v
113
195
 
114
196
 
@@ -117,32 +199,43 @@ def not_issubclass(v: type[T], spec: ta.Any, msg: Message = None) -> type[T]: #
117
199
 
118
200
  def in_(v: T, c: ta.Container[T], msg: Message = None) -> T:
119
201
  if v not in c:
120
- _raise(ValueError, 'Must be in', msg, v, c)
202
+ _raise(ValueError, 'Must be in', msg, _Args(v, c))
121
203
  return v
122
204
 
123
205
 
124
206
  def not_in(v: T, c: ta.Container[T], msg: Message = None) -> T:
125
207
  if v in c:
126
- _raise(ValueError, 'Must not be in', msg, v, c)
208
+ _raise(ValueError, 'Must not be in', msg, _Args(v, c))
127
209
  return v
128
210
 
129
211
 
130
212
  def empty(v: SizedT, msg: Message = None) -> SizedT:
131
213
  if len(v) != 0:
132
- _raise(ValueError, 'Must be empty', msg, v)
214
+ _raise(ValueError, 'Must be empty', msg, _Args(v))
215
+ return v
216
+
217
+
218
+ def iterempty(v: ta.Iterable[T], msg: Message = None) -> ta.Iterable[T]:
219
+ it = iter(v)
220
+ try:
221
+ next(it)
222
+ except StopIteration:
223
+ pass
224
+ else:
225
+ _raise(ValueError, 'Must be empty', msg, _Args(v))
133
226
  return v
134
227
 
135
228
 
136
229
  def not_empty(v: SizedT, msg: Message = None) -> SizedT:
137
230
  if len(v) == 0:
138
- _raise(ValueError, 'Must not be empty', msg, v)
231
+ _raise(ValueError, 'Must not be empty', msg, _Args(v))
139
232
  return v
140
233
 
141
234
 
142
235
  def unique(it: ta.Iterable[T], msg: Message = None) -> ta.Iterable[T]:
143
236
  dupes = [e for e, c in collections.Counter(it).items() if c > 1]
144
237
  if dupes:
145
- _raise(ValueError, 'Must be unique', msg, it, dupes)
238
+ _raise(ValueError, 'Must be unique', msg, _Args(it, dupes))
146
239
  return it
147
240
 
148
241
 
@@ -150,7 +243,7 @@ def single(obj: ta.Iterable[T], message: Message = None) -> T:
150
243
  try:
151
244
  [value] = obj
152
245
  except ValueError:
153
- _raise(ValueError, 'Must be single', message, obj)
246
+ _raise(ValueError, 'Must be single', message, _Args(obj))
154
247
  else:
155
248
  return value
156
249
 
@@ -165,7 +258,7 @@ def optional_single(obj: ta.Iterable[T], message: Message = None) -> T | None:
165
258
  next(it)
166
259
  except StopIteration:
167
260
  return value # noqa
168
- _raise(ValueError, 'Must be empty or single', message, obj)
261
+ _raise(ValueError, 'Must be empty or single', message, _Args(obj))
169
262
 
170
263
 
171
264
  ##
@@ -173,48 +266,45 @@ def optional_single(obj: ta.Iterable[T], message: Message = None) -> T | None:
173
266
 
174
267
  def none(v: ta.Any, msg: Message = None) -> None:
175
268
  if v is not None:
176
- _raise(ValueError, 'Must be None', msg, v)
269
+ _raise(ValueError, 'Must be None', msg, _Args(v))
177
270
 
178
271
 
179
272
  def not_none(v: T | None, msg: Message = None) -> T:
180
273
  if v is None:
181
- _raise(ValueError, 'Must not be None', msg, v)
274
+ _raise(ValueError, 'Must not be None', msg, _Args(v))
182
275
  return v
183
276
 
184
277
 
185
278
  ##
186
279
 
187
280
 
188
- def equal(v: T, *os: ta.Any, msg: Message = None) -> T:
189
- for o in os:
190
- if o != v:
191
- _raise(ValueError, 'Must be equal', msg, v, os)
281
+ def equal(v: T, o: ta.Any, msg: Message = None) -> T:
282
+ if o != v:
283
+ _raise(ValueError, 'Must be equal', msg, _Args(v, o), render_fmt='%s != %s')
192
284
  return v
193
285
 
194
286
 
195
- def is_(v: T, *os: ta.Any, msg: Message = None) -> T:
196
- for o in os:
197
- if o is not v:
198
- _raise(ValueError, 'Must be the same', msg, v, os)
287
+ def is_(v: T, o: ta.Any, msg: Message = None) -> T:
288
+ if o is not v:
289
+ _raise(ValueError, 'Must be the same', msg, _Args(v, o), render_fmt='%s is not %s')
199
290
  return v
200
291
 
201
292
 
202
- def is_not(v: T, *os: ta.Any, msg: Message = None) -> T:
203
- for o in os:
204
- if o is v:
205
- _raise(ValueError, 'Must not be the same', msg, v, os)
293
+ def is_not(v: T, o: ta.Any, msg: Message = None) -> T:
294
+ if o is v:
295
+ _raise(ValueError, 'Must not be the same', msg, _Args(v, o), render_fmt='%s is %s')
206
296
  return v
207
297
 
208
298
 
209
299
  def callable(v: T, msg: Message = None) -> T: # noqa
210
300
  if not _callable(v):
211
- _raise(TypeError, 'Must be callable', msg, v)
301
+ _raise(TypeError, 'Must be callable', msg, _Args(v))
212
302
  return v # type: ignore
213
303
 
214
304
 
215
305
  def non_empty_str(v: str | None, msg: Message = None) -> str:
216
306
  if not _isinstance(v, str) or not v:
217
- _raise(ValueError, 'Must be non-empty str', msg, v)
307
+ _raise(ValueError, 'Must be non-empty str', msg, _Args(v))
218
308
  return v
219
309
 
220
310
 
@@ -0,0 +1,132 @@
1
+ import ast
2
+ import dataclasses as dc
3
+ import inspect
4
+ import pprint
5
+ import textwrap
6
+ import types
7
+ import typing as ta
8
+
9
+ from .. import lang
10
+
11
+
12
+ if ta.TYPE_CHECKING:
13
+ import executing
14
+ else:
15
+ executing = lang.proxy_import('executing')
16
+
17
+
18
+ class ArgsRenderer:
19
+ """
20
+ TODO:
21
+ - kwargs
22
+ - recursion
23
+ - whatever pytest looks like
24
+ - make sure not leaking sensitive data
25
+ """
26
+
27
+ def __init__(
28
+ self,
29
+ origin: types.TracebackType | types.FrameType | None = None,
30
+ back: int = 1,
31
+ ) -> None:
32
+ super().__init__()
33
+
34
+ self._origin = origin
35
+
36
+ self._frame: types.FrameType | None
37
+ if isinstance(origin, types.TracebackType):
38
+ self._frame = origin.tb_frame
39
+ elif isinstance(origin, types.FrameType):
40
+ self._frame = origin
41
+ elif origin is None:
42
+ frame = inspect.currentframe()
43
+ for _ in range(back + 1):
44
+ if frame is None:
45
+ break
46
+ frame = frame.f_back
47
+ self._frame = frame
48
+ else:
49
+ raise TypeError(origin)
50
+
51
+ def _get_indented_text(
52
+ self,
53
+ src: executing.Source,
54
+ node: ast.AST,
55
+ ) -> str:
56
+ result = src.asttokens().get_text(node)
57
+ if '\n' in result:
58
+ result = ' ' * node.first_token.start[1] + result # type: ignore
59
+ result = textwrap.dedent(result)
60
+ result = result.strip()
61
+ return result
62
+
63
+ def _val_to_string(self, obj: ta.Any) -> str:
64
+ s = pprint.pformat(obj)
65
+ s = s.replace('\\n', '\n')
66
+ return s
67
+
68
+ def _is_literal_expr(self, s: str) -> bool:
69
+ try:
70
+ ast.literal_eval(s)
71
+ except Exception: # noqa
72
+ return False
73
+ return True
74
+
75
+ @dc.dataclass(frozen=True)
76
+ class RenderedArg:
77
+ val: str
78
+ expr: str
79
+ is_literal_expr: bool
80
+
81
+ def __str__(self) -> str:
82
+ if self.is_literal_expr:
83
+ return self.val
84
+ else:
85
+ return f'({self.expr} = {self.val})'
86
+
87
+ def render_args(
88
+ self,
89
+ *vals: ta.Any,
90
+ ) -> ta.Sequence[RenderedArg] | None:
91
+ if self._frame is None:
92
+ return None
93
+
94
+ call_node = executing.Source.executing(self._frame).node
95
+ if not isinstance(call_node, ast.Call):
96
+ return None
97
+
98
+ source = executing.Source.for_frame(self._frame)
99
+
100
+ exprs = [
101
+ self._get_indented_text(source, arg) # noqa
102
+ for arg in call_node.args
103
+ ]
104
+ if len(exprs) != len(vals):
105
+ return None
106
+
107
+ return [
108
+ self.RenderedArg(
109
+ val=self._val_to_string(val),
110
+ expr=expr,
111
+ is_literal_expr=self._is_literal_expr(expr),
112
+ )
113
+ for val, expr in zip(vals, exprs)
114
+ ]
115
+
116
+ @classmethod
117
+ def smoketest(cls) -> bool:
118
+ def bar(z):
119
+ return z + 1
120
+
121
+ def foo(x, y):
122
+ return cls().render_args(x, y)
123
+
124
+ r = foo(1, bar(2))
125
+ if r is None:
126
+ return False
127
+
128
+ x, y = r
129
+ return (
130
+ x == cls.RenderedArg(val='1', expr='1', is_literal_expr=True) and
131
+ y == cls.RenderedArg(val='3', expr='bar(2)', is_literal_expr=False)
132
+ )