omlish 0.0.0.dev447__py3-none-any.whl → 0.0.0.dev493__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (265) hide show
  1. omlish/.omlish-manifests.json +12 -0
  2. omlish/README.md +199 -0
  3. omlish/__about__.py +21 -16
  4. omlish/argparse/all.py +17 -9
  5. omlish/argparse/cli.py +16 -3
  6. omlish/argparse/utils.py +21 -0
  7. omlish/asyncs/asyncio/rlock.py +110 -0
  8. omlish/asyncs/asyncio/sync.py +43 -0
  9. omlish/asyncs/asyncio/utils.py +2 -0
  10. omlish/asyncs/sync.py +25 -0
  11. omlish/bootstrap/_marshal.py +1 -1
  12. omlish/bootstrap/diag.py +12 -21
  13. omlish/bootstrap/main.py +2 -5
  14. omlish/bootstrap/sys.py +27 -28
  15. omlish/cexts/__init__.py +0 -0
  16. omlish/cexts/include/omlish/omlish.hh +1 -0
  17. omlish/collections/__init__.py +13 -1
  18. omlish/collections/attrregistry.py +210 -0
  19. omlish/collections/cache/impl.py +1 -0
  20. omlish/collections/identity.py +1 -0
  21. omlish/collections/mappings.py +28 -0
  22. omlish/collections/trie.py +5 -1
  23. omlish/collections/utils.py +77 -0
  24. omlish/concurrent/all.py +2 -1
  25. omlish/concurrent/futures.py +25 -0
  26. omlish/concurrent/threadlets.py +1 -1
  27. omlish/daemons/reparent.py +2 -3
  28. omlish/daemons/spawning.py +2 -3
  29. omlish/dataclasses/__init__.py +2 -0
  30. omlish/dataclasses/impl/api/classes/decorator.py +3 -0
  31. omlish/dataclasses/impl/api/classes/make.py +3 -0
  32. omlish/dataclasses/impl/concerns/repr.py +15 -2
  33. omlish/dataclasses/impl/configs.py +97 -37
  34. omlish/dataclasses/impl/generation/compilation.py +21 -19
  35. omlish/dataclasses/impl/generation/globals.py +1 -0
  36. omlish/dataclasses/impl/generation/ops.py +1 -0
  37. omlish/dataclasses/impl/generation/plans.py +2 -17
  38. omlish/dataclasses/impl/generation/processor.py +106 -25
  39. omlish/dataclasses/impl/processing/base.py +8 -0
  40. omlish/dataclasses/impl/processing/driving.py +19 -7
  41. omlish/dataclasses/specs.py +1 -0
  42. omlish/dataclasses/tools/modifiers.py +5 -0
  43. omlish/diag/_pycharm/runhack.py +1 -1
  44. omlish/diag/cmds/__init__.py +0 -0
  45. omlish/diag/{lslocks.py → cmds/lslocks.py} +6 -6
  46. omlish/diag/{lsof.py → cmds/lsof.py} +6 -6
  47. omlish/diag/{ps.py → cmds/ps.py} +6 -6
  48. omlish/diag/pycharm.py +16 -2
  49. omlish/diag/pydevd.py +58 -40
  50. omlish/diag/replserver/console.py +1 -1
  51. omlish/dispatch/__init__.py +18 -12
  52. omlish/dispatch/methods.py +50 -140
  53. omlish/dom/rendering.py +1 -1
  54. omlish/formats/dotenv.py +1 -1
  55. omlish/formats/json/stream/__init__.py +13 -0
  56. omlish/funcs/guard.py +225 -0
  57. omlish/graphs/dot/rendering.py +1 -1
  58. omlish/http/all.py +44 -4
  59. omlish/http/clients/asyncs.py +33 -27
  60. omlish/http/clients/base.py +17 -1
  61. omlish/http/clients/coro/__init__.py +0 -0
  62. omlish/http/clients/coro/sync.py +171 -0
  63. omlish/http/clients/default.py +208 -29
  64. omlish/http/clients/executor.py +56 -0
  65. omlish/http/clients/httpx.py +72 -11
  66. omlish/http/clients/middleware.py +181 -0
  67. omlish/http/clients/sync.py +33 -27
  68. omlish/http/clients/syncasync.py +49 -0
  69. omlish/http/clients/urllib.py +6 -3
  70. omlish/http/coro/client/connection.py +15 -6
  71. omlish/http/coro/io.py +2 -0
  72. omlish/http/flasky/__init__.py +40 -0
  73. omlish/http/flasky/_compat.py +2 -0
  74. omlish/http/flasky/api.py +82 -0
  75. omlish/http/flasky/app.py +203 -0
  76. omlish/http/flasky/cvs.py +59 -0
  77. omlish/http/flasky/requests.py +20 -0
  78. omlish/http/flasky/responses.py +23 -0
  79. omlish/http/flasky/routes.py +23 -0
  80. omlish/http/flasky/types.py +15 -0
  81. omlish/http/urls.py +67 -0
  82. omlish/inject/__init__.py +57 -29
  83. omlish/inject/_dataclasses.py +5148 -0
  84. omlish/inject/binder.py +11 -52
  85. omlish/inject/eagers.py +2 -0
  86. omlish/inject/elements.py +27 -0
  87. omlish/inject/helpers/__init__.py +0 -0
  88. omlish/inject/{utils.py → helpers/constfn.py} +3 -3
  89. omlish/inject/{tags.py → helpers/id.py} +2 -2
  90. omlish/inject/helpers/late.py +76 -0
  91. omlish/inject/{managed.py → helpers/managed.py} +10 -10
  92. omlish/inject/helpers/multis.py +143 -0
  93. omlish/inject/helpers/wrappers.py +54 -0
  94. omlish/inject/impl/elements.py +54 -21
  95. omlish/inject/impl/injector.py +29 -25
  96. omlish/inject/impl/inspect.py +10 -1
  97. omlish/inject/impl/maysync.py +3 -4
  98. omlish/inject/impl/multis.py +3 -0
  99. omlish/inject/impl/sync.py +3 -4
  100. omlish/inject/injector.py +31 -2
  101. omlish/inject/inspect.py +35 -0
  102. omlish/inject/maysync.py +2 -4
  103. omlish/inject/multis.py +8 -0
  104. omlish/inject/overrides.py +3 -3
  105. omlish/inject/privates.py +6 -0
  106. omlish/inject/providers.py +3 -2
  107. omlish/inject/sync.py +5 -4
  108. omlish/io/buffers.py +118 -0
  109. omlish/io/readers.py +29 -0
  110. omlish/iterators/transforms.py +2 -2
  111. omlish/lang/__init__.py +180 -97
  112. omlish/lang/_asyncs.cc +186 -0
  113. omlish/lang/asyncs.py +17 -0
  114. omlish/lang/casing.py +11 -0
  115. omlish/lang/contextmanagers.py +28 -4
  116. omlish/lang/functions.py +31 -22
  117. omlish/lang/imports/_capture.cc +11 -9
  118. omlish/lang/imports/capture.py +363 -170
  119. omlish/lang/imports/proxy.py +455 -152
  120. omlish/lang/lazyglobals.py +22 -9
  121. omlish/lang/params.py +17 -0
  122. omlish/lang/recursion.py +0 -1
  123. omlish/lang/sequences.py +124 -0
  124. omlish/lifecycles/README.md +30 -0
  125. omlish/lifecycles/__init__.py +87 -13
  126. omlish/lifecycles/_dataclasses.py +1388 -0
  127. omlish/lifecycles/base.py +178 -64
  128. omlish/lifecycles/contextmanagers.py +113 -4
  129. omlish/lifecycles/controller.py +150 -87
  130. omlish/lifecycles/injection.py +143 -0
  131. omlish/lifecycles/listeners.py +56 -0
  132. omlish/lifecycles/managed.py +142 -0
  133. omlish/lifecycles/manager.py +218 -93
  134. omlish/lifecycles/states.py +2 -0
  135. omlish/lifecycles/transitions.py +3 -0
  136. omlish/lifecycles/unwrap.py +57 -0
  137. omlish/lite/abstract.py +54 -24
  138. omlish/lite/asyncs.py +2 -2
  139. omlish/lite/attrops.py +2 -0
  140. omlish/lite/contextmanagers.py +4 -4
  141. omlish/lite/dataclasses.py +44 -0
  142. omlish/lite/maybes.py +8 -0
  143. omlish/lite/maysync.py +1 -5
  144. omlish/lite/pycharm.py +1 -1
  145. omlish/lite/typing.py +24 -0
  146. omlish/logs/_amalg.py +1 -1
  147. omlish/logs/all.py +25 -11
  148. omlish/logs/asyncs.py +73 -0
  149. omlish/logs/base.py +101 -12
  150. omlish/logs/contexts.py +4 -1
  151. omlish/logs/lists.py +125 -0
  152. omlish/logs/modules.py +19 -1
  153. omlish/logs/std/loggers.py +6 -1
  154. omlish/logs/std/noisy.py +11 -9
  155. omlish/logs/{standard.py → std/standard.py} +3 -4
  156. omlish/logs/utils.py +17 -2
  157. omlish/manifests/loading.py +2 -1
  158. omlish/marshal/__init__.py +33 -13
  159. omlish/marshal/_dataclasses.py +2774 -0
  160. omlish/marshal/base/configs.py +12 -0
  161. omlish/marshal/base/contexts.py +36 -21
  162. omlish/marshal/base/funcs.py +8 -11
  163. omlish/marshal/base/options.py +8 -0
  164. omlish/marshal/base/registries.py +146 -44
  165. omlish/marshal/base/types.py +40 -16
  166. omlish/marshal/composite/iterables.py +33 -20
  167. omlish/marshal/composite/literals.py +20 -18
  168. omlish/marshal/composite/mappings.py +36 -23
  169. omlish/marshal/composite/maybes.py +29 -19
  170. omlish/marshal/composite/newtypes.py +16 -16
  171. omlish/marshal/composite/optionals.py +14 -14
  172. omlish/marshal/composite/special.py +15 -15
  173. omlish/marshal/composite/unions/__init__.py +0 -0
  174. omlish/marshal/composite/unions/literals.py +93 -0
  175. omlish/marshal/composite/unions/primitives.py +103 -0
  176. omlish/marshal/factories/invalidate.py +18 -68
  177. omlish/marshal/factories/method.py +26 -0
  178. omlish/marshal/factories/moduleimport/factories.py +22 -65
  179. omlish/marshal/factories/multi.py +13 -25
  180. omlish/marshal/factories/recursive.py +42 -56
  181. omlish/marshal/factories/typecache.py +29 -74
  182. omlish/marshal/factories/typemap.py +42 -43
  183. omlish/marshal/objects/dataclasses.py +129 -106
  184. omlish/marshal/objects/marshal.py +18 -14
  185. omlish/marshal/objects/namedtuples.py +48 -42
  186. omlish/marshal/objects/unmarshal.py +19 -15
  187. omlish/marshal/polymorphism/marshal.py +9 -11
  188. omlish/marshal/polymorphism/metadata.py +16 -5
  189. omlish/marshal/polymorphism/standard.py +13 -1
  190. omlish/marshal/polymorphism/unions.py +15 -105
  191. omlish/marshal/polymorphism/unmarshal.py +9 -10
  192. omlish/marshal/singular/enums.py +14 -18
  193. omlish/marshal/standard.py +10 -6
  194. omlish/marshal/trivial/any.py +1 -1
  195. omlish/marshal/trivial/forbidden.py +21 -26
  196. omlish/metadata.py +23 -1
  197. omlish/os/forkhooks.py +4 -0
  198. omlish/os/pidfiles/pinning.py +2 -2
  199. omlish/reflect/__init__.py +43 -26
  200. omlish/reflect/ops.py +10 -1
  201. omlish/reflect/types.py +1 -0
  202. omlish/secrets/marshal.py +1 -1
  203. omlish/specs/jmespath/__init__.py +12 -3
  204. omlish/specs/jmespath/_dataclasses.py +2893 -0
  205. omlish/specs/jmespath/ast.py +1 -1
  206. omlish/specs/jsonrpc/__init__.py +13 -0
  207. omlish/specs/jsonrpc/_marshal.py +32 -23
  208. omlish/specs/jsonrpc/conns.py +10 -7
  209. omlish/specs/jsonschema/_marshal.py +1 -1
  210. omlish/specs/jsonschema/keywords/__init__.py +7 -0
  211. omlish/specs/jsonschema/keywords/_dataclasses.py +1644 -0
  212. omlish/specs/openapi/_marshal.py +31 -22
  213. omlish/sql/__init__.py +24 -5
  214. omlish/sql/{tabledefs/alchemy.py → alchemy/tabledefs.py} +2 -2
  215. omlish/sql/api/dbapi.py +1 -1
  216. omlish/sql/dbapi/__init__.py +15 -0
  217. omlish/sql/{dbapi.py → dbapi/drivers.py} +2 -2
  218. omlish/sql/queries/__init__.py +3 -0
  219. omlish/sql/queries/_marshal.py +2 -2
  220. omlish/sql/queries/rendering.py +1 -1
  221. omlish/sql/tabledefs/_marshal.py +1 -1
  222. omlish/subprocesses/base.py +4 -0
  223. omlish/subprocesses/editor.py +1 -1
  224. omlish/sync.py +155 -21
  225. omlish/term/alt.py +60 -0
  226. omlish/term/confirm.py +8 -8
  227. omlish/term/pager.py +235 -0
  228. omlish/term/terminfo.py +935 -0
  229. omlish/term/termstate.py +67 -0
  230. omlish/term/vt100/terminal.py +0 -3
  231. omlish/testing/pytest/plugins/asyncs/fixtures.py +4 -1
  232. omlish/testing/pytest/plugins/asyncs/plugin.py +2 -0
  233. omlish/testing/pytest/plugins/skips.py +2 -1
  234. omlish/testing/unittest/main.py +3 -3
  235. omlish/text/docwrap/__init__.py +3 -0
  236. omlish/text/docwrap/__main__.py +11 -0
  237. omlish/text/docwrap/api.py +83 -0
  238. omlish/text/docwrap/cli.py +91 -0
  239. omlish/text/docwrap/groups.py +84 -0
  240. omlish/text/docwrap/lists.py +167 -0
  241. omlish/text/docwrap/parts.py +146 -0
  242. omlish/text/docwrap/reflowing.py +106 -0
  243. omlish/text/docwrap/rendering.py +151 -0
  244. omlish/text/docwrap/utils.py +11 -0
  245. omlish/text/docwrap/wrapping.py +59 -0
  246. omlish/text/filecache.py +2 -2
  247. omlish/text/lorem.py +6 -0
  248. omlish/text/parts.py +2 -2
  249. omlish/text/textwrap.py +51 -0
  250. omlish/typedvalues/marshal.py +85 -59
  251. omlish/typedvalues/values.py +2 -1
  252. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/METADATA +36 -32
  253. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/RECORD +260 -199
  254. omlish/dataclasses/impl/generation/mangling.py +0 -18
  255. omlish/funcs/match.py +0 -227
  256. omlish/lifecycles/abstract.py +0 -86
  257. omlish/marshal/factories/match.py +0 -34
  258. omlish/marshal/factories/simple.py +0 -28
  259. /omlish/inject/{impl → helpers}/proxy.py +0 -0
  260. /omlish/inject/impl/{providers2.py → providersmap.py} +0 -0
  261. /omlish/sql/{abc.py → dbapi/abc.py} +0 -0
  262. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/WHEEL +0 -0
  263. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/entry_points.txt +0 -0
  264. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/licenses/LICENSE +0 -0
  265. {omlish-0.0.0.dev447.dist-info → omlish-0.0.0.dev493.dist-info}/top_level.txt +0 -0
@@ -1,3 +1,4 @@
1
+ import threading
1
2
  import typing as ta
2
3
 
3
4
 
@@ -15,6 +16,10 @@ class AmbiguousLazyGlobalsFallbackError(Exception):
15
16
  return f'{self.__class__.__name__}({self.attr!r}, {self.fallbacks!r})'
16
17
 
17
18
 
19
+ _LAZY_GLOBALS_LOCK = threading.RLock()
20
+
21
+
22
+ @ta.final
18
23
  class LazyGlobals:
19
24
  def __init__(
20
25
  self,
@@ -22,8 +27,6 @@ class LazyGlobals:
22
27
  globals: ta.MutableMapping[str, ta.Any] | None = None, # noqa
23
28
  update_globals: bool = False,
24
29
  ) -> None:
25
- super().__init__()
26
-
27
30
  self._globals = globals
28
31
  self._update_globals = update_globals
29
32
 
@@ -37,18 +40,28 @@ class LazyGlobals:
37
40
  except KeyError:
38
41
  pass
39
42
  else:
40
- if not isinstance(xga, cls):
43
+ if xga.__class__ is not cls:
41
44
  raise RuntimeError(f'Module already has __getattr__ hook: {xga}') # noqa
42
45
  return xga
43
46
 
44
- lm = cls(
45
- globals=globals,
46
- update_globals=True,
47
- )
47
+ with _LAZY_GLOBALS_LOCK:
48
+ try:
49
+ xga = globals['__getattr__']
50
+ except KeyError:
51
+ pass
52
+ else:
53
+ if xga.__class__ is not cls:
54
+ raise RuntimeError(f'Module already has __getattr__ hook: {xga}') # noqa
55
+ return xga
56
+
57
+ lm = cls(
58
+ globals=globals,
59
+ update_globals=True,
60
+ )
48
61
 
49
- globals['__getattr__'] = lm
62
+ globals['__getattr__'] = lm
50
63
 
51
- return lm
64
+ return lm
52
65
 
53
66
  def set_fn(self, attr: str, fn: ta.Callable[[], ta.Any]) -> 'LazyGlobals':
54
67
  self._attr_fns[attr] = fn
omlish/lang/params.py CHANGED
@@ -1,6 +1,7 @@
1
1
  """
2
2
  TODO:
3
3
  - check validity
4
+ - signature vs getfullargspec - diff unwrapping + 'self' handling
4
5
  """
5
6
  import dataclasses as dc
6
7
  import enum
@@ -16,6 +17,13 @@ from .classes.restrict import Sealed
16
17
  T = ta.TypeVar('T')
17
18
 
18
19
 
20
+ CanParamSpec: ta.TypeAlias = ta.Union[
21
+ 'ParamSpec',
22
+ inspect.Signature,
23
+ ta.Callable,
24
+ ]
25
+
26
+
19
27
  ##
20
28
 
21
29
 
@@ -101,6 +109,15 @@ class ParamSpec(ta.Sequence[Param], Final):
101
109
 
102
110
  #
103
111
 
112
+ @classmethod
113
+ def of(cls, obj: CanParamSpec) -> 'ParamSpec':
114
+ if isinstance(obj, ParamSpec):
115
+ return obj
116
+ elif isinstance(obj, inspect.Signature):
117
+ return cls.of_signature(obj)
118
+ else:
119
+ return cls.inspect(obj)
120
+
104
121
  @classmethod
105
122
  def of_signature(
106
123
  cls,
omlish/lang/recursion.py CHANGED
@@ -13,7 +13,6 @@ P = ta.ParamSpec('P')
13
13
 
14
14
 
15
15
  _LOCK = threading.RLock()
16
-
17
16
  _LOCAL: threading.local
18
17
 
19
18
 
@@ -0,0 +1,124 @@
1
+ """
2
+ TODO:
3
+ - StrView, BytesView - in lieu of hkt lol
4
+ - cext? even necessary?
5
+ - __eq__, cmp, __hash__
6
+ - __buffer__
7
+ - optimize `slice(None)`, keep as SeqView but fast path ops
8
+ - shorter repr if __len__ > some threshold
9
+ - use materialize()?
10
+ """
11
+ import typing as ta
12
+
13
+
14
+ T = ta.TypeVar('T')
15
+
16
+
17
+ ##
18
+
19
+
20
+ def iterslice(
21
+ seq: ta.Sequence[T],
22
+ slc: slice,
23
+ ) -> ta.Iterator[T]:
24
+ return map(seq.__getitem__, range(*slc.indices(len(seq))))
25
+
26
+
27
+ def iterrange(
28
+ seq: ta.Sequence[T],
29
+ start: int | None = None,
30
+ stop: int | None = None,
31
+ step: int | None = None,
32
+ ) -> ta.Iterator[T]:
33
+ return iterslice(seq, slice(start, stop, step))
34
+
35
+
36
+ ##
37
+
38
+
39
+ @ta.final
40
+ class SeqView(ta.Sequence[T]):
41
+ def __init__(self, data: ta.Sequence[T], slice_: slice = slice(None)) -> None:
42
+ if data.__class__ is SeqView:
43
+ self._data = data._data # type: ignore[attr-defined] # noqa
44
+ self._range = data._range[slice_] # type: ignore[attr-defined] # noqa
45
+ else:
46
+ self._data = data
47
+ self._range = range(*slice_.indices(len(data)))
48
+
49
+ def __init_subclass__(cls, **kwargs):
50
+ raise TypeError
51
+
52
+ _data: ta.Sequence[T]
53
+ _range: range
54
+
55
+ @classmethod
56
+ def _from_range(cls, base: ta.Sequence[T], rng: range) -> 'SeqView[T]':
57
+ self = object.__new__(cls)
58
+ self._data = base
59
+ self._range = rng
60
+ return self
61
+
62
+ def __repr__(self) -> str:
63
+ return f'{self.__class__.__name__}({self._data!r}, {self.slice!r})'
64
+
65
+ #
66
+
67
+ def __len__(self) -> int:
68
+ return len(self._range)
69
+
70
+ def __getitem__(self, key: int | slice) -> ta.Union[T, 'SeqView[T]']: # type: ignore[override]
71
+ if isinstance(key, slice):
72
+ nr = self._range[key]
73
+ return SeqView._from_range(self._data, nr)
74
+ return self._data[self._range[key]]
75
+
76
+ def __iter__(self) -> ta.Iterator[T]:
77
+ return map(self._data.__getitem__, self._range)
78
+
79
+ def __reversed__(self) -> ta.Iterator[T]:
80
+ return map(self._data.__getitem__, reversed(self._range))
81
+
82
+ def count(self, value: ta.Any) -> int:
83
+ c = 0
84
+ for i in self._range:
85
+ if self._data[i] == value:
86
+ c += 1
87
+ return c
88
+
89
+ def index(self, value: ta.Any, start: int = 0, stop: int | None = None) -> int:
90
+ sub = self._range[slice(start, stop, 1)]
91
+ for off, i in enumerate(sub):
92
+ if self._data[i] == value:
93
+ return off
94
+ raise ValueError(f'{value!r} is not in view')
95
+
96
+ #
97
+
98
+ @property
99
+ def data(self) -> ta.Sequence[T]:
100
+ return self._data
101
+
102
+ _slice: slice
103
+
104
+ @property
105
+ def slice(self) -> slice:
106
+ try:
107
+ return self._slice
108
+ except AttributeError:
109
+ pass
110
+
111
+ step = self._range.step
112
+ start = self._range.start
113
+ if len(self._range) == 0:
114
+ stop = start
115
+ else:
116
+ last = start + (len(self._range) - 1) * step
117
+ stop = last + (1 if step > 0 else -1)
118
+ slc = slice(start, stop, step)
119
+
120
+ self._slice = slc
121
+ return slc
122
+
123
+ def materialize(self) -> ta.Sequence[T]:
124
+ return self._data[self.slice]
@@ -0,0 +1,30 @@
1
+ Lifecycle management, inspired by [governator](https://github.com/Netflix/governator/tree/master/governator-core/).
2
+
3
+ A central idea is to 'hide the guts' of a given class's lifecycle management from code interacting with it.
4
+
5
+ The main classes are as follows:
6
+
7
+ - Lifecycle / AsyncLifecycle - the code 'managed by' the rest of the lifecycle machinery. In general, user code will
8
+ hide its implementations of these from the code that otherwise interacts with it. Being the lowest level / unit of
9
+ management callbacks, it intentionally provides no additional machinery, existing solely as a skeleton of methods
10
+ which will be called by lifecycle internals - this is to reduce friction with more functional / less OO code. However,
11
+ it still chooses to be a class with multiple nullary methods, rather than a more functional-style single unary free
12
+ function: the operations present in each method are generally intended to have no overlap in practice, and their
13
+ explicit division is a conscious choice.
14
+
15
+ - LifecycleManaged / AsyncLifecycleManaged - a mixin which can be used to add lifecycle management behavior to a class.
16
+ This removes the need for manual subclassing of Lifecycle / AsyncLifecycle, providing private '\_lifecycle_<state>'
17
+ callback methods (with default no-op implementations) which subclasses may override.
18
+
19
+ - LifecycleListener / AsyncLifecycleListener - callback interfaces whose methods will be called when a lifecycle object
20
+ goes through a lifecycle state transition.
21
+
22
+ - LifecycleController / AsyncLifecycleController - these classes run the state machine for any single Lifecycle /
23
+ AsyncLifecycle instance. They are also responsible for maintaining a registry of lifecycle listeners and calling their
24
+ methods as necessary. Unlike user code, these classes are openly subclasses of Lifecycle / AsyncLifecycle, allowing
25
+ them to be called as application state dictates - they will internally ensure correct state transitions.
26
+
27
+ - LifecycleManager / AsyncLifecycleManager - these classes are responsible for construction and operation of (acyclic)
28
+ graphs of lifecycle objects. They will ensure that, as necessary according to registered dependencies, lifecycle
29
+ objects are started in the correct order, and that they are stopped in the correct order. This class is itself a
30
+ LifecycleManaged / AsyncLifecycleManaged. Notably, AsyncLifecycleManager can also manage sync Lifecycles.
@@ -1,43 +1,71 @@
1
- from .abstract import ( # noqa
2
- AbstractLifecycle,
1
+ from .. import dataclasses as _dc
3
2
 
4
- AbstractAsyncLifecycle,
3
+
4
+ _dc.init_package(
5
+ globals(),
6
+ codegen=True,
5
7
  )
6
8
 
9
+
10
+ ##
11
+
12
+
7
13
  from .base import ( # noqa
8
- AnyLifecycleCallback,
14
+ Lifecycle,
15
+ AsyncLifecycle,
9
16
  AnyLifecycle,
10
- AnyCallbackLifecycle,
17
+ ANY_LIFECYCLE_TYPES,
11
18
 
12
- LifecycleCallback,
13
- CallbackLifecycle,
14
- Lifecycle,
19
+ sync_to_async_lifecycle,
20
+ as_async_lifecycle,
21
+ async_to_sync_lifecycle,
22
+ as_sync_lifecycle,
15
23
 
16
- AsyncLifecycleCallback,
24
+ CallbackLifecycle,
17
25
  CallbackAsyncLifecycle,
18
- AsyncLifecycle,
19
26
  )
20
27
 
21
28
  from .contextmanagers import ( # noqa
22
29
  ContextManagerLifecycle,
30
+ AsyncContextManagerLifecycle,
31
+
23
32
  LifecycleContextManager,
33
+ AsyncLifecycleContextManager,
34
+
35
+ lifecycle_context_manage,
36
+ async_lifecycle_context_manage,
24
37
  )
25
38
 
26
39
  from .controller import ( # noqa
27
- AnyLifecycleListener,
40
+ LifecycleController,
41
+ AsyncLifecycleController,
28
42
  AnyLifecycleController,
43
+ ANY_LIFECYCLE_CONTROLLER_TYPES,
44
+ )
29
45
 
30
- LifecycleController,
46
+ from .listeners import ( # noqa
31
47
  LifecycleListener,
48
+ AsyncLifecycleListener,
49
+ AnyLifecycleListener,
50
+ ANY_LIFECYCLE_LISTENER_TYPES,
51
+ )
52
+
53
+ from .managed import ( # noqa
54
+ LifecycleManaged,
55
+ AsyncLifecycleManaged,
56
+ AnyLifecycleManaged,
57
+ ANY_LIFECYCLE_MANAGED_TYPES,
32
58
  )
33
59
 
34
60
  from .manager import ( # noqa
61
+ LifecycleManagerEntry,
35
62
  LifecycleManager,
63
+ AsyncLifecycleManager,
36
64
  )
37
65
 
38
66
  from .states import ( # noqa
39
- LifecycleState,
40
67
  LifecycleStateError,
68
+ LifecycleState,
41
69
  LifecycleStates,
42
70
  )
43
71
 
@@ -45,3 +73,49 @@ from .transitions import ( # noqa
45
73
  LifecycleTransition,
46
74
  LifecycleTransitions,
47
75
  )
76
+
77
+ from .unwrap import ( # noqa
78
+ unwrap_lifecycle,
79
+ unwrap_async_lifecycle,
80
+ unwrap_any_lifecycle,
81
+ )
82
+
83
+
84
+ ##
85
+
86
+
87
+ from .. import lang as _lang # noqa
88
+
89
+
90
+ with _lang.auto_proxy_init(globals()):
91
+ ##
92
+
93
+ from .injection import ( # noqa
94
+ bind_lifecycle_registrar,
95
+ bind_async_lifecycle_registrar,
96
+
97
+ bind_managed_lifecycle_manager,
98
+ bind_async_managed_lifecycle_manager,
99
+ )
100
+
101
+
102
+ ##
103
+
104
+
105
+ NEW = LifecycleStates.NEW
106
+
107
+ CONSTRUCTING = LifecycleStates.CONSTRUCTING
108
+ FAILED_CONSTRUCTING = LifecycleStates.FAILED_CONSTRUCTING
109
+ CONSTRUCTED = LifecycleStates.CONSTRUCTED
110
+
111
+ STARTING = LifecycleStates.STARTING
112
+ FAILED_STARTING = LifecycleStates.FAILED_STARTING
113
+ STARTED = LifecycleStates.STARTED
114
+
115
+ STOPPING = LifecycleStates.STOPPING
116
+ FAILED_STOPPING = LifecycleStates.FAILED_STOPPING
117
+ STOPPED = LifecycleStates.STOPPED
118
+
119
+ DESTROYING = LifecycleStates.DESTROYING
120
+ FAILED_DESTROYING = LifecycleStates.FAILED_DESTROYING
121
+ DESTROYED = LifecycleStates.DESTROYED