Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ jobs:

- run: |
mk python-release owner=libre-embedded \
repo=runtimepy version=5.15.4
repo=runtimepy version=5.15.5
if: |
matrix.python-version == '3.12'
&& matrix.system == 'ubuntu-latest'
Expand Down
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[DESIGN]
max-args=10
max-positional-arguments=10
max-attributes=16
max-attributes=17
max-parents=14
max-public-methods=22
max-branches=13
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
=====================================
generator=datazen
version=3.2.3
hash=99eea1986d2105483ebb2fe566128f5f
hash=fd0e57419cf9437a64c4f82cae3625f0
=====================================
-->

# runtimepy ([5.15.4](https://pypi.org/project/runtimepy/))
# runtimepy ([5.15.5](https://pypi.org/project/runtimepy/))

[![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
![Build Status](https://github.com/libre-embedded/runtimepy/workflows/Python%20Package/badge.svg)
Expand Down
2 changes: 1 addition & 1 deletion local/configs/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ time_command: true

requirements:
- aiofiles
- vcorelib>=3.6.3
- vcorelib>=3.6.4
- svgen>=0.8.0
- websockets
- psutil
Expand Down
2 changes: 1 addition & 1 deletion local/variables/package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
major: 5
minor: 15
patch: 4
patch: 5
entry: runtimepy
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta:__legacy__"

[project]
name = "runtimepy"
version = "5.15.4"
version = "5.15.5"
description = "A framework for implementing Python services."
readme = "README.md"
requires-python = ">=3.12"
Expand Down
4 changes: 2 additions & 2 deletions runtimepy/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# =====================================
# generator=datazen
# version=3.2.3
# hash=b0f0463a508c9a1312a071f5c0b06f3b
# hash=8ce7abe0f8c0e64d9afc0b5e4de6e2ad
# =====================================

"""
Expand All @@ -10,7 +10,7 @@

DESCRIPTION = "A framework for implementing Python services."
PKG_NAME = "runtimepy"
VERSION = "5.15.4"
VERSION = "5.15.5"

# runtimepy-specific content.
METRICS_NAME = "metrics"
Expand Down
12 changes: 11 additions & 1 deletion runtimepy/channel/environment/command/processor.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
from runtimepy.mixins.environment import ChannelEnvironmentMixin
from runtimepy.primitives.bool import Bool
from runtimepy.primitives.field import BitField
from runtimepy.ui.button import ActionButton

CommandHook = Callable[[Namespace, Optional[FieldOrChannel]], None]

Expand All @@ -33,7 +34,11 @@ class ChannelCommandProcessor(ChannelEnvironmentMixin):
"""A command processing interface for channel environments."""

def __init__(
self, env: ChannelEnvironment, logger: LoggerType, **kwargs
self,
env: ChannelEnvironment,
logger: LoggerType,
buttons: list[ActionButton] = None,
**kwargs,
) -> None:
"""Initialize this instance."""

Expand All @@ -49,6 +54,11 @@ def __init__(

self.parser.initialize()

# Action buttons.
if buttons is None:
buttons = []
self.buttons: list[ActionButton] = buttons

def register_custom_commands(
self, *custom_commands: CustomCommand
) -> None:
Expand Down
4 changes: 4 additions & 0 deletions runtimepy/data/css/bootstrap_extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ select:hover {
background-image: linear-gradient(to bottom, var(--bs-tertiary-bg), rgba(var(--bs-tertiary-bg-rgb), 0), var(--bs-tertiary-bg));
}

.bg-gradient-tertiary-left-right {
background-image: linear-gradient(to right, var(--bs-tertiary-bg), rgba(var(--bs-tertiary-bg-rgb), 0), var(--bs-tertiary-bg));
}

.border-start-info-subtle {
border-left: var(--bs-border-width) var(--bs-border-style) var(--bs-info-border-subtle);
}
Expand Down
8 changes: 8 additions & 0 deletions runtimepy/data/css/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -74,3 +74,11 @@ body > :first-child {
.overscroll-behavior-none {
overscroll-behavior: none;
}

.channel-views-min-width {
min-width: 5.5em;
}

.channel-filter-min-width {
min-width: 5.5em;
}
62 changes: 41 additions & 21 deletions runtimepy/data/dummy_load.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,42 @@
---
# UDP JSON clients.
clients:
- factory: udp_json
name: udp_json_client
defer: true
kwargs:
remote_addr: [localhost, "$udp_json"]
views:
- [metrics, metrics]
- [transmit, tx]
- [receive, rx]
buttons: &buttons
- icon: tux
key: test
payload: {}
- icon: tux
key: test
text: asdf
payload: {}
- icon: tux
key: test
payload: {}
outline: false
- icon: tux
key: test
text: asdf
payload: {}
outline: false
markdown: |
# `udp_json_client`

Connects to `udp_json_server`.

- factory: udp_json
name: udp_json_server
kwargs:
local_addr: [localhost, "$udp_json"]

# Add some sample tasks.
tasks:
# Chaos.
Expand All @@ -9,6 +47,7 @@ tasks:
a: 1
b: 2
c: 3
buttons: *buttons
views:
- [zero, "\\.0\\."]
- [one, "\\.1\\."]
Expand Down Expand Up @@ -49,27 +88,6 @@ tasks:
# Drive interactions with runtime entities that won't otherwise be polled.
- {name: app, factory: SampleApp, period_s: 0.25}

# UDP JSON clients.
clients:
- factory: udp_json
name: udp_json_client
defer: true
kwargs:
remote_addr: [localhost, "$udp_json"]
views:
- [metrics, metrics]
- [transmit, tx]
- [receive, rx]
markdown: |
# `udp_json_client`

Connects to `udp_json_server`.

- factory: udp_json
name: udp_json_server
kwargs:
local_addr: [localhost, "$udp_json"]

# Add some sample structs.
structs:
- name: example.struct1
Expand All @@ -80,6 +98,8 @@ structs:
b: 2
c: 3

buttons: *buttons

markdown: |
# Docs for `example.struct1`

Expand Down
2 changes: 1 addition & 1 deletion runtimepy/data/js/classes/WorkerInterface.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ class WorkerInterface {

command(data) { this.send({kind : "command", value : data}); }

bus(data) { this.worker.postMessage({bus : data}); }
bus(key, data) { this.worker.postMessage({key : key, bus : data}); }

toWorker(data, param) { return this.send({"worker" : data}, param); }
}
2 changes: 1 addition & 1 deletion runtimepy/data/js/sample.js
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
console.log(`sample.js included (${tab.name})`);
// tab.worker.bus({a: 1, b: 2, c: 3});
// tab.worker.bus("test", {a: 1, b: 2, c: 3});
17 changes: 17 additions & 0 deletions runtimepy/data/schemas/Button.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
---
type: object
additionalProperties: false
required: [key, payload]
properties:
key:
type: string
payload:
type: object
text:
type: string
icon:
type: string
variant:
type: string
outline:
type: boolean
1 change: 1 addition & 0 deletions runtimepy/data/schemas/ClientConnectionConfig.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ includes:
- has_name.yaml
- has_markdown.yaml
- has_views.yaml
- has_buttons.yaml

properties:
defer:
Expand Down
6 changes: 6 additions & 0 deletions runtimepy/data/schemas/has_buttons.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
properties:
buttons:
type: array
items:
$ref: package://runtimepy/schemas/Button.yaml
12 changes: 12 additions & 0 deletions runtimepy/net/arbiter/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
from runtimepy.net.server import RuntimepyServerConnection
from runtimepy.subprocess.peer import RuntimepyPeer as _RuntimepyPeer
from runtimepy.tui.mixin import CursesWindow, TuiMixin
from runtimepy.ui.button import ActionButton

ServerTask = _Awaitable[None]
RuntimeProcessTask = tuple[
Expand Down Expand Up @@ -148,6 +149,7 @@ def __init__(

self._commands: list[tuple[str, str]] = []
self._views: dict[str, dict[str, str]] = {}
self._buttons: dict[str, list[ActionButton]] = {}

self._init()

Expand All @@ -157,9 +159,16 @@ def _init(self) -> None:
def _register_connection(self, connection: _Connection, name: str) -> None:
"""Perform connection registration."""

# Handle views.
if name in self._views:
connection.env.views.update(self._views[name])
del self._views[name]

# Handle buttons.
if name in self._buttons:
connection.command.buttons.extend(self._buttons[name])
del self._buttons[name]

self._connections[name] = connection
self.manager.queue.put_nowait(connection)
connection.logger.info("Registered as '%s'.", name)
Expand All @@ -170,6 +179,7 @@ def register_connection(
*names: str,
delim: str = None,
views: dict[str, str] = None,
buttons: list[ActionButton] = None,
) -> bool:
"""Attempt to register a connection object."""

Expand All @@ -180,6 +190,8 @@ def register_connection(

if views:
self._views[name] = views
if buttons:
self._buttons[name] = buttons

if (
name not in self._connections
Expand Down
1 change: 1 addition & 0 deletions runtimepy/net/arbiter/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@ async def process_config(
**fix_kwargs(kwargs),
views=client.get("views"),
markdown=client.get("markdown"),
buttons=client.get("buttons", []),
), f"Couldn't register client '{name}' ({factory})!"

# Register servers.
Expand Down
3 changes: 3 additions & 0 deletions runtimepy/net/arbiter/factory/connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from runtimepy.net.arbiter.base import ServerTask as _ServerTask
from runtimepy.net.connection import Connection as _Connection
from runtimepy.net.manager import ConnectionManager as _ConnectionManager
from runtimepy.ui.button import ActionButton


class ConnectionFactory:
Expand Down Expand Up @@ -90,6 +91,7 @@ async def factory_client(
factory_inst = self._conn_factories[factory]

views = kwargs.pop("views", {})
buttons = ActionButton.from_top_level(kwargs.pop("buttons", []))

conn = factory_inst.client(name, *args, **kwargs)
if not defer:
Expand All @@ -100,6 +102,7 @@ async def factory_client(
*self._conn_names[factory_inst],
name,
views=views,
buttons=buttons,
)

return result
Expand Down
11 changes: 11 additions & 0 deletions runtimepy/net/server/app/env/tab/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
A module implementing a channel-environment tab HTML interface.
"""

# built-in
from io import StringIO

# third-party
from vcorelib.io.markdown import MarkdownMixin
from vcorelib.logging import LoggerMixin
Expand Down Expand Up @@ -39,3 +42,11 @@ def __init__(
# Logging.
LoggerMixin.__init__(self, logger=self.command.logger)
self.log_limiter = RateLimiter.from_s(1.0)

def _action_markdown(self) -> str:
"""Get action-button markdown."""

with StringIO() as stream:
for button in self.command.buttons:
button.element().encode(stream)
return stream.getvalue()
10 changes: 10 additions & 0 deletions runtimepy/net/server/app/env/tab/html.py
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,16 @@ def compose(self, parent: Element) -> None:
)
logs.booleans.add("readonly")

if self.command.buttons:
centered_markdown(
vert_container,
self._action_markdown(),
"border-start",
"border-bottom",
"border-end",
"bg-gradient-tertiary-left-right",
)

self.channel_table(vert_container)

centered_markdown(
Expand Down
Loading