Skip to content

Commit

Permalink
Merge pull request #235 from vkottler/dev/controls
Browse files Browse the repository at this point in the history
Dev/controls
  • Loading branch information
vkottler authored Jun 21, 2024
2 parents 5bcccf7 + 93ad999 commit 6297e39
Show file tree
Hide file tree
Showing 46 changed files with 656 additions and 136 deletions.
7 changes: 6 additions & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ on:
env:
TWINE_PASSWORD: ${{secrets.TWINE_PASSWORD}}
GITHUB_API_TOKEN: ${{secrets.API_TOKEN}}
CODECOV_TOKEN: ${{secrets.CODECOV_TOKEN}}

jobs:
build:
Expand Down Expand Up @@ -60,6 +61,10 @@ jobs:
PY_TEST_EXTRA_ARGS: --cov-report=xml

- uses: codecov/codecov-action@v3.1.5
with:
fail_ci_if_error: true
verbose: true
token: ${{secrets.CODECOV_TOKEN}}

- run: mk pypi-upload-ci
env:
Expand All @@ -72,7 +77,7 @@ jobs:
- run: |
mk python-release owner=vkottler \
repo=runtimepy version=4.6.1
repo=runtimepy version=5.0.0
if: |
matrix.python-version == '3.11'
&& matrix.system == 'ubuntu-latest'
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.1.4
hash=4418deec8fe739bca86f22f58d2f3e1f
hash=895daf8e1a0633698eac373d7017dbde
=====================================
-->

# runtimepy ([4.6.1](https://pypi.org/project/runtimepy/))
# runtimepy ([5.0.0](https://pypi.org/project/runtimepy/))

[![python](https://img.shields.io/pypi/pyversions/runtimepy.svg)](https://pypi.org/project/runtimepy/)
![Build Status](https://github.com/vkottler/runtimepy/workflows/Python%20Package/badge.svg)
Expand Down
2 changes: 1 addition & 1 deletion config
2 changes: 1 addition & 1 deletion local/configs/package.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: A framework for implementing Python services.
entry: {{entry}}

requirements:
- vcorelib>=3.2.6
- vcorelib>=3.2.8
- svgen>=0.6.7
- websockets
- psutil
Expand Down
6 changes: 3 additions & 3 deletions local/variables/package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
major: 4
minor: 6
patch: 1
major: 5
minor: 0
patch: 0
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 = "4.6.1"
version = "5.0.0"
description = "A framework for implementing Python services."
readme = "README.md"
requires-python = ">=3.11"
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.1.4
# hash=1f6ecacb506da0891ce4397cd8209529
# hash=8c2e796a8c4689d3e6713f7e3647ed13
# =====================================

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

DESCRIPTION = "A framework for implementing Python services."
PKG_NAME = "runtimepy"
VERSION = "4.6.1"
VERSION = "5.0.0"

# runtimepy-specific content.
METRICS_NAME = "metrics"
Expand Down
6 changes: 6 additions & 0 deletions runtimepy/channel/environment/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ def names(self) -> _Iterator[str]:
"""Iterate over registered names in the environment."""
yield from self.channels.names.names

def search_names(
self, pattern: str, exact: bool = False
) -> _Iterator[str]:
"""Search for names belonging to this environment."""
yield from self.channels.names.search(pattern, exact=exact)

def set_default(self, key: str, default: _Default) -> None:
"""Set a new default value for a channel."""

Expand Down
Empty file added runtimepy/control/__init__.py
Empty file.
56 changes: 56 additions & 0 deletions runtimepy/control/env/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"""
A module implementing runtime-environment registration routines for commonly
used control channel types.
"""

# built-in
from typing import TypeVar

# internal
from runtimepy.channel.environment import ChannelEnvironment
from runtimepy.primitives import AnyPrimitive
from runtimepy.ui.controls import Controlslike

T = TypeVar("T", bound=AnyPrimitive)


def phase_angle(
env: ChannelEnvironment,
primitive: type[T],
name: str = "phase_angle",
controls: Controlslike = "phase",
**kwargs,
) -> T:
"""Create a phase-angle channel."""

prim = primitive()
env.channel(name, prim, commandable=True, controls=controls, **kwargs)
return prim # type: ignore


def amplitude(
env: ChannelEnvironment,
primitive: type[T],
name: str = "amplitude",
controls: Controlslike = "amplitude",
**kwargs,
) -> T:
"""Create an amplitude channel."""

prim = primitive()
env.channel(name, prim, commandable=True, controls=controls, **kwargs)
return prim # type: ignore


def steps(
env: ChannelEnvironment,
primitive: type[T],
name: str = "steps",
controls: Controlslike = "steps",
**kwargs,
) -> T:
"""Create a steps channel."""

prim = primitive()
env.channel(name, prim, commandable=True, controls=controls, **kwargs)
return prim # type: ignore
68 changes: 68 additions & 0 deletions runtimepy/control/source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
"""
A module implementing signal source structs.
"""

# built-in
from abc import abstractmethod
from typing import Any, Generic, cast

# internal
from runtimepy.control.env import amplitude
from runtimepy.net.arbiter.info import RuntimeStruct
from runtimepy.primitives import Double, T


class PrimitiveSource(RuntimeStruct, Generic[T]):
"""A simple output-source struct."""

kind: type[T]

outputs: list[T]
amplitudes: list[Double]

length: int

def init_source(self) -> None:
"""Initialize this value source."""

@abstractmethod
def source(self, index: int) -> float | int | bool:
"""Provide the next value."""

def init_env(self) -> None:
"""Initialize this double-source environment."""

self.outputs = []
self.amplitudes = []

# Load 'count' from config.
count: int = self.config.get("count", 1) # type: ignore

for idx in range(count):
# Output channel.
output = self.kind()
self.outputs.append(output)
self.env.channel(f"{idx}.output", output)

# Amplitude channel.
self.amplitudes.append(
amplitude(self.env, Double, name=f"{idx}.amplitude")
)

self.init_source()
self.length = len(self.outputs)

def poll(self) -> None:
"""Update the outputs."""

for idx in range(self.length):
# Difficult to avoid cast.
self.outputs[idx].value = cast(
Any, self.amplitudes[idx].value * self.source(idx)
)


class DoubleSource(PrimitiveSource[Double]):
"""A simple double output source."""

kind = Double
Loading

0 comments on commit 6297e39

Please sign in to comment.