runtimepy 5.7.6__py3-none-any.whl → 5.7.7__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.
runtimepy/__init__.py CHANGED
@@ -1,7 +1,7 @@
1
1
  # =====================================
2
2
  # generator=datazen
3
3
  # version=3.1.4
4
- # hash=cab7cff2cb194a61178fa386b80eae85
4
+ # hash=ed12f307211d1317e3ce6a7c4409b97f
5
5
  # =====================================
6
6
 
7
7
  """
@@ -10,7 +10,7 @@ Useful defaults and other package metadata.
10
10
 
11
11
  DESCRIPTION = "A framework for implementing Python services."
12
12
  PKG_NAME = "runtimepy"
13
- VERSION = "5.7.6"
13
+ VERSION = "5.7.7"
14
14
 
15
15
  # runtimepy-specific content.
16
16
  METRICS_NAME = "metrics"
@@ -43,7 +43,7 @@ class ChannelMetrics:
43
43
  def __str__(self) -> str:
44
44
  """Get metrics as a string."""
45
45
 
46
- return "\t".join(
46
+ return " | ".join(
47
47
  [
48
48
  f"messages={self.messages.value}",
49
49
  f"message_rate={self.message_rate.value:.2f}",
@@ -52,7 +52,11 @@ class ConnectionMetricsPoller(_ArbiterTask):
52
52
 
53
53
  # Handle any incoming commands.
54
54
  processors: list[Awaitable[None]] = []
55
- for mapping in self.app.connections.values(), self.app.tasks.values():
55
+ for mapping in (
56
+ self.app.connections.values(),
57
+ self.app.tasks.values(),
58
+ self.app.structs.values(),
59
+ ):
56
60
  for item in mapping:
57
61
  if isinstance(item, AsyncCommandProcessingMixin):
58
62
  processors.append(item.process_command_queue())
@@ -6,6 +6,7 @@ A module implementing an application information interface.
6
6
  from abc import ABC as _ABC
7
7
  import asyncio as _asyncio
8
8
  from contextlib import AsyncExitStack as _AsyncExitStack
9
+ from contextlib import contextmanager
9
10
  from dataclasses import dataclass
10
11
  from logging import getLogger as _getLogger
11
12
  from re import compile as _compile
@@ -57,13 +58,29 @@ class RuntimeStruct(RuntimeStructBase, _ABC):
57
58
 
58
59
  byte_order: ByteOrder = DEFAULT_BYTE_ORDER
59
60
 
61
+ # Set this for structs to automatically be polled when the application is
62
+ # going down.
63
+ final_poll = False
64
+
60
65
  def init_env(self) -> None:
61
66
  """Initialize this sample environment."""
62
67
 
68
+ @contextmanager
69
+ def _final_poll(self) -> _Iterator[None]:
70
+ """Poll when the context ends."""
71
+
72
+ try:
73
+ yield
74
+ finally:
75
+ self.poll()
76
+
63
77
  async def build(self, app: "AppInfo", **kwargs) -> None:
64
78
  """Build a struct instance's channel environment."""
65
79
 
66
80
  self.app = app
81
+ if self.final_poll:
82
+ self.app.stack.enter_context(self._final_poll())
83
+
67
84
  self.init_env()
68
85
  self.update_byte_order(self.byte_order, **kwargs)
69
86
 
@@ -102,6 +119,9 @@ class TrigStruct(RuntimeStruct, TrigMixin):
102
119
  class SampleStruct(TrigStruct):
103
120
  """A sample runtime structure."""
104
121
 
122
+ # For fun.
123
+ final_poll = True
124
+
105
125
  def init_env(self) -> None:
106
126
  """Initialize this sample environment."""
107
127
  super().init_env()
@@ -3,7 +3,10 @@ A module implementing a runtime structure base.
3
3
  """
4
4
 
5
5
  # built-in
6
+ from argparse import Namespace
7
+ import asyncio
6
8
  from logging import getLogger as _getLogger
9
+ from typing import Optional
7
10
 
8
11
  # third-party
9
12
  from vcorelib.io import MarkdownMixin
@@ -11,15 +14,20 @@ from vcorelib.io.types import JsonObject as _JsonObject
11
14
 
12
15
  # internal
13
16
  from runtimepy import PKG_NAME
17
+ from runtimepy.channel.environment.command import FieldOrChannel
14
18
  from runtimepy.channel.environment.command.processor import (
15
19
  ChannelCommandProcessor,
16
20
  )
21
+ from runtimepy.mixins.async_command import AsyncCommandProcessingMixin
17
22
  from runtimepy.mixins.environment import ChannelEnvironmentMixin
18
23
  from runtimepy.mixins.logging import LoggerMixinLevelControl
19
24
 
20
25
 
21
26
  class RuntimeStructBase(
22
- LoggerMixinLevelControl, ChannelEnvironmentMixin, MarkdownMixin
27
+ LoggerMixinLevelControl,
28
+ ChannelEnvironmentMixin,
29
+ AsyncCommandProcessingMixin,
30
+ MarkdownMixin,
23
31
  ):
24
32
  """A base runtime structure."""
25
33
 
@@ -42,6 +50,23 @@ class RuntimeStructBase(
42
50
  self.command = ChannelCommandProcessor(self.env, self.logger)
43
51
  self.config = config
44
52
 
53
+ async def poll(args: Namespace, __: Optional[FieldOrChannel]) -> None:
54
+ """Handle a test command."""
55
+
56
+ count = 1
57
+ delay = 0.0
58
+
59
+ if args.extra:
60
+ count = int(args.extra[0])
61
+ if len(args.extra) > 1:
62
+ delay = float(args.extra[1])
63
+
64
+ for _ in range(count):
65
+ self.poll()
66
+ await asyncio.sleep(delay)
67
+
68
+ self._setup_async_commands(poll)
69
+
45
70
  def poll(self) -> None:
46
71
  """
47
72
  A method that other runtime entities can call to perform canonical
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: runtimepy
3
- Version: 5.7.6
3
+ Version: 5.7.7
4
4
  Summary: A framework for implementing Python services.
5
5
  Home-page: https://github.com/vkottler/runtimepy
6
6
  Author: Vaughn Kottler
@@ -17,11 +17,11 @@ Classifier: License :: OSI Approved :: MIT License
17
17
  Requires-Python: >=3.11
18
18
  Description-Content-Type: text/markdown
19
19
  License-File: LICENSE
20
+ Requires-Dist: svgen >=0.6.8
20
21
  Requires-Dist: aiofiles
21
22
  Requires-Dist: websockets
22
23
  Requires-Dist: vcorelib >=3.4.2
23
24
  Requires-Dist: psutil
24
- Requires-Dist: svgen >=0.6.8
25
25
  Provides-Extra: test
26
26
  Requires-Dist: pylint ; extra == 'test'
27
27
  Requires-Dist: flake8 ; extra == 'test'
@@ -45,11 +45,11 @@ Requires-Dist: uvloop ; (sys_platform != "win32" and sys_platform != "cygwin") a
45
45
  =====================================
46
46
  generator=datazen
47
47
  version=3.1.4
48
- hash=41ff8742602f69f2831092a4b666cddc
48
+ hash=0bf47d2ff3fb0ed78ed013f4fcbc59e2
49
49
  =====================================
50
50
  -->
51
51
 
52
- # runtimepy ([5.7.6](https://pypi.org/project/runtimepy/))
52
+ # runtimepy ([5.7.7](https://pypi.org/project/runtimepy/))
53
53
 
54
54
  [![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
55
55
  ![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
@@ -1,4 +1,4 @@
1
- runtimepy/__init__.py,sha256=47z6hCc2pWcbeYdGuB007x_wR84imlspZBFz0Ue3_oc,390
1
+ runtimepy/__init__.py,sha256=ifv28DYiMhfJHoYR8HQoEZaUsU7HvJuVEy6bMmCZqYc,390
2
2
  runtimepy/__main__.py,sha256=OPAed6hggoQdw-6QAR62mqLC-rCkdDhOq0wyeS2vDRI,332
3
3
  runtimepy/app.py,sha256=sTvatbsGZ2Hdel36Si_WUbNMtg9CzsJyExr5xjIcxDE,970
4
4
  runtimepy/dev_requirements.txt,sha256=j0dh11ztJAzfaUL0iFheGjaZj9ppDzmTkclTT8YKO8c,230
@@ -125,7 +125,7 @@ runtimepy/message/handlers.py,sha256=He9NC7MCkaV2clKc8dTSZ_T8N2l3ATjaTFzBr9n1T34
125
125
  runtimepy/message/interface.py,sha256=vg25Uhp7wrDFH6v2iRKUBwnCBpjc3JAFjwdu3KArrLo,11285
126
126
  runtimepy/message/types.py,sha256=vajDWKW32LjzsfH-eVCCxZTWVctj4_-tjanhnmCqUis,821
127
127
  runtimepy/metrics/__init__.py,sha256=NyCcB3uJi4_tGMO-ws3CPRA2fph2t15BcW_tfeV9fmc,357
128
- runtimepy/metrics/channel.py,sha256=YhALSMCPHESkYChzzE6dNAxKX-2bPqVe02E_qeyyt5E,2526
128
+ runtimepy/metrics/channel.py,sha256=rCF_NZ4UaIYV4NExmw0Mskzyd2Npy-c_hFiRe36_bzg,2527
129
129
  runtimepy/metrics/connection.py,sha256=FiN0BQ79eDBf5qCh1sx7m6CSDbMMW7WMi7li96mHkoo,808
130
130
  runtimepy/metrics/task.py,sha256=g6CttQ3SS217DJRBFnj-rDUq6uauZdMOcTOjHgSEfWo,1911
131
131
  runtimepy/mixins/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -148,7 +148,7 @@ runtimepy/net/util.py,sha256=P6WnH4n8JJkEfKwepk1eP4lGPxWjqcFv0yL3N0mvtrw,5897
148
148
  runtimepy/net/apps/__init__.py,sha256=vjo7e19QXtJwe6V6B-QGvYiJveYobnYIfpkKZrnS17w,710
149
149
  runtimepy/net/arbiter/__init__.py,sha256=ptKF995rYKvkm4Mya92vA5QEDqcFq5NRD0IYGqZ6_do,740
150
150
  runtimepy/net/arbiter/base.py,sha256=w5IFDRU1Zfw7sfg0eS8hj7_Ip6bHHYQ4S212Ic-Kj-c,14817
151
- runtimepy/net/arbiter/info.py,sha256=zipdr928xN32Dt5Wl_FbCCAf7XOlT0GGNHiv4DoI-94,9216
151
+ runtimepy/net/arbiter/info.py,sha256=tlzfbn3soyejArxfZ4lrLbaBVOjiz4nX52wa6XMfXuo,9684
152
152
  runtimepy/net/arbiter/result.py,sha256=PHZo5qj4SI08ZeWPFk_8OZ1umI6L0dp5nJpjjS8QUpM,2871
153
153
  runtimepy/net/arbiter/task.py,sha256=APcc5QioAG8uueIzxJU-vktIn8Ys3yJd_CFlRWb6Ieo,795
154
154
  runtimepy/net/arbiter/udp.py,sha256=-ecHJs-utcsiTfr5wSb73hUUuYFBeRVT_D1znYp5q6A,893
@@ -159,7 +159,7 @@ runtimepy/net/arbiter/config/util.py,sha256=MezLSil5mEwioI5kxDOZa9y118st1_t0El8D
159
159
  runtimepy/net/arbiter/factory/__init__.py,sha256=jC1szUYucH4Us3jbb0mhFgnklHlorya5DYGGw2pqfe4,334
160
160
  runtimepy/net/arbiter/factory/connection.py,sha256=uSwnvIWGJcDd2ReK-s9lBx-NcRQ1JH_7VbwkWjE_8zA,3690
161
161
  runtimepy/net/arbiter/factory/task.py,sha256=YLRv55dnDBqHRJIMYgO9_uHi0AW-8hwa0n3wHAKyncE,1959
162
- runtimepy/net/arbiter/housekeeping/__init__.py,sha256=80vzksjCq1r9Kx25YeOKTJu2Ek98YWvEEgrsC8qzwJM,3469
162
+ runtimepy/net/arbiter/housekeeping/__init__.py,sha256=mgrYnDdL1DSP6fXdtk2VU9uqTvtgX2VX5q2Q9EfcJus,3545
163
163
  runtimepy/net/arbiter/imports/__init__.py,sha256=W7-kkM4B_zDU42Fyh0PmZL56JslS_0_qzvpzUhN6aDU,5041
164
164
  runtimepy/net/arbiter/imports/util.py,sha256=d4_HnWphrkiHQkyYr8YJKvSSTXoMf3Bct_7jg_CS9eA,1086
165
165
  runtimepy/net/arbiter/struct/__init__.py,sha256=Vr38dp2X0PZOrAbjKsZ9xZdQ1j3z92s4QuvRtYYVuNI,5990
@@ -261,7 +261,7 @@ runtimepy/registry/name.py,sha256=uhxmijwUT7x59NUYV4hJSe7VcnAbLDUSAPaKhR6K-N0,17
261
261
  runtimepy/sample/__init__.py,sha256=N7P6hnCLF9NwnkZA1h3LzS2C334SAO48Fu8adHxWGLU,56
262
262
  runtimepy/sample/peer.py,sha256=eZJ3gmvGsXoRTIyJ_OS71T5C1kjysbvd-yF5xZxedLU,1621
263
263
  runtimepy/sample/program.py,sha256=wL61OzdUYrHw3Lwbd_eeBDARhS7kEzdifGOFgXvvnAw,2332
264
- runtimepy/struct/__init__.py,sha256=B8sb-fEXX_rpJ8ssVuZiZPmnmxKdY1DY6I_mrGm578c,1491
264
+ runtimepy/struct/__init__.py,sha256=wFjLwX83ztCF1CuFxnldetzMOoBs_UMirLV778GBGZc,2220
265
265
  runtimepy/subprocess/__init__.py,sha256=VAiFrYFCU5ETDVoWLOVlrrSsx2d1_atYXUfXYc_OQ9g,4059
266
266
  runtimepy/subprocess/interface.py,sha256=rYvM8bgoT4DoXGhdidhfmivzrjmEoW6788DjGyAdJ7A,8032
267
267
  runtimepy/subprocess/peer.py,sha256=oYw9a0yKAPR18Z6Qt24wYWrcX6EizeQE64htL11WVjM,7593
@@ -284,9 +284,9 @@ runtimepy/tui/task.py,sha256=nUZo9fuOC-k1Wpqdzkv9v1tQirCI28fZVgcC13Ijvus,1093
284
284
  runtimepy/tui/channels/__init__.py,sha256=evDaiIn-YS9uGhdo8ZGtP9VK1ek6sr_P1nJ9JuSET0o,4536
285
285
  runtimepy/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
286
286
  runtimepy/ui/controls.py,sha256=yvT7h3thbYaitsakcIAJ90EwKzJ4b-jnc6p3UuVf_XE,1241
287
- runtimepy-5.7.6.dist-info/LICENSE,sha256=okYCYhGsx_BlzvFdoNVBVpw_Cfb4SOqHA_VAARml4Hc,1071
288
- runtimepy-5.7.6.dist-info/METADATA,sha256=p5qI1xHfkh1RGygCvs5SsLxk4NzECG15G_5699VRsl8,9308
289
- runtimepy-5.7.6.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
290
- runtimepy-5.7.6.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
291
- runtimepy-5.7.6.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
292
- runtimepy-5.7.6.dist-info/RECORD,,
287
+ runtimepy-5.7.7.dist-info/LICENSE,sha256=okYCYhGsx_BlzvFdoNVBVpw_Cfb4SOqHA_VAARml4Hc,1071
288
+ runtimepy-5.7.7.dist-info/METADATA,sha256=RbUgD3uuOyvV__lOtj8TAIca5btsr-2wW4monhtDWZ8,9308
289
+ runtimepy-5.7.7.dist-info/WHEEL,sha256=OVMc5UfuAQiSplgO0_WdW7vXVGAt9Hdd6qtN4HotdyA,91
290
+ runtimepy-5.7.7.dist-info/entry_points.txt,sha256=-btVBkYv7ybcopqZ_pRky-bEzu3vhbaG3W3Z7ERBiFE,51
291
+ runtimepy-5.7.7.dist-info/top_level.txt,sha256=0jPmh6yqHyyJJDwEID-LpQly-9kQ3WRMjH7Lix8peLg,10
292
+ runtimepy-5.7.7.dist-info/RECORD,,