omlish 0.0.0.dev17__tar.gz → 0.0.0.dev19__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 (285) hide show
  1. {omlish-0.0.0.dev17/omlish.egg-info → omlish-0.0.0.dev19}/PKG-INFO +1 -1
  2. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/__about__.py +2 -2
  3. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/anyio.py +22 -12
  4. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/flavors.py +4 -2
  5. omlish-0.0.0.dev19/omlish/bootstrap/__init__.py +3 -0
  6. omlish-0.0.0.dev19/omlish/bootstrap/__main__.py +4 -0
  7. omlish-0.0.0.dev19/omlish/bootstrap/base.py +38 -0
  8. omlish-0.0.0.dev19/omlish/bootstrap/diag.py +128 -0
  9. omlish-0.0.0.dev19/omlish/bootstrap/harness.py +81 -0
  10. omlish-0.0.0.dev19/omlish/bootstrap/main.py +183 -0
  11. omlish-0.0.0.dev19/omlish/bootstrap/sys.py +361 -0
  12. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/defs.py +29 -5
  13. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/logs.py +1 -1
  14. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/configs.py +11 -23
  15. omlish-0.0.0.dev19/omlish/logs/noisy.py +15 -0
  16. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/multiprocessing.py +7 -3
  17. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/__init__.py +8 -3
  18. omlish-0.0.0.dev19/omlish/testing/pytest/plugins/depskip.py +81 -0
  19. omlish-0.0.0.dev19/omlish/testing/pytest/plugins/utils.py +14 -0
  20. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19/omlish.egg-info}/PKG-INFO +1 -1
  21. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/SOURCES.txt +10 -1
  22. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/pyproject.toml +1 -1
  23. omlish-0.0.0.dev17/omlish/bootstrap.py +0 -746
  24. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/LICENSE +0 -0
  25. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/MANIFEST.in +0 -0
  26. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/README.rst +0 -0
  27. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/__init__.py +0 -0
  28. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/argparse.py +0 -0
  29. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/__init__.py +0 -0
  30. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/asyncio.py +0 -0
  31. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/asyncs.py +0 -0
  32. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/bridge.py +0 -0
  33. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/trio.py +0 -0
  34. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/asyncs/trio_asyncio.py +0 -0
  35. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/c3.py +0 -0
  36. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/cached.py +0 -0
  37. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/check.py +0 -0
  38. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/__init__.py +0 -0
  39. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/_abc.py +0 -0
  40. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/_io_abc.py +0 -0
  41. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/__init__.py +0 -0
  42. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/descriptor.py +0 -0
  43. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/impl.py +0 -0
  44. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/cache/types.py +0 -0
  45. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/coerce.py +0 -0
  46. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/exceptions.py +0 -0
  47. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/frozen.py +0 -0
  48. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/identity.py +0 -0
  49. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/indexed.py +0 -0
  50. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/mappings.py +0 -0
  51. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/ordered.py +0 -0
  52. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/persistent.py +0 -0
  53. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/skiplist.py +0 -0
  54. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/sorted.py +0 -0
  55. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/treap.py +0 -0
  56. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/treapmap.py +0 -0
  57. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/unmodifiable.py +0 -0
  58. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/collections/utils.py +0 -0
  59. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/concurrent.py +0 -0
  60. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/__init__.py +0 -0
  61. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/classes.py +0 -0
  62. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/flattening.py +0 -0
  63. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/configs/strings.py +0 -0
  64. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/__init__.py +0 -0
  65. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/__init__.py +0 -0
  66. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/api.py +0 -0
  67. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/as_.py +0 -0
  68. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/copy.py +0 -0
  69. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/descriptors.py +0 -0
  70. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/exceptions.py +0 -0
  71. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/fields.py +0 -0
  72. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/frozen.py +0 -0
  73. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/hashing.py +0 -0
  74. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/init.py +0 -0
  75. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/internals.py +0 -0
  76. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/main.py +0 -0
  77. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/metaclass.py +0 -0
  78. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/metadata.py +0 -0
  79. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/order.py +0 -0
  80. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/params.py +0 -0
  81. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/processing.py +0 -0
  82. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/reflect.py +0 -0
  83. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/replace.py +0 -0
  84. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/repr.py +0 -0
  85. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/simple.py +0 -0
  86. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/slots.py +0 -0
  87. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/impl/utils.py +0 -0
  88. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dataclasses/utils.py +0 -0
  89. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/datetimes.py +0 -0
  90. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/__init__.py +0 -0
  91. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/procfs.py +0 -0
  92. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/procstats.py +0 -0
  93. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/ps.py +0 -0
  94. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/pydevd.py +0 -0
  95. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/__init__.py +0 -0
  96. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/__main__.py +0 -0
  97. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/console.py +0 -0
  98. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/replserver/server.py +0 -0
  99. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/diag/threads.py +0 -0
  100. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/__init__.py +0 -0
  101. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/_dispatch2.py +0 -0
  102. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/_dispatch3.py +0 -0
  103. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/dispatch.py +0 -0
  104. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/functions.py +0 -0
  105. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dispatch/methods.py +0 -0
  106. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/docker.py +0 -0
  107. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/dynamic.py +0 -0
  108. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/fnpairs.py +0 -0
  109. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/__init__.py +0 -0
  110. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/dotenv.py +0 -0
  111. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/json.py +0 -0
  112. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/props.py +0 -0
  113. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/formats/yaml.py +0 -0
  114. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/__init__.py +0 -0
  115. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dags.py +0 -0
  116. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/domination.py +0 -0
  117. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/__init__.py +0 -0
  118. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/items.py +0 -0
  119. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/rendering.py +0 -0
  120. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/dot/utils.py +0 -0
  121. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/graphs/trees.py +0 -0
  122. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/__init__.py +0 -0
  123. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/asgi.py +0 -0
  124. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/collections.py +0 -0
  125. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/consts.py +0 -0
  126. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/cookies.py +0 -0
  127. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/dates.py +0 -0
  128. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/encodings.py +0 -0
  129. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/json.py +0 -0
  130. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/sessions.py +0 -0
  131. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/http/wsgi.py +0 -0
  132. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/__init__.py +0 -0
  133. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/binder.py +0 -0
  134. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/bindings.py +0 -0
  135. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/eagers.py +0 -0
  136. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/elements.py +0 -0
  137. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/exceptions.py +0 -0
  138. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/__init__.py +0 -0
  139. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/bindings.py +0 -0
  140. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/elements.py +0 -0
  141. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/injector.py +0 -0
  142. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/inspect.py +0 -0
  143. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/multis.py +0 -0
  144. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/origins.py +0 -0
  145. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/privates.py +0 -0
  146. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/providers.py +0 -0
  147. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/proxy.py +0 -0
  148. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/impl/scopes.py +0 -0
  149. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/injector.py +0 -0
  150. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/inspect.py +0 -0
  151. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/keys.py +0 -0
  152. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/listeners.py +0 -0
  153. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/managed.py +0 -0
  154. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/multis.py +0 -0
  155. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/origins.py +0 -0
  156. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/overrides.py +0 -0
  157. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/privates.py +0 -0
  158. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/providers.py +0 -0
  159. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/scopes.py +0 -0
  160. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/types.py +0 -0
  161. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/inject/utils.py +0 -0
  162. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/iterators.py +0 -0
  163. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/__init__.py +0 -0
  164. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/cached.py +0 -0
  165. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/__init__.py +0 -0
  166. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/abstract.py +0 -0
  167. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/restrict.py +0 -0
  168. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/simple.py +0 -0
  169. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/classes/virtual.py +0 -0
  170. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/clsdct.py +0 -0
  171. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/cmp.py +0 -0
  172. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/contextmanagers.py +0 -0
  173. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/descriptors.py +0 -0
  174. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/exceptions.py +0 -0
  175. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/functions.py +0 -0
  176. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/imports.py +0 -0
  177. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/iterables.py +0 -0
  178. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/maybes.py +0 -0
  179. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/objects.py +0 -0
  180. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/resolving.py +0 -0
  181. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/strings.py +0 -0
  182. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/sys.py +0 -0
  183. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/timeouts.py +0 -0
  184. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lang/typing.py +0 -0
  185. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/libc.py +0 -0
  186. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/__init__.py +0 -0
  187. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/abstract.py +0 -0
  188. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/base.py +0 -0
  189. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/contextmanagers.py +0 -0
  190. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/controller.py +0 -0
  191. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/manager.py +0 -0
  192. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/states.py +0 -0
  193. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lifecycles/transitions.py +0 -0
  194. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/__init__.py +0 -0
  195. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/cached.py +0 -0
  196. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/check.py +0 -0
  197. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/contextmanagers.py +0 -0
  198. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/json.py +0 -0
  199. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/marshal.py +0 -0
  200. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/reflect.py +0 -0
  201. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/runtime.py +0 -0
  202. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/secrets.py +0 -0
  203. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/strings.py +0 -0
  204. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/lite/subprocesses.py +0 -0
  205. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/__init__.py +0 -0
  206. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/_abc.py +0 -0
  207. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/formatters.py +0 -0
  208. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/logs/utils.py +0 -0
  209. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/__init__.py +0 -0
  210. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/any.py +0 -0
  211. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/base.py +0 -0
  212. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/base64.py +0 -0
  213. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/dataclasses.py +0 -0
  214. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/datetimes.py +0 -0
  215. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/enums.py +0 -0
  216. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/exceptions.py +0 -0
  217. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/factories.py +0 -0
  218. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/forbidden.py +0 -0
  219. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/global_.py +0 -0
  220. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/iterables.py +0 -0
  221. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/mappings.py +0 -0
  222. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/maybes.py +0 -0
  223. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/naming.py +0 -0
  224. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/numbers.py +0 -0
  225. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/objects.py +0 -0
  226. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/optionals.py +0 -0
  227. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/polymorphism.py +0 -0
  228. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/primitives.py +0 -0
  229. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/registries.py +0 -0
  230. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/standard.py +0 -0
  231. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/utils.py +0 -0
  232. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/uuids.py +0 -0
  233. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/marshal/values.py +0 -0
  234. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/matchfns.py +0 -0
  235. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/math.py +0 -0
  236. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/os.py +0 -0
  237. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/__init__.py +0 -0
  238. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/isinstance.py +0 -0
  239. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/ops.py +0 -0
  240. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/subst.py +0 -0
  241. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/reflect/types.py +0 -0
  242. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/runmodule.py +0 -0
  243. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/__init__.py +0 -0
  244. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/crypto.py +0 -0
  245. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/marshal.py +0 -0
  246. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/openssl.py +0 -0
  247. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/passwords.py +0 -0
  248. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/secrets.py +0 -0
  249. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/secrets/subprocesses.py +0 -0
  250. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/__init__.py +0 -0
  251. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/_abc.py +0 -0
  252. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/asyncs.py +0 -0
  253. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/dbs.py +0 -0
  254. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/duckdb.py +0 -0
  255. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/exprs.py +0 -0
  256. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/secrets.py +0 -0
  257. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sql/sqlean.py +0 -0
  258. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/stats.py +0 -0
  259. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/sync.py +0 -0
  260. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/term.py +0 -0
  261. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/__init__.py +0 -0
  262. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/__init__.py +0 -0
  263. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/helpers.py +0 -0
  264. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/inject/__init__.py +0 -0
  265. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/inject/harness.py +0 -0
  266. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/marks.py +0 -0
  267. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/_registry.py +0 -0
  268. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/asyncs.py +0 -0
  269. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/logging.py +0 -0
  270. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/managermarks.py +0 -0
  271. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/pydevd.py +0 -0
  272. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/repeat.py +0 -0
  273. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/skips.py +0 -0
  274. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/spacing.py +0 -0
  275. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/pytest/plugins/switches.py +0 -0
  276. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/testing/testing.py +0 -0
  277. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/__init__.py +0 -0
  278. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/delimit.py +0 -0
  279. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/glyphsplit.py +0 -0
  280. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/indent.py +0 -0
  281. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish/text/parts.py +0 -0
  282. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/dependency_links.txt +0 -0
  283. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/requires.txt +0 -0
  284. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/omlish.egg-info/top_level.txt +0 -0
  285. {omlish-0.0.0.dev17 → omlish-0.0.0.dev19}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev17
3
+ Version: 0.0.0.dev19
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -1,5 +1,5 @@
1
- __version__ = '0.0.0.dev17'
2
- __revision__ = 'c238de47faafaf823b552b9e5cf22e47f5c9cd2b'
1
+ __version__ = '0.0.0.dev19'
2
+ __revision__ = '509bb451054d2d955e55cbcf1f271a9166a904eb'
3
3
 
4
4
 
5
5
  #
@@ -37,6 +37,12 @@ from .. import lang
37
37
 
38
38
  T = ta.TypeVar('T')
39
39
 
40
+ MemoryObjectReceiveStream: ta.TypeAlias = anyio.streams.memory.MemoryObjectReceiveStream
41
+ MemoryObjectSendStream: ta.TypeAlias = anyio.streams.memory.MemoryObjectSendStream
42
+
43
+ StapledByteStream: ta.TypeAlias = anyio.streams.stapled.StapledByteStream
44
+ StapledObjectStream: ta.TypeAlias = anyio.streams.stapled.StapledObjectStream
45
+
40
46
 
41
47
  ##
42
48
 
@@ -130,39 +136,43 @@ def get_current_backend_task() -> BackendTask | None:
130
136
  def split_memory_object_streams(
131
137
  *args: anyio.create_memory_object_stream[T],
132
138
  ) -> tuple[
133
- anyio.streams.memory.MemoryObjectSendStream[T],
134
- anyio.streams.memory.MemoryObjectReceiveStream[T],
139
+ MemoryObjectSendStream[T],
140
+ MemoryObjectReceiveStream[T],
135
141
  ]:
136
142
  [tup] = args
137
143
  return tup
138
144
 
139
145
 
146
+ def create_stapled_memory_object_stream(max_buffer_size: float = 0) -> StapledObjectStream:
147
+ return StapledObjectStream(*anyio.create_memory_object_stream(max_buffer_size))
148
+
149
+
140
150
  # FIXME: https://github.com/python/mypy/issues/15238
141
151
  # FIXME: https://youtrack.jetbrains.com/issues?q=tag:%20%7BPEP%20695%7D
142
152
  def create_memory_object_stream[T](max_buffer_size: float = 0) -> tuple[
143
- anyio.streams.memory.MemoryObjectSendStream[T],
144
- anyio.streams.memory.MemoryObjectReceiveStream[T],
153
+ MemoryObjectSendStream[T],
154
+ MemoryObjectReceiveStream[T],
145
155
  ]:
146
156
  return anyio.create_memory_object_stream[T](max_buffer_size) # noqa
147
157
 
148
158
 
149
159
  def staple_memory_object_stream(
150
160
  *args: anyio.create_memory_object_stream[T],
151
- ) -> anyio.streams.stapled.StapledObjectStream[T]:
161
+ ) -> StapledObjectStream[T]:
152
162
  send, receive = args
153
- return anyio.streams.stapled.StapledObjectStream(
154
- check.isinstance(send, anyio.streams.memory.MemoryObjectSendStream), # type: ignore
155
- check.isinstance(receive, anyio.streams.memory.MemoryObjectReceiveStream), # type: ignore
163
+ return StapledObjectStream(
164
+ check.isinstance(send, MemoryObjectSendStream), # type: ignore
165
+ check.isinstance(receive, MemoryObjectReceiveStream), # type: ignore
156
166
  )
157
167
 
158
168
 
159
169
  # FIXME: https://github.com/python/mypy/issues/15238
160
170
  # FIXME: https://youtrack.jetbrains.com/issues?q=tag:%20%7BPEP%20695%7D
161
- def staple_memory_object_stream2[T](max_buffer_size: float = 0) -> anyio.streams.stapled.StapledObjectStream[T]:
171
+ def staple_memory_object_stream2[T](max_buffer_size: float = 0) -> StapledObjectStream[T]:
162
172
  send, receive = anyio.create_memory_object_stream[T](max_buffer_size)
163
- return anyio.streams.stapled.StapledObjectStream(
164
- check.isinstance(send, anyio.streams.memory.MemoryObjectSendStream), # type: ignore
165
- check.isinstance(receive, anyio.streams.memory.MemoryObjectReceiveStream), # type: ignore
173
+ return StapledObjectStream(
174
+ check.isinstance(send, MemoryObjectSendStream), # type: ignore
175
+ check.isinstance(receive, MemoryObjectReceiveStream), # type: ignore
166
176
  )
167
177
 
168
178
 
@@ -1,8 +1,8 @@
1
1
  """
2
+ Tools for working with the different async loop implementations - currently anyio, asyncio, trio.
3
+
2
4
  TODO:
3
- - 'get current'? -> sniffio..
4
5
  - mark whole class / module?
5
- - sync/greenlet bridge
6
6
  """
7
7
  import abc
8
8
  import dataclasses as dc
@@ -73,11 +73,13 @@ def _get_module_flavor(p: str) -> Flavor | None:
73
73
  return _MODULE_FLAVOR_CACHE[p]
74
74
  except KeyError:
75
75
  pass
76
+
76
77
  pf: Flavor | None = None
77
78
  for cp, cf in PACKAGE_FLAVORS.items():
78
79
  if p.startswith(cp) and (len(cp) == len(p) or p[len(cp)] == '.'):
79
80
  pf = cf
80
81
  break
82
+
81
83
  _MODULE_FLAVOR_CACHE[p] = pf
82
84
  return pf
83
85
 
@@ -0,0 +1,3 @@
1
+ from .harness import ( # noqa
2
+ bootstrap,
3
+ )
@@ -0,0 +1,4 @@
1
+ if __name__ == '__main__':
2
+ from .main import _main
3
+
4
+ _main()
@@ -0,0 +1,38 @@
1
+ import abc
2
+ import dataclasses as dc
3
+ import typing as ta
4
+
5
+
6
+ BootstrapConfigT = ta.TypeVar('BootstrapConfigT', bound='Bootstrap.Config')
7
+
8
+
9
+ ##
10
+
11
+
12
+ class Bootstrap(abc.ABC, ta.Generic[BootstrapConfigT]):
13
+ @dc.dataclass(frozen=True)
14
+ class Config(abc.ABC): # noqa
15
+ pass
16
+
17
+ def __init__(self, config: BootstrapConfigT) -> None:
18
+ super().__init__()
19
+ self._config = config
20
+
21
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
22
+ super().__init_subclass__(**kwargs)
23
+ if not cls.__name__.endswith('Bootstrap'):
24
+ raise NameError(cls)
25
+ if abc.ABC not in cls.__bases__ and not issubclass(cls.__dict__['Config'], Bootstrap.Config):
26
+ raise TypeError(cls)
27
+
28
+
29
+ class SimpleBootstrap(Bootstrap[BootstrapConfigT], abc.ABC):
30
+ @abc.abstractmethod
31
+ def run(self) -> None:
32
+ raise NotImplementedError
33
+
34
+
35
+ class ContextBootstrap(Bootstrap[BootstrapConfigT], abc.ABC):
36
+ @abc.abstractmethod
37
+ def enter(self) -> ta.ContextManager[None]:
38
+ raise NotImplementedError
@@ -0,0 +1,128 @@
1
+ # ruff: noqa: UP007
2
+ import contextlib
3
+ import dataclasses as dc
4
+ import signal
5
+ import sys
6
+ import typing as ta
7
+
8
+ from .. import lang
9
+ from .base import Bootstrap
10
+ from .base import ContextBootstrap
11
+
12
+
13
+ if ta.TYPE_CHECKING:
14
+ import cProfile # noqa
15
+ import pstats
16
+
17
+ from ..diag import threads as diagt
18
+
19
+ else:
20
+ cProfile = lang.proxy_import('cProfile') # noqa
21
+ pstats = lang.proxy_import('pstats')
22
+
23
+ diagt = lang.proxy_import('..diag.threads', __package__)
24
+
25
+
26
+ ##
27
+
28
+
29
+ class ProfilingBootstrap(ContextBootstrap['ProfilingBootstrap.Config']):
30
+ @dc.dataclass(frozen=True)
31
+ class Config(Bootstrap.Config):
32
+ enable: bool = False
33
+ builtins: bool = True
34
+
35
+ outfile: ta.Optional[str] = None
36
+
37
+ print: bool = False
38
+ sort: str = 'cumtime'
39
+ topn: int = 100
40
+
41
+ @contextlib.contextmanager
42
+ def enter(self) -> ta.Iterator[None]:
43
+ if not self._config.enable:
44
+ yield
45
+ return
46
+
47
+ prof = cProfile.Profile()
48
+ prof.enable()
49
+ try:
50
+ yield
51
+
52
+ finally:
53
+ prof.disable()
54
+ prof.create_stats()
55
+
56
+ if self._config.print:
57
+ pstats.Stats(prof) \
58
+ .strip_dirs() \
59
+ .sort_stats(self._config.sort) \
60
+ .print_stats(self._config.topn)
61
+
62
+ if self._config.outfile is not None:
63
+ prof.dump_stats(self._config.outfile)
64
+
65
+
66
+ ##
67
+
68
+
69
+ class ThreadDumpBootstrap(ContextBootstrap['ThreadDumpBootstrap.Config']):
70
+ @dc.dataclass(frozen=True)
71
+ class Config(Bootstrap.Config):
72
+ interval_s: ta.Optional[float] = None
73
+
74
+ on_sigquit: bool = False
75
+
76
+ @contextlib.contextmanager
77
+ def enter(self) -> ta.Iterator[None]:
78
+ if self._config.interval_s:
79
+ tdt = diagt.create_thread_dump_thread(
80
+ interval_s=self._config.interval_s,
81
+ start=True,
82
+ )
83
+ else:
84
+ tdt = None
85
+
86
+ if self._config.on_sigquit:
87
+ dump_threads_str = diagt.dump_threads_str
88
+
89
+ def handler(signum, frame):
90
+ print(dump_threads_str(), file=sys.stderr)
91
+
92
+ prev_sq = lang.just(signal.signal(signal.SIGQUIT, handler))
93
+ else:
94
+ prev_sq = lang.empty()
95
+
96
+ try:
97
+ yield
98
+
99
+ finally:
100
+ if tdt is not None:
101
+ tdt.stop_nowait()
102
+
103
+ if prev_sq.present:
104
+ signal.signal(signal.SIGQUIT, prev_sq.must())
105
+
106
+
107
+ ##
108
+
109
+
110
+ class TimebombBootstrap(ContextBootstrap['TimebombBootstrap.Config']):
111
+ @dc.dataclass(frozen=True)
112
+ class Config(Bootstrap.Config):
113
+ delay_s: ta.Optional[float] = None
114
+
115
+ @contextlib.contextmanager
116
+ def enter(self) -> ta.Iterator[None]:
117
+ if not self._config.delay_s:
118
+ yield
119
+ return
120
+
121
+ tbt = diagt.create_timebomb_thread(
122
+ self._config.delay_s,
123
+ start=True,
124
+ )
125
+ try:
126
+ yield
127
+ finally:
128
+ tbt.stop_nowait()
@@ -0,0 +1,81 @@
1
+ """
2
+ TODO:
3
+ - more logging options
4
+ - a more powerful interface would be run_fn_with_bootstrap..
5
+ - ./python -m gprof2dot -f pstats prof.pstats | dot -Tpdf -o prof.pstats.pdf && open prof.pstats.pdf
6
+ - multiprocess profiling - afterfork, suffix with pid
7
+
8
+ TODO diag:
9
+ - yappi
10
+ - stackscope
11
+ - https://github.com/pythonspeed/filprofiler
12
+ - https://pypi.org/project/guppy3/
13
+ - https://pypi.org/project/memory-profiler/
14
+ - https://pypi.org/project/Pympler/
15
+
16
+ TODO new items:
17
+ - pydevd connect-back
18
+ - debugging / pdb
19
+ - repl server
20
+ - packaging fixups
21
+ - daemonize ( https://github.com/thesharp/daemonize/blob/master/daemonize.py )
22
+ """
23
+ # ruff: noqa: UP006
24
+ import contextlib
25
+ import typing as ta
26
+
27
+ from .. import lang
28
+ from . import diag # noqa
29
+ from . import sys # noqa
30
+ from .base import Bootstrap
31
+ from .base import ContextBootstrap
32
+ from .base import SimpleBootstrap
33
+
34
+
35
+ ##
36
+
37
+
38
+ BOOTSTRAP_TYPES_BY_NAME: ta.Mapping[str, ta.Type[Bootstrap]] = { # noqa
39
+ lang.snake_case(cls.__name__[:-len('Bootstrap')]): cls
40
+ for cls in lang.deep_subclasses(Bootstrap)
41
+ if not lang.is_abstract_class(cls)
42
+ }
43
+
44
+ BOOTSTRAP_TYPES_BY_CONFIG_TYPE: ta.Mapping[ta.Type[Bootstrap.Config], ta.Type[Bootstrap]] = {
45
+ cls.Config: cls
46
+ for cls in BOOTSTRAP_TYPES_BY_NAME.values()
47
+ }
48
+
49
+
50
+ ##
51
+
52
+
53
+ class BootstrapHarness:
54
+ def __init__(self, lst: ta.Sequence[Bootstrap]) -> None:
55
+ super().__init__()
56
+ self._lst = lst
57
+
58
+ @contextlib.contextmanager
59
+ def __call__(self) -> ta.Iterator[None]:
60
+ with contextlib.ExitStack() as es:
61
+ for c in self._lst:
62
+ if isinstance(c, SimpleBootstrap):
63
+ c.run()
64
+ elif isinstance(c, ContextBootstrap):
65
+ es.enter_context(c.enter())
66
+ else:
67
+ raise TypeError(c)
68
+
69
+ yield
70
+
71
+
72
+ ##
73
+
74
+
75
+ @contextlib.contextmanager
76
+ def bootstrap(*cfgs: Bootstrap.Config) -> ta.Iterator[None]:
77
+ with BootstrapHarness([
78
+ BOOTSTRAP_TYPES_BY_CONFIG_TYPE[type(c)](c)
79
+ for c in cfgs
80
+ ])():
81
+ yield
@@ -0,0 +1,183 @@
1
+ # ruff: noqa: UP006 UP007
2
+ import argparse
3
+ import dataclasses as dc
4
+ import io
5
+ import itertools
6
+ import sys
7
+ import typing as ta
8
+
9
+ from .. import lang
10
+ from .base import Bootstrap
11
+ from .harness import BOOTSTRAP_TYPES_BY_NAME
12
+ from .harness import bootstrap
13
+
14
+
15
+ if ta.TYPE_CHECKING:
16
+ import runpy
17
+
18
+ else:
19
+ runpy = lang.proxy_import('runpy')
20
+
21
+
22
+ ##
23
+
24
+
25
+ class _OrderedArgsAction(argparse.Action):
26
+ def __call__(self, parser, namespace, values, option_string=None):
27
+ if 'ordered_args' not in namespace:
28
+ setattr(namespace, 'ordered_args', [])
29
+ if self.const is not None:
30
+ value = self.const
31
+ else:
32
+ value = values
33
+ namespace.ordered_args.append((self.dest, value))
34
+
35
+
36
+ def _or_opt(ty):
37
+ return (ty, ta.Optional[ty])
38
+
39
+
40
+ def _int_or_str(v):
41
+ try:
42
+ return int(v)
43
+ except ValueError:
44
+ return v
45
+
46
+
47
+ def _add_arguments(parser: argparse.ArgumentParser) -> None:
48
+ # ta.Optional[ta.Mapping[str, ta.Tuple[ta.Optional[int], ta.Optional[int]]]]
49
+
50
+ for cname, cls in BOOTSTRAP_TYPES_BY_NAME.items():
51
+ for fld in dc.fields(cls.Config):
52
+ aname = f'--{cname}:{fld.name}'
53
+ kw: ta.Dict[str, ta.Any] = {}
54
+
55
+ if fld.type in _or_opt(str):
56
+ pass
57
+ elif fld.type in _or_opt(bool):
58
+ kw.update(const=True, nargs=0)
59
+ elif fld.type in _or_opt(int):
60
+ kw.update(type=int)
61
+ elif fld.type in _or_opt(float):
62
+ kw.update(type=float)
63
+ elif fld.type in _or_opt(ta.Union[int, str]):
64
+ kw.update(type=_int_or_str)
65
+
66
+ elif fld.type in (
67
+ *_or_opt(ta.Sequence[str]),
68
+ *_or_opt(ta.Mapping[str, ta.Optional[str]]),
69
+ *_or_opt(ta.Mapping[int, ta.Union[int, str, None]]),
70
+ *_or_opt(ta.Mapping[str, ta.Tuple[ta.Optional[int], ta.Optional[int]]]),
71
+ ):
72
+ if aname[-1] != 's':
73
+ raise NameError(aname)
74
+ aname = aname[:-1]
75
+
76
+ else:
77
+ raise TypeError(fld)
78
+
79
+ parser.add_argument(aname, action=_OrderedArgsAction, **kw)
80
+
81
+
82
+ def _process_arguments(args: ta.Any) -> ta.Sequence[Bootstrap.Config]:
83
+ if not (oa := getattr(args, 'ordered_args', None)):
84
+ return []
85
+
86
+ cfgs: ta.List[Bootstrap.Config] = []
87
+
88
+ for cname, cargs in [
89
+ (n, list(g))
90
+ for n, g in
91
+ itertools.groupby(oa, key=lambda s: s[0].partition(':')[0])
92
+ ]:
93
+ ccls = BOOTSTRAP_TYPES_BY_NAME[cname].Config
94
+ flds = {f.name: f for f in dc.fields(ccls)}
95
+
96
+ kw: ta.Dict[str, ta.Any] = {}
97
+ for aname, aval in cargs:
98
+ k = aname.partition(':')[2]
99
+
100
+ if k not in flds:
101
+ k += 's'
102
+ fld = flds[k]
103
+
104
+ if fld.type in _or_opt(ta.Sequence[str]):
105
+ kw.setdefault(k, []).append(aval)
106
+
107
+ elif fld.type in _or_opt(ta.Mapping[str, ta.Optional[str]]):
108
+ if '=' not in aval:
109
+ kw.setdefault(k, {})[aval] = None
110
+ else:
111
+ ek, _, ev = aval.partition('=')
112
+ kw.setdefault(k, {})[ek] = ev
113
+
114
+ elif fld.type in _or_opt(ta.Mapping[int, ta.Union[int, str, None]]):
115
+ fk, _, fv = aval.partition('=')
116
+ if not fv:
117
+ kw.setdefault(k, {})[int(fk)] = None
118
+ else:
119
+ kw.setdefault(k, {})[int(fk)] = _int_or_str(fv)
120
+
121
+ elif fld.type in _or_opt(ta.Mapping[str, ta.Tuple[ta.Optional[int], ta.Optional[int]]]):
122
+ fk, _, fv = aval.partition('=')
123
+ if ',' in fv:
124
+ tl, tr = fv.split(',')
125
+ else:
126
+ tl, tr = None, None
127
+ kw.setdefault(k, {})[fk] = (_int_or_str(tl) if tl else None, _int_or_str(tr) if tr else None)
128
+
129
+ else:
130
+ raise TypeError(fld)
131
+
132
+ else:
133
+ kw[k] = aval
134
+
135
+ cfg = ccls(**kw)
136
+ cfgs.append(cfg)
137
+
138
+ return cfgs
139
+
140
+
141
+ ##
142
+
143
+
144
+ def _main() -> int:
145
+ parser = argparse.ArgumentParser()
146
+
147
+ _add_arguments(parser)
148
+
149
+ parser.add_argument('-m', '--module', action='store_true')
150
+ parser.add_argument('target')
151
+ parser.add_argument('args', nargs=argparse.REMAINDER)
152
+
153
+ args = parser.parse_args()
154
+ cfgs = _process_arguments(args)
155
+
156
+ with bootstrap(*cfgs):
157
+ tgt = args.target
158
+
159
+ if args.module:
160
+ sys.argv = [tgt, *(args.args or ())]
161
+ runpy._run_module_as_main(tgt) # type: ignore # noqa
162
+
163
+ else:
164
+ with io.open_code(tgt) as fp:
165
+ src = fp.read()
166
+
167
+ ns = dict(
168
+ __name__='__main__',
169
+ __file__=tgt,
170
+ __builtins__=__builtins__,
171
+ __spec__=None,
172
+ )
173
+
174
+ import __main__ # noqa
175
+ __main__.__dict__.clear()
176
+ __main__.__dict__.update(ns)
177
+ exec(compile(src, tgt, 'exec'), __main__.__dict__, __main__.__dict__)
178
+
179
+ return 0
180
+
181
+
182
+ if __name__ == '__main__':
183
+ sys.exit(_main())