Skip to content

Commit 74e6d38

Browse files
authored
Merge pull request #283 from vkottler/dev/5.7.7
5.7.7 - Minor improvements
2 parents 0311186 + 5ebbc7d commit 74e6d38

File tree

10 files changed

+70
-10
lines changed

10 files changed

+70
-10
lines changed

.github/workflows/python-package.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ jobs:
7777
7878
- run: |
7979
mk python-release owner=vkottler \
80-
repo=runtimepy version=5.7.6
80+
repo=runtimepy version=5.7.7
8181
if: |
8282
matrix.python-version == '3.12'
8383
&& matrix.system == 'ubuntu-latest'

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@
22
=====================================
33
generator=datazen
44
version=3.1.4
5-
hash=41ff8742602f69f2831092a4b666cddc
5+
hash=0bf47d2ff3fb0ed78ed013f4fcbc59e2
66
=====================================
77
-->
88

9-
# runtimepy ([5.7.6](https://pypi.org/project/runtimepy/))
9+
# runtimepy ([5.7.7](https://pypi.org/project/runtimepy/))
1010

1111
[![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
1212
![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)

local/variables/package.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
22
major: 5
33
minor: 7
4-
patch: 6
4+
patch: 7
55
entry: runtimepy

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"
44

55
[project]
66
name = "runtimepy"
7-
version = "5.7.6"
7+
version = "5.7.7"
88
description = "A framework for implementing Python services."
99
readme = "README.md"
1010
requires-python = ">=3.11"

runtimepy/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# =====================================
22
# generator=datazen
33
# version=3.1.4
4-
# hash=cab7cff2cb194a61178fa386b80eae85
4+
# hash=ed12f307211d1317e3ce6a7c4409b97f
55
# =====================================
66

77
"""
@@ -10,7 +10,7 @@
1010

1111
DESCRIPTION = "A framework for implementing Python services."
1212
PKG_NAME = "runtimepy"
13-
VERSION = "5.7.6"
13+
VERSION = "5.7.7"
1414

1515
# runtimepy-specific content.
1616
METRICS_NAME = "metrics"

runtimepy/metrics/channel.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def update(self, other: "ChannelMetrics") -> None:
4343
def __str__(self) -> str:
4444
"""Get metrics as a string."""
4545

46-
return "\t".join(
46+
return " | ".join(
4747
[
4848
f"messages={self.messages.value}",
4949
f"message_rate={self.message_rate.value:.2f}",

runtimepy/net/arbiter/housekeeping/__init__.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ async def dispatch(self) -> bool:
5252

5353
# Handle any incoming commands.
5454
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+
):
5660
for item in mapping:
5761
if isinstance(item, AsyncCommandProcessingMixin):
5862
processors.append(item.process_command_queue())

runtimepy/net/arbiter/info.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from abc import ABC as _ABC
77
import asyncio as _asyncio
88
from contextlib import AsyncExitStack as _AsyncExitStack
9+
from contextlib import contextmanager
910
from dataclasses import dataclass
1011
from logging import getLogger as _getLogger
1112
from re import compile as _compile
@@ -57,13 +58,29 @@ class RuntimeStruct(RuntimeStructBase, _ABC):
5758

5859
byte_order: ByteOrder = DEFAULT_BYTE_ORDER
5960

61+
# Set this for structs to automatically be polled when the application is
62+
# going down.
63+
final_poll = False
64+
6065
def init_env(self) -> None:
6166
"""Initialize this sample environment."""
6267

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+
6377
async def build(self, app: "AppInfo", **kwargs) -> None:
6478
"""Build a struct instance's channel environment."""
6579

6680
self.app = app
81+
if self.final_poll:
82+
self.app.stack.enter_context(self._final_poll())
83+
6784
self.init_env()
6885
self.update_byte_order(self.byte_order, **kwargs)
6986

@@ -102,6 +119,9 @@ def poll(self) -> None:
102119
class SampleStruct(TrigStruct):
103120
"""A sample runtime structure."""
104121

122+
# For fun.
123+
final_poll = True
124+
105125
def init_env(self) -> None:
106126
"""Initialize this sample environment."""
107127
super().init_env()

runtimepy/struct/__init__.py

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,31 @@
33
"""
44

55
# built-in
6+
from argparse import Namespace
7+
import asyncio
68
from logging import getLogger as _getLogger
9+
from typing import Optional
710

811
# third-party
912
from vcorelib.io import MarkdownMixin
1013
from vcorelib.io.types import JsonObject as _JsonObject
1114

1215
# internal
1316
from runtimepy import PKG_NAME
17+
from runtimepy.channel.environment.command import FieldOrChannel
1418
from runtimepy.channel.environment.command.processor import (
1519
ChannelCommandProcessor,
1620
)
21+
from runtimepy.mixins.async_command import AsyncCommandProcessingMixin
1722
from runtimepy.mixins.environment import ChannelEnvironmentMixin
1823
from runtimepy.mixins.logging import LoggerMixinLevelControl
1924

2025

2126
class RuntimeStructBase(
22-
LoggerMixinLevelControl, ChannelEnvironmentMixin, MarkdownMixin
27+
LoggerMixinLevelControl,
28+
ChannelEnvironmentMixin,
29+
AsyncCommandProcessingMixin,
30+
MarkdownMixin,
2331
):
2432
"""A base runtime structure."""
2533

@@ -42,6 +50,23 @@ def __init__(
4250
self.command = ChannelCommandProcessor(self.env, self.logger)
4351
self.config = config
4452

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+
4570
def poll(self) -> None:
4671
"""
4772
A method that other runtime entities can call to perform canonical

tests/net/server/__init__.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ async def runtimepy_http_client_server(
139139
client.request_json(
140140
RequestHeader(method="POST", target="/sample1/custom/asdf")
141141
),
142+
client.request_json(
143+
RequestHeader(method="POST", target="/struct2/custom/poll")
144+
),
145+
client.request_json(
146+
RequestHeader(method="POST", target="/struct2/custom/poll/5")
147+
),
148+
client.request_json(
149+
RequestHeader(
150+
method="POST", target="/struct2/custom/poll/5/0.01"
151+
)
152+
),
142153
client.request_json(
143154
RequestHeader(
144155
method="POST", target="/sample1/custom/test_command"

0 commit comments

Comments
 (0)