omlish 0.0.0.dev3__tar.gz → 0.0.0.dev5__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.

Potentially problematic release.


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

Files changed (225) hide show
  1. {omlish-0.0.0.dev3/omlish.egg-info → omlish-0.0.0.dev5}/PKG-INFO +4 -1
  2. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/__about__.py +1 -1
  3. omlish-0.0.0.dev5/omlish/__init__.py +8 -0
  4. omlish-0.0.0.dev5/omlish/asyncs/__init__.py +35 -0
  5. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/asyncs/anyio.py +66 -0
  6. omlish-0.0.0.dev5/omlish/asyncs/flavors.py +227 -0
  7. omlish-0.0.0.dev5/omlish/asyncs/trio_asyncio.py +47 -0
  8. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/c3.py +1 -1
  9. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/cached.py +1 -2
  10. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/__init__.py +4 -1
  11. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/cache/impl.py +1 -1
  12. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/utils.py +38 -6
  13. omlish-0.0.0.dev5/omlish/configs/__init__.py +5 -0
  14. omlish-0.0.0.dev5/omlish/configs/classes.py +53 -0
  15. omlish-0.0.0.dev5/omlish/configs/dotenv.py +586 -0
  16. omlish-0.0.0.dev5/omlish/configs/props.py +604 -0
  17. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/api.py +1 -1
  18. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/fields.py +1 -0
  19. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/main.py +1 -0
  20. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/metaclass.py +6 -1
  21. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/reflect.py +15 -2
  22. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/defs.py +1 -1
  23. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/diag/procfs.py +29 -1
  24. omlish-0.0.0.dev5/omlish/diag/procstats.py +32 -0
  25. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/diag/replserver/console.py +3 -3
  26. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/diag/replserver/server.py +6 -5
  27. omlish-0.0.0.dev5/omlish/diag/threads.py +86 -0
  28. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/docker.py +19 -0
  29. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dynamic.py +2 -2
  30. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/fnpairs.py +121 -24
  31. omlish-0.0.0.dev5/omlish/graphs/dags.py +113 -0
  32. omlish-0.0.0.dev5/omlish/graphs/domination.py +268 -0
  33. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/graphs/trees.py +2 -2
  34. omlish-0.0.0.dev5/omlish/http/__init__.py +25 -0
  35. omlish-0.0.0.dev5/omlish/http/asgi.py +131 -0
  36. omlish-0.0.0.dev5/omlish/http/consts.py +47 -0
  37. omlish-0.0.0.dev5/omlish/http/cookies.py +194 -0
  38. omlish-0.0.0.dev5/omlish/http/dates.py +70 -0
  39. omlish-0.0.0.dev5/omlish/http/encodings.py +6 -0
  40. omlish-0.0.0.dev5/omlish/http/json.py +273 -0
  41. omlish-0.0.0.dev5/omlish/http/sessions.py +197 -0
  42. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/__init__.py +8 -2
  43. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/bindings.py +3 -3
  44. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/exceptions.py +3 -3
  45. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/impl/elements.py +46 -25
  46. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/impl/injector.py +8 -5
  47. omlish-0.0.0.dev5/omlish/inject/impl/multis.py +74 -0
  48. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/impl/providers.py +19 -39
  49. {omlish-0.0.0.dev3/omlish/inject → omlish-0.0.0.dev5/omlish/inject/impl}/proxy.py +2 -2
  50. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/impl/scopes.py +4 -2
  51. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/injector.py +1 -0
  52. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/keys.py +3 -9
  53. omlish-0.0.0.dev5/omlish/inject/multis.py +70 -0
  54. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/providers.py +23 -23
  55. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/scopes.py +7 -3
  56. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/types.py +0 -8
  57. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/iterators.py +13 -0
  58. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/json.py +138 -1
  59. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/__init__.py +8 -0
  60. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/classes/restrict.py +1 -1
  61. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/classes/virtual.py +2 -2
  62. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/contextmanagers.py +64 -0
  63. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/datetimes.py +6 -5
  64. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/functions.py +10 -0
  65. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/imports.py +11 -2
  66. omlish-0.0.0.dev5/omlish/lang/sys.py +7 -0
  67. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/typing.py +1 -0
  68. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/logs/utils.py +1 -1
  69. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/datetimes.py +1 -1
  70. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/reflect.py +8 -2
  71. omlish-0.0.0.dev5/omlish/sql/__init__.py +9 -0
  72. omlish-0.0.0.dev5/omlish/sql/asyncs.py +148 -0
  73. omlish-0.0.0.dev5/omlish/sync.py +70 -0
  74. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/term.py +6 -1
  75. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pydevd.py +2 -0
  76. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/__init__.py +5 -0
  77. omlish-0.0.0.dev5/omlish/testing/pytest/helpers.py +11 -0
  78. omlish-0.0.0.dev3/omlish/testing/pytest/helpers.py → omlish-0.0.0.dev5/omlish/testing/pytest/marks.py +22 -9
  79. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/__init__.py +2 -0
  80. omlish-0.0.0.dev5/omlish/testing/pytest/plugins/managermarks.py +60 -0
  81. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/testing.py +10 -0
  82. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/text/delimit.py +4 -0
  83. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5/omlish.egg-info}/PKG-INFO +4 -1
  84. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish.egg-info/SOURCES.txt +22 -1
  85. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish.egg-info/requires.txt +4 -0
  86. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/pyproject.toml +31 -18
  87. omlish-0.0.0.dev3/omlish/asyncs/__init__.py +0 -17
  88. omlish-0.0.0.dev3/omlish/configs/props.py +0 -64
  89. omlish-0.0.0.dev3/omlish/http/__init__.py +0 -0
  90. omlish-0.0.0.dev3/omlish/http/consts.py +0 -20
  91. omlish-0.0.0.dev3/omlish/inject/impl/__init__.py +0 -0
  92. omlish-0.0.0.dev3/omlish/sql/__init__.py +0 -0
  93. omlish-0.0.0.dev3/omlish/text/__init__.py +0 -0
  94. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/LICENSE +0 -0
  95. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/MANIFEST.in +0 -0
  96. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/README.md +0 -0
  97. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/argparse.py +0 -0
  98. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/asyncs/asyncio.py +0 -0
  99. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/asyncs/asyncs.py +0 -0
  100. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/asyncs/futures.py +0 -0
  101. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/asyncs/trio.py +0 -0
  102. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/check.py +0 -0
  103. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/_abc.py +0 -0
  104. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/_io_abc.py +0 -0
  105. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/cache/__init__.py +0 -0
  106. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/cache/descriptor.py +0 -0
  107. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/cache/types.py +0 -0
  108. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/coerce.py +0 -0
  109. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/frozen.py +0 -0
  110. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/identity.py +0 -0
  111. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/indexed.py +1 -1
  112. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/mappings.py +0 -0
  113. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/ordered.py +0 -0
  114. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/persistent.py +0 -0
  115. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/skiplist.py +0 -0
  116. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/sorted.py +0 -0
  117. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/treap.py +0 -0
  118. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/treapmap.py +0 -0
  119. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/collections/unmodifiable.py +0 -0
  120. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/configs/flattening.py +0 -0
  121. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/__init__.py +0 -0
  122. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/__init__.py +0 -0
  123. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/as_.py +1 -1
  124. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/exceptions.py +0 -0
  125. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/frozen.py +0 -0
  126. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/hashing.py +0 -0
  127. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/init.py +1 -1
  128. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/internals.py +0 -0
  129. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/metadata.py +0 -0
  130. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/order.py +1 -1
  131. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/params.py +0 -0
  132. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/processing.py +0 -0
  133. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/replace.py +0 -0
  134. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/repr.py +0 -0
  135. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/simple.py +0 -0
  136. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/slots.py +0 -0
  137. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dataclasses/impl/utils.py +0 -0
  138. {omlish-0.0.0.dev3/omlish → omlish-0.0.0.dev5/omlish/diag}/__init__.py +0 -0
  139. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/diag/ps.py +0 -0
  140. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/diag/replserver/__init__.py +0 -0
  141. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/diag/replserver/__main__.py +0 -0
  142. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dispatch/__init__.py +0 -0
  143. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dispatch/dispatch.py +0 -0
  144. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dispatch/functions.py +0 -0
  145. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/dispatch/methods.py +0 -0
  146. {omlish-0.0.0.dev3/omlish/configs → omlish-0.0.0.dev5/omlish/graphs}/__init__.py +0 -0
  147. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/graphs/dot/__init__.py +0 -0
  148. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/graphs/dot/items.py +0 -0
  149. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/graphs/dot/rendering.py +0 -0
  150. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/graphs/dot/utils.py +0 -0
  151. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/http/wsgi.py +0 -0
  152. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/binder.py +0 -0
  153. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/eagers.py +0 -0
  154. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/elements.py +0 -0
  155. {omlish-0.0.0.dev3/omlish/diag → omlish-0.0.0.dev5/omlish/inject/impl}/__init__.py +0 -0
  156. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/impl/bindings.py +0 -0
  157. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/impl/inspect.py +0 -0
  158. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/impl/private.py +0 -0
  159. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/inspect.py +0 -0
  160. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/managed.py +0 -0
  161. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/overrides.py +0 -0
  162. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/inject/private.py +0 -0
  163. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/cached.py +0 -0
  164. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/classes/__init__.py +0 -0
  165. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/classes/abstract.py +0 -0
  166. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/classes/simple.py +0 -0
  167. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/clsdct.py +0 -0
  168. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/cmp.py +0 -0
  169. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/descriptors.py +0 -0
  170. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/exceptions.py +0 -0
  171. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/iterables.py +0 -0
  172. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/maybes.py +0 -0
  173. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/objects.py +0 -0
  174. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/resolving.py +0 -0
  175. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/strings.py +0 -0
  176. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/lang/timeouts.py +0 -0
  177. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/libc.py +0 -0
  178. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/logs/__init__.py +0 -0
  179. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/logs/_abc.py +0 -0
  180. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/logs/configs.py +0 -0
  181. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/logs/filters.py +0 -0
  182. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/logs/formatters.py +0 -0
  183. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/__init__.py +0 -0
  184. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/any.py +0 -0
  185. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/base.py +0 -0
  186. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/base64.py +0 -0
  187. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/dataclasses.py +0 -0
  188. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/enums.py +0 -0
  189. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/exceptions.py +0 -0
  190. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/factories.py +0 -0
  191. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/global_.py +0 -0
  192. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/iterables.py +0 -0
  193. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/mappings.py +0 -0
  194. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/naming.py +0 -0
  195. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/objects.py +0 -0
  196. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/optionals.py +0 -0
  197. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/polymorphism.py +0 -0
  198. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/primitives.py +0 -0
  199. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/registries.py +0 -0
  200. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/standard.py +0 -0
  201. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/utils.py +0 -0
  202. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/uuids.py +0 -0
  203. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/marshal/values.py +0 -0
  204. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/math.py +0 -0
  205. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/os.py +0 -0
  206. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/runmodule.py +0 -0
  207. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/sql/_abc.py +0 -0
  208. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/sql/dbs.py +0 -0
  209. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/stats.py +0 -0
  210. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/__init__.py +0 -0
  211. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/inject/__init__.py +0 -0
  212. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/inject/harness.py +1 -1
  213. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/_registry.py +0 -0
  214. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/logging.py +0 -0
  215. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/pydevd.py +0 -0
  216. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/repeat.py +0 -0
  217. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/skips.py +0 -0
  218. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/spacing.py +0 -0
  219. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/testing/pytest/plugins/switches.py +0 -0
  220. {omlish-0.0.0.dev3/omlish/graphs → omlish-0.0.0.dev5/omlish/text}/__init__.py +0 -0
  221. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/text/indent.py +0 -0
  222. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish/text/parts.py +0 -0
  223. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish.egg-info/dependency_links.txt +0 -0
  224. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/omlish.egg-info/top_level.txt +0 -0
  225. {omlish-0.0.0.dev3 → omlish-0.0.0.dev5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: omlish
3
- Version: 0.0.0.dev3
3
+ Version: 0.0.0.dev5
4
4
  Summary: omlish
5
5
  Author: wrmsr
6
6
  License: BSD-3-Clause
@@ -13,6 +13,9 @@ Requires-Python: >=3.12
13
13
  License-File: LICENSE
14
14
  Provides-Extra: async
15
15
  Requires-Dist: anyio; extra == "async"
16
+ Provides-Extra: trio
17
+ Requires-Dist: trio; extra == "trio"
18
+ Requires-Dist: trio-asyncio; extra == "trio"
16
19
  Provides-Extra: http
17
20
  Requires-Dist: httpx; extra == "http"
18
21
  Provides-Extra: sql
@@ -3,4 +3,4 @@ __url__ = 'https://github.com/wrmsr/omlish'
3
3
  __license__ = 'BSD-3-Clause'
4
4
  __requires_python__ = '>=3.12'
5
5
 
6
- __version__ = '0.0.0.dev3'
6
+ __version__ = '0.0.0.dev5'
@@ -0,0 +1,8 @@
1
+ import sys as _sys
2
+
3
+
4
+ REQUIRED_PYTHON_VERSION = (3, 12)
5
+
6
+
7
+ if _sys.version_info < REQUIRED_PYTHON_VERSION:
8
+ raise RuntimeError(f'Python version {_sys.version_info=} < {REQUIRED_PYTHON_VERSION}')
@@ -0,0 +1,35 @@
1
+ from .asyncs import ( # noqa
2
+ SyncableIterable,
3
+ async_list,
4
+ sync_await,
5
+ sync_list,
6
+ syncable_iterable,
7
+ )
8
+
9
+ from .flavors import ( # noqa
10
+ ContextManagerAdapter,
11
+ Flavor,
12
+ adapt,
13
+ adapt_context,
14
+ from_anyio,
15
+ from_anyio_context,
16
+ from_asyncio,
17
+ from_asyncio_context,
18
+ from_trio,
19
+ from_trio_context,
20
+ get_flavor,
21
+ mark_anyio,
22
+ mark_asyncio,
23
+ mark_flavor,
24
+ mark_trio,
25
+ with_adapter_loop,
26
+ )
27
+
28
+ from .futures import ( # noqa
29
+ FutureError,
30
+ FutureTimeoutError,
31
+ ImmediateExecutor,
32
+ new_thread_or_immediate_executor,
33
+ wait_dependent_futures,
34
+ wait_futures,
35
+ )
@@ -1,4 +1,9 @@
1
1
  """
2
+ TODO:
3
+ - bane
4
+ - owned lock
5
+ - async once
6
+
2
7
  lookit:
3
8
  - https://github.com/davidbrochart/sqlite-anyio/blob/a3ba4c6ef0535b14a5a60071fcd6ed565a514963/sqlite_anyio/sqlite.py
4
9
  - https://github.com/rafalkrupinski/ratelimit-anyio/blob/2910a8a3d6fa54ed17ee6ba457686c9f7a4c4beb/src/ratelimit_anyio/__init__.py
@@ -84,3 +89,64 @@ async def gather(*fns: ta.Callable[..., ta.Awaitable[T]], take_first: bool = Fal
84
89
 
85
90
  async def first(*fns: ta.Callable[..., ta.Awaitable[T]], **kwargs: ta.Any) -> list[lang.Maybe[T]]:
86
91
  return await gather(*fns, take_first=True, **kwargs)
92
+
93
+
94
+ ##
95
+
96
+
97
+ class Once:
98
+ def __init__(self) -> None:
99
+ super().__init__()
100
+ self._done = False
101
+ self._lock = anyio.Lock()
102
+
103
+ async def do(self, fn: ta.Callable[[], ta.Awaitable[None]]) -> bool:
104
+ if self._done:
105
+ return False
106
+ async with self._lock:
107
+ if self._done:
108
+ return False # type: ignore
109
+ try:
110
+ await fn()
111
+ finally:
112
+ self._done = True
113
+ return True
114
+
115
+
116
+ class Lazy(ta.Generic[T]):
117
+ def __init__(self) -> None:
118
+ super().__init__()
119
+ self._once = Once()
120
+ self._v: lang.Maybe[T] = lang.empty()
121
+
122
+ def peek(self) -> lang.Maybe[T]:
123
+ return self._v
124
+
125
+ def set(self, v: T) -> None:
126
+ self._v = lang.just(v)
127
+
128
+ async def get(self, fn: ta.Callable[[], ta.Awaitable[T]]) -> T:
129
+ async def do():
130
+ self._v = lang.just(await fn())
131
+ await self._once.do(do)
132
+ return self._v.must()
133
+
134
+
135
+ class LazyFn(ta.Generic[T]):
136
+ def __init__(self, fn: ta.Callable[[], ta.Awaitable[T]]) -> None:
137
+ super().__init__()
138
+ self._fn = fn
139
+ self._once = Once()
140
+ self._v: lang.Maybe[T] = lang.empty()
141
+
142
+ def peek(self) -> lang.Maybe[T]:
143
+ return self._v
144
+
145
+ def set(self, v: T) -> None:
146
+ self._v = lang.just(v)
147
+
148
+ async def get(self) -> T:
149
+ async def do():
150
+ self._v = lang.just(await self._fn())
151
+ await self._once.do(do)
152
+ return self._v.must()
@@ -0,0 +1,227 @@
1
+ """
2
+ TODO:
3
+ - 'get current'? -> sniffio..
4
+ - mark whole class / module?
5
+ - sync/greenlet bridge
6
+ """
7
+ import abc
8
+ import dataclasses as dc
9
+ import enum
10
+ import functools
11
+ import typing as ta
12
+
13
+ from .. import lang
14
+ from .trio_asyncio import check_trio_asyncio
15
+ from .trio_asyncio import with_trio_asyncio_loop
16
+
17
+
18
+ if ta.TYPE_CHECKING:
19
+ import sniffio
20
+ import trio_asyncio
21
+ else:
22
+ sniffio = lang.proxy_import('sniffio')
23
+ trio_asyncio = lang.proxy_import('trio_asyncio')
24
+
25
+
26
+ T = ta.TypeVar('T')
27
+
28
+
29
+ ##
30
+
31
+
32
+ _FLAVOR_ATTR = '__async_flavor__'
33
+
34
+
35
+ class _MISSING(lang.Marker):
36
+ pass
37
+
38
+
39
+ class Flavor(enum.Enum):
40
+ ASYNCIO = enum.auto()
41
+ TRIO = enum.auto()
42
+ ANYIO = enum.auto()
43
+
44
+
45
+ def mark_flavor(f: Flavor):
46
+ if not isinstance(f, Flavor):
47
+ raise TypeError(f)
48
+
49
+ def inner(fn):
50
+ setattr(fn, _FLAVOR_ATTR, f)
51
+ return fn
52
+
53
+ return inner
54
+
55
+
56
+ mark_asyncio = mark_flavor(Flavor.ASYNCIO)
57
+ mark_anyio = mark_flavor(Flavor.ANYIO)
58
+ mark_trio = mark_flavor(Flavor.TRIO)
59
+
60
+ PACKAGE_FLAVORS: ta.MutableMapping[str, Flavor] = {
61
+ 'anyio': Flavor.ANYIO,
62
+ 'asyncio': Flavor.ASYNCIO,
63
+ 'trio': Flavor.TRIO,
64
+
65
+ 'sqlalchemy.ext.asyncio': Flavor.ASYNCIO,
66
+ }
67
+
68
+ _MODULE_FLAVOR_CACHE: dict[str, Flavor | None] = {}
69
+
70
+
71
+ def _get_module_flavor(p: str) -> Flavor | None:
72
+ try:
73
+ return _MODULE_FLAVOR_CACHE[p]
74
+ except KeyError:
75
+ pass
76
+ pf: Flavor | None = None
77
+ for cp, cf in PACKAGE_FLAVORS.items():
78
+ if p.startswith(cp) and (len(cp) == len(p) or p[len(cp)] == '.'):
79
+ pf = cf
80
+ break
81
+ _MODULE_FLAVOR_CACHE[p] = pf
82
+ return pf
83
+
84
+
85
+ def get_flavor(obj: ta.Any, default: Flavor | type[_MISSING] | None = _MISSING) -> Flavor:
86
+ u = lang.unwrap_func(obj)
87
+
88
+ try:
89
+ return getattr(u, _FLAVOR_ATTR)
90
+ except AttributeError:
91
+ pass
92
+
93
+ if (mn := getattr(u, '__module__', None)) is not None:
94
+ if (pf := _get_module_flavor(mn)):
95
+ return pf
96
+
97
+ if default is not _MISSING:
98
+ return default # type: ignore
99
+
100
+ raise TypeError(f'not marked with flavor: {obj}')
101
+
102
+
103
+ ##
104
+
105
+
106
+ def with_adapter_loop(*, wait=False):
107
+ def outer(fn):
108
+ @functools.wraps(fn)
109
+ async def inner(*args, **kwargs):
110
+ cur_lib = sniffio.current_async_library()
111
+
112
+ if cur_lib == 'asyncio':
113
+ await fn(*args, **kwargs)
114
+
115
+ elif cur_lib == 'trio':
116
+ await with_trio_asyncio_loop(wait=wait)(fn)(*args, **kwargs)
117
+
118
+ else:
119
+ raise RuntimeError(f'Unknown async library: {cur_lib}')
120
+
121
+ return inner
122
+
123
+ return outer
124
+
125
+
126
+ ##
127
+
128
+
129
+ class Adapter(lang.Abstract):
130
+ _FROM_METHODS_BY_FLAVOR: ta.ClassVar[ta.Mapping[Flavor, str]] = {
131
+ Flavor.ANYIO: 'from_anyio',
132
+ Flavor.ASYNCIO: 'from_asyncio',
133
+ Flavor.TRIO: 'from_trio',
134
+ }
135
+
136
+ def adapt(self, fn, fl=None):
137
+ if fl is None:
138
+ fl = get_flavor(fn)
139
+ return getattr(self, self._FROM_METHODS_BY_FLAVOR[fl])(fn)
140
+
141
+ #
142
+
143
+ def from_anyio(self, fn):
144
+ return fn
145
+
146
+ @abc.abstractmethod
147
+ def from_asyncio(self, fn):
148
+ raise NotImplementedError
149
+
150
+ @abc.abstractmethod
151
+ def from_trio(self, fn):
152
+ raise NotImplementedError
153
+
154
+
155
+ class AsyncioAdapter(Adapter):
156
+ def from_asyncio(self, fn):
157
+ return fn
158
+
159
+ def from_trio(self, fn):
160
+ check_trio_asyncio()
161
+ return trio_asyncio.trio_as_aio(fn)
162
+
163
+
164
+ class TrioAdapter(Adapter):
165
+ def from_asyncio(self, fn):
166
+ check_trio_asyncio()
167
+ return trio_asyncio.aio_as_trio(fn)
168
+
169
+ def from_trio(self, fn):
170
+ return fn
171
+
172
+
173
+ _ADAPTERS_BY_BACKEND: ta.Mapping[str, Adapter] = {
174
+ 'asyncio': AsyncioAdapter(),
175
+ 'trio': TrioAdapter(),
176
+ }
177
+
178
+
179
+ def get_adapter() -> Adapter:
180
+ return _ADAPTERS_BY_BACKEND[sniffio.current_async_library()]
181
+
182
+
183
+ def adapt(fn, fl=None):
184
+ return get_adapter().adapt(fn, fl)
185
+
186
+
187
+ def from_anyio(fn):
188
+ return get_adapter().from_anyio(fn)
189
+
190
+
191
+ def from_asyncio(fn):
192
+ return get_adapter().from_asyncio(fn)
193
+
194
+
195
+ def from_trio(fn):
196
+ return get_adapter().from_trio(fn)
197
+
198
+
199
+ ##
200
+
201
+
202
+ @dc.dataclass(frozen=True)
203
+ class ContextManagerAdapter(ta.Generic[T]):
204
+ obj: ta.AsyncContextManager[T]
205
+ adapt: ta.Callable[[ta.Callable], ta.Callable]
206
+
207
+ async def __aenter__(self, *args: ta.Any, **kwargs: ta.Any) -> T:
208
+ return await self.adapt(self.obj.__aenter__)(*args, **kwargs)
209
+
210
+ async def __aexit__(self, exc_type, exc_val, exc_tb):
211
+ return await self.adapt(self.obj.__aexit__)(exc_type, exc_val, exc_tb)
212
+
213
+
214
+ def adapt_context(obj):
215
+ return ContextManagerAdapter(obj, get_adapter().adapt)
216
+
217
+
218
+ def from_anyio_context(obj):
219
+ return ContextManagerAdapter(obj, get_adapter().from_anyio)
220
+
221
+
222
+ def from_asyncio_context(obj):
223
+ return ContextManagerAdapter(obj, get_adapter().from_asyncio)
224
+
225
+
226
+ def from_trio_context(obj):
227
+ return ContextManagerAdapter(obj, get_adapter().from_trio)
@@ -0,0 +1,47 @@
1
+ import functools
2
+ import typing as ta
3
+
4
+ from .. import lang
5
+
6
+
7
+ if ta.TYPE_CHECKING:
8
+ import asyncio
9
+
10
+ import sniffio
11
+ import trio_asyncio
12
+ else:
13
+ asyncio = lang.proxy_import('asyncio')
14
+
15
+ sniffio = lang.proxy_import('sniffio')
16
+ trio_asyncio = lang.proxy_import('trio_asyncio')
17
+
18
+
19
+ def check_trio_asyncio() -> None:
20
+ if trio_asyncio.current_loop.get() is None:
21
+ raise RuntimeError('trio_asyncio loop not running')
22
+
23
+
24
+ def with_trio_asyncio_loop(*, wait=False):
25
+ def outer(fn):
26
+ @functools.wraps(fn)
27
+ async def inner(*args, **kwargs):
28
+ if trio_asyncio.current_loop.get() is not None:
29
+ await fn(*args, **kwargs)
30
+ return
31
+
32
+ if sniffio.current_async_library() != 'trio':
33
+ raise RuntimeError('trio loop not running')
34
+
35
+ loop: asyncio.BaseEventLoop
36
+ async with trio_asyncio.open_loop() as loop:
37
+ try:
38
+ await fn(*args, **kwargs)
39
+ finally:
40
+ if wait:
41
+ # FIXME: lol
42
+ while asyncio.all_tasks(loop):
43
+ await asyncio.sleep(.2)
44
+
45
+ return inner
46
+
47
+ return outer
@@ -144,7 +144,7 @@ def compose_mro(
144
144
 
145
145
  # Remove entries which are strict bases of other entries (they will end up in the MRO anyway.
146
146
  def is_strict_base(typ):
147
- for other in types:
147
+ for other in types: # noqa
148
148
  if typ != other and typ in (get_mro(other) or []):
149
149
  return True
150
150
  return False
@@ -1,6 +1,5 @@
1
- from .lang.cached import cached_function
2
1
  from .lang.cached import _CachedProperty # noqa
3
-
2
+ from .lang.cached import cached_function
4
3
 
5
4
  function = cached_function
6
5
 
@@ -90,9 +90,12 @@ from .utils import ( # noqa
90
90
  all_not_equal,
91
91
  indexes,
92
92
  key_cmp,
93
+ multi_map,
94
+ multi_map_by,
93
95
  mut_toposort,
94
96
  partition,
95
97
  toposort,
96
98
  unique,
97
- unique_dict,
99
+ unique_map,
100
+ unique_map_by,
98
101
  )
@@ -55,7 +55,7 @@ class CacheImpl(Cache[K, V]):
55
55
  if not ta.TYPE_CHECKING:
56
56
  from ..._ext.cy.collections.cache import CacheLink as Link
57
57
  else:
58
- raise ImportError
58
+ raise ImportError # noqa
59
59
 
60
60
  except ImportError:
61
61
  class Link:
@@ -12,6 +12,9 @@ K = ta.TypeVar('K')
12
12
  V = ta.TypeVar('V')
13
13
 
14
14
 
15
+ ##
16
+
17
+
15
18
  def mut_toposort(data: dict[T, set[T]]) -> ta.Iterator[set[T]]:
16
19
  for k, v in data.items():
17
20
  v.discard(k)
@@ -31,6 +34,9 @@ def toposort(data: ta.Mapping[T, ta.AbstractSet[T]]) -> ta.Iterator[set[T]]:
31
34
  return mut_toposort({k: set(v) for k, v in data.items()})
32
35
 
33
36
 
37
+ ##
38
+
39
+
34
40
  def partition(items: ta.Iterable[T], pred: ta.Callable[[T], bool]) -> tuple[list[T], list[T]]:
35
41
  t: list[T] = []
36
42
  f: list[T] = []
@@ -54,13 +60,36 @@ def unique(it: ta.Iterable[T], *, identity: bool = False) -> list[T]:
54
60
  return ret
55
61
 
56
62
 
57
- def unique_dict(items: ta.Iterable[tuple[K, V]], *, identity: bool = False) -> ta.MutableMapping[K, V]:
58
- dct: ta.MutableMapping[K, V] = IdentityKeyDict() if identity else {}
59
- for k, v in items:
60
- if k in dct:
63
+ def unique_map(kvs: ta.Iterable[tuple[K, V]], *, identity: bool = False) -> ta.MutableMapping[K, V]:
64
+ d: ta.MutableMapping[K, V] = IdentityKeyDict() if identity else {}
65
+ for k, v in kvs:
66
+ if k in d:
61
67
  raise KeyError(k)
62
- dct[k] = v
63
- return dct
68
+ d[k] = v
69
+ return d
70
+
71
+
72
+ def unique_map_by(fn: ta.Callable[[V], K], vs: ta.Iterable[V], *, identity: bool = False) -> ta.MutableMapping[K, V]:
73
+ return unique_map(((fn(v), v) for v in vs), identity=identity)
74
+
75
+
76
+ def multi_map(kvs: ta.Iterable[tuple[K, V]], *, identity: bool = False) -> ta.MutableMapping[K, list[V]]:
77
+ d: ta.MutableMapping[K, list[V]] = IdentityKeyDict() if identity else {}
78
+ l: list[V]
79
+ for k, v in kvs:
80
+ try:
81
+ l = d[k]
82
+ except KeyError:
83
+ l = d[k] = []
84
+ l.append(v)
85
+ return d
86
+
87
+
88
+ def multi_map_by(fn: ta.Callable[[V], K], vs: ta.Iterable[V], *, identity: bool = False) -> ta.MutableMapping[K, list[V]]: # noqa
89
+ return multi_map(((fn(v), v) for v in vs), identity=identity)
90
+
91
+
92
+ ##
64
93
 
65
94
 
66
95
  def all_equal(it: ta.Iterable[T]) -> bool:
@@ -81,6 +110,9 @@ def all_not_equal(it: ta.Iterable[T]) -> bool:
81
110
  return True
82
111
 
83
112
 
113
+ ##
114
+
115
+
84
116
  def key_cmp(fn: ta.Callable[[K, K], int]) -> ta.Callable[[tuple[K, V], tuple[K, V]], int]:
85
117
  return lambda t0, t1: fn(t0[0], t1[0])
86
118
 
@@ -0,0 +1,5 @@
1
+ from .classes import ( # noqa
2
+ Config,
3
+ Configurable,
4
+ get_impl,
5
+ )
@@ -0,0 +1,53 @@
1
+ import typing as ta
2
+ import weakref
3
+
4
+ from .. import check
5
+ from .. import dataclasses as dc
6
+ from .. import lang
7
+
8
+
9
+ class Config(
10
+ dc.Data,
11
+ lang.Abstract,
12
+ frozen=True,
13
+ reorder=True,
14
+ confer=frozenset([
15
+ 'frozen',
16
+ 'reorder',
17
+ 'confer',
18
+ ]),
19
+ ):
20
+ pass
21
+
22
+
23
+ ConfigT = ta.TypeVar('ConfigT', bound='Config')
24
+
25
+ _CONFIG_CLS_MAP: ta.MutableMapping[type[Config], type['Configurable']] = weakref.WeakValueDictionary()
26
+
27
+
28
+ class Configurable(ta.Generic[ConfigT], lang.Abstract):
29
+
30
+ # FIXME: https://github.com/python/mypy/issues/5144
31
+ Config: ta.ClassVar[type[ConfigT]] # type: ignore # noqa
32
+
33
+ def __init_subclass__(cls, **kwargs: ta.Any) -> None:
34
+ super().__init_subclass__(**kwargs)
35
+
36
+ cfg_cls = check.issubclass(cls.__dict__['Config'], Config)
37
+ check.not_in(cfg_cls, _CONFIG_CLS_MAP)
38
+ _CONFIG_CLS_MAP[cfg_cls] = cls
39
+
40
+ def __init__(self, config: ConfigT) -> None:
41
+ super().__init__()
42
+
43
+ self._config: ConfigT = check.isinstance(config, self.Config)
44
+
45
+
46
+ def get_impl(cfg: type[Config] | Config) -> type[Configurable]:
47
+ if isinstance(cfg, type):
48
+ cfg_cls = check.issubclass(cfg, Config) # noqa
49
+ elif isinstance(cfg, Config):
50
+ cfg_cls = type(cfg)
51
+ else:
52
+ raise TypeError(cfg)
53
+ return _CONFIG_CLS_MAP[cfg_cls]