Skip to main content

tango-frame

en ja

tango-frame automatically exposes an ordinary Python device-control class as a TANGO Device Server and provides a corresponding Python client wrapper.

The device-control class itself does not need to import PyTango or inherit from tango.server.Device. Public methods are mapped to TANGO commands and Python properties are mapped to TANGO attributes.

Concept

The framework keeps the device implementation and the communication layer separate.

ordinary Python device class
        |
        +---- tango-frame ----> TANGO Device Server
        |                        method   -> command
        |                        property -> attribute
        |
        +---- tango-frame ----> Python client wrapper
                                 |
                                 +---- TANGO DeviceProxy

tango-frame is not a separate RPC protocol layered on top of TANGO. It generates and uses normal TANGO commands and attributes.

Features

  • An ordinary Python class is used as the device API definition.
  • Public methods are exposed as named TANGO commands.
  • @property values are exposed as TANGO attributes.
  • Read/write Python properties become read/write TANGO attributes.
  • Native TANGO-compatible scalar and homogeneous array types are used when possible.
  • Calls that cannot be represented directly by one TANGO command input, such as heterogeneous multiple arguments, are packed into one JSON string input.
  • Complex return values that cannot be represented by a native TANGO type are encoded as JSON strings.
  • The client presents the device API as Python methods and properties while communicating through tango.DeviceProxy.
  • Device-specific client behavior can override automatic remote dispatch.

Package layout

src/
└── tango_frame/
    ├── __init__.py
    ├── auto_dispatch.py
    ├── client.py
    ├── codec.py
    ├── introspection.py
    ├── server.py
    └── type_mapping.py

example/
└── device_server/
    ├── src/
    │   └── device/
    │       ├── device_class.py
    │       └── server_tango/
    │           ├── tango_ds.py
    │           └── device_client.py
    └── example/
        ├── server_start.py
        └── client.py

src/tango_frame/ is the reusable framework and contains no concrete device implementation.

example/device_server/src/device/ is a concrete example device module. device_class.py is independent of TANGO. server_tango/ contains only the TANGO-specific adaptation for that device.

Installation

pip install .

Important: strong Python / TANGO version dependencies. This is not a general-purpose Python RPC framework. It depends on PyTango and native TANGO libraries. Installation or execution may be impossible for certain combinations of Python version, operating system, CPU architecture, and TANGO runtime. Many existing instrument environments cannot use this framework, especially when their Python or TANGO versions cannot be upgraded.

Package and runtime requirements (v0.1.4)

Component Requirements and limitations
tango-frame Package metadata requires Python >=3.9. Python 3.7/3.8 cannot use PyTango 10.
PyTango pytango>=10. Version 10.0.x requires Python >=3.9; the 10.1 and 10.3 series require Python >=3.10.
xlogger-py xlogger-py. Published version 0.3.1 requires Python >=3.7.
setuptools setuptools>=61 for building; not a runtime dependency.
cppTango PyTango 10.0.x requires cppTango >=10.0.0; other PyTango series may require different cppTango versions.
Native libraries cppTango depends on libraries including omniORB4 and libzmq. Wheel availability, OS, architecture, and system libraries can prevent installation.

Note: requires-python >=3.9 does not guarantee that every Python version >=3.9 works with every PyTango release. Python 3.9 requires selecting an appropriate PyTango 10.0.x release, not the 10.3 series. Python 3.7-compatible type annotations in a device class do not make the complete framework Python 3.7-compatible. Successful dependency resolution also does not replace integration testing on the target device and TANGO deployment.

Official references: PyTango 10.0.0, PyTango 10.3.1, xlogger-py 0.3.1.

Device class

A device class remains an ordinary Python class.

from typing import List


class DeviceClass(object):
    def __init__(self) -> None:
        self._position = 0.0

    def add(self, value: float) -> float:
        self._position += value
        return self._position

    def move(
            self,
            position: float,
            speed: float = 1.0,
            wait: bool = True,
    ) -> bool:
        self._position = position
        return wait

    def get_samples(self) -> List[float]:
        return [1.0, 2.0, 3.0]

    @property
    def position(self) -> float:
        return self._position

    @position.setter
    def position(self, value: float) -> None:
        self._position = value

The class can still be instantiated and used directly without TANGO.

TANGO Device Server

A device-specific TANGO server class only binds the device class to AutoDispatchDevice.

from tango_frame import AutoDispatchDevice

from device.device_class import DeviceClass


class TangoDevice(AutoDispatchDevice):
    device_class = DeviceClass

The public API is converted automatically. For the example above:

add(value: float) -> float
    TANGO command: float -> float

move(position: float, speed: float, wait: bool) -> bool
    TANGO command: JSON string -> bool

get_samples() -> List[float]
    TANGO command: void -> homogeneous float array

position: float
    TANGO read/write attribute

A device-specific server can exclude methods that must not be executed remotely:

class TangoDevice(AutoDispatchDevice):
    device_class = DeviceClass
    excluded_commands = {"save"}

The actual server is started with the normal PyTango server runtime. The example uses -nodb only to run locally without a TANGO database.

Client

The corresponding client is defined by binding the same device class to AutoDispatchClient.

from tango_frame import AutoDispatchClient

from device.device_class import DeviceClass


class DeviceClient(AutoDispatchClient):
    device_class = DeviceClass

The client uses TANGO DeviceProxy internally, while the caller uses Python-style methods and properties.

device = DeviceClient(
    "tango://127.0.0.1:10000/test/tango/device#dbase=no"
)

print(device.position)
print(device.add(2.5))
device.position = 20.0

Device-specific client operations can be implemented normally. For example, a save(path) method should write on the client machine rather than on the Device Server machine:

from pathlib import Path


class DeviceClient(AutoDispatchClient):
    device_class = DeviceClass

    def save(self, path: str) -> str:
        data = self.get_data()
        Path(path).write_bytes(data)
        return path

The explicitly implemented client method takes precedence over automatic remote dispatch.

Type conversion

tango-frame prefers native TANGO values.

Python API TANGO representation
bool native boolean
int native integer
float native double
str native string
homogeneous List[T] native TANGO array/spectrum
no argument / no return void
multiple or heterogeneous arguments one JSON string input
unsupported complex return value JSON string

JSON is therefore a fallback for Python call structures that do not map directly to TANGO's command model; it is not the default transport format.

Documentation

Sphinx/MyST documentation is under docs/.

cd docs
./build.sh

Version

Current version: 0.1.4

See CHANGELOG.md.

Metadata

Release files for tango-frame 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tango-frame 0.1.5
File Size Uploaded Provenance Actions
tango_frame-0.1.5.tar.gz 17.9 kB With provenance Details for tango_frame-0.1.5.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for tango-frame 0.1.5
File Interpreter ABI Platform Actions
tango_frame-0.1.5-py3-none-any.whl Python 3 none any Details for tango_frame-0.1.5-py3-none-any.whl

Total release size: 35.6 kB

Release files / tango_frame-0.1.5.tar.gz

Download URL tango_frame-0.1.5.tar.gz
Size 17.9 kB
Tags Source
SHA-256 checksum
How to use checksums
0c4d3e202690c3656a08e2c601439b3ce1159b7e894c317b9525abadebc295d6
BLAKE2b-256 checksum
How to use checksums
932e86d29274a063d8110617a5488c212263a71192993f3ff78174f1b9582801
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Release files / tango_frame-0.1.5-py3-none-any.whl

Download URL tango_frame-0.1.5-py3-none-any.whl
Size 17.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4c89ed7583950101493417d6e767971ccb7ddca68d02e1e2da9c676140acbba4
BLAKE2b-256 checksum
How to use checksums
a1a9be60737a7470480ac4f113bc199d1550a74c2c13d93ece98288cf516f594
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

Security for tango-frame 0.1.5

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for tango_frame-0.1.5.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 24, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page