Skip to content

Commit

Permalink
Rename the library (#215)
Browse files Browse the repository at this point in the history
* Semi-automatic rebranding

* Extend the test memory limit

* Update the SonarCloud project key

* Make generated code independent of PyCyphal

* Fix 3.7 compatibility
  • Loading branch information
pavel-kirienko authored Apr 10, 2022
1 parent e0a46fc commit 1c45393
Show file tree
Hide file tree
Showing 230 changed files with 3,650 additions and 3,770 deletions.
8 changes: 4 additions & 4 deletions .appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ for:
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
install:
- 'systeminfo'
# Configure Npcap. This is for testing the packet capture functionality in the UAVCAN/UDP transport.
# Configure Npcap. This is for testing the packet capture functionality in the Cyphal/UDP transport.
- '.test_deps\npcap-0.96.exe /loopback_support=yes /winpcap_mode=yes /S'
# Installation of the NDIS filter driver from Npcap may have disrupted network connectivity, as explained in
# https://github.com/nmap/npcap/issues/215. Also, a restart appears to be necessary to enable the NPF service.
Expand All @@ -72,7 +72,7 @@ for:
APPVEYOR_BUILD_WORKER_IMAGE: Ubuntu2004
install:
- 'export extras_pkg="linux-*-extra-$(uname -r)"'
# Graphviz is needed for the docs, ncat is needed for testing the UAVCAN/serial transport.
# Graphviz is needed for the docs, ncat is needed for testing the Cyphal/serial transport.
- 'sudo apt-get install -y $extras_pkg graphviz ncat'
- 'git submodule update --init --recursive'
- 'python -m pip install --upgrade pip setuptools nox'
Expand Down Expand Up @@ -100,10 +100,10 @@ for:
# Configure git credentials.
- echo "https://${GIT_TOKEN}:[email protected]" > ~/.git-credentials
- git config --global credential.helper store
- git config --global user.email "hedgehoginthefog@uavcan.org"
- git config --global user.email "hedgehoginthefog@opencyphal.org"
- git config --global user.name "Release Automation"
# Tag and publish this release. Push the tag after the release is out in case it could not be published.
- 'git tag "$(cat pyuavcan/VERSION)"'
- 'git tag "$(cat pycyphal/VERSION)"'
- 'python setup.py sdist bdist_wheel'
- 'python -m twine upload dist/*'
- 'git push --tags'
Expand Down
3 changes: 3 additions & 0 deletions .idea/dictionaries/pavel.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions .test_deps/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Test dependencies

This directory contains external dependencies necessary for running the intergration test suite
This directory contains external dependencies necessary for running the integration test suite
that cannot be sourced from package managers.
To see how these components are used, refer to the test scripts.

Expand All @@ -11,7 +11,7 @@ Please keep this document in sync with the contents of this directory.
### Portable Ncat

Ncat is needed for brokering TCP connections that emulate serial port connections.
This is needed for testing the UAVCAN/serial transport without having to access a physical serial port
This is needed for testing the Cyphal/serial transport without having to access a physical serial port
(which would be difficult to set up on a CI server).

The binary comes with the following statement by its developers:
Expand All @@ -33,7 +33,7 @@ The binary comes with the following statement by its developers:

### Npcap installer

Npcap is needed for testing the network sniffer of the UAVCAN/UDP transport implementation on Windows.
Npcap is needed for testing the network sniffer of the Cyphal/UDP transport implementation on Windows.

Npcap is distributed under the terms of Nmap Public Source License: https://nmap.org/npsl/.

Expand Down
5 changes: 5 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
Changelog
=========

v1.5
----

- The library renamed from PyUAVCAN to PyCyphal and republished under the new name.

v1.4
----

Expand Down
16 changes: 8 additions & 8 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Source directory layout
Most of the package configuration can be gathered by reading ``setup.cfg``.
When adding new tools and such, try storing all their configuration there to keep everything in one place.

All shippable entities are located exclusively inside the directory ``pyuavcan/``.
All shippable entities are located exclusively inside the directory ``pycyphal/``.
The entirety of the directory is packaged for distribution.

The submodule ``demo/public_regulated_data_types/`` is needed only for demo, testing, and documentation building.
Expand Down Expand Up @@ -77,8 +77,8 @@ This helps reduce scope contamination and avoid naming conflicts.

::

from pyuavcan.transport import Transport # Avoid this if you can.
import pyuavcan.transport # Prefer this.
from pycyphal.transport import Transport # Avoid this if you can.
import pycyphal.transport # Prefer this.


Semantic and behavioral conventions
Expand All @@ -103,9 +103,9 @@ API functions and methods that contain the following parameters should adhere to
+======================================+=======================+=======================================================+
|``pydsdl.*Type`` |``model`` |PyDSDL type model (descriptor). |
+--------------------------------------+-----------------------+-------------------------------------------------------+
|``pyuavcan.dsdl.*Object`` |``obj`` |Instance of a generated class implementing DSDL type. |
|``pycyphal.dsdl.*Object`` |``obj`` |Instance of a generated class implementing DSDL type. |
+--------------------------------------+-----------------------+-------------------------------------------------------+
|``typing.Type[pyuavcan.dsdl.*Object]``|``dtype`` |Generated class implementing a DSDL type. |
|``typing.Type[pycyphal.dsdl.*Object]``|``dtype`` |Generated class implementing a DSDL type. |
+--------------------------------------+-----------------------+-------------------------------------------------------+
|``float`` |``monotonic_deadline`` |Abort operation if not completed **by** this time. |
| | |Time system is ``AbstractEventLoop.time()``. |
Expand Down Expand Up @@ -209,7 +209,7 @@ After the packages are generated, the output is cached on disk to permit fast re
The cache can be invalidated manually by running ``nox -s clean``.

On GNU/Linux, the amount of memory available for the test process is artificially limited to a few gibibytes
to catch possible memory hogs (like https://github.com/UAVCAN/pydsdl/issues/23 ).
to catch possible memory hogs (like https://github.com/OpenCyphal/pydsdl/issues/23 ).
See ``conftest.py`` for details.


Expand All @@ -228,14 +228,14 @@ When the CI/CD pipelines pass, you are all set.
Releasing
---------

PyUAVCAN is versioned by following `Semantic Versioning <https://semver.org>`_.
PyCyphal is versioned by following `Semantic Versioning <https://semver.org>`_.

Please update ``/CHANGELOG.rst`` whenever you introduce externally visible changes.
Changes that only affect the internal structure of the library (like test rigging, internal refactorings, etc.)
should not be mentioned in the changelog.

CI/CD automation uploads a new release to PyPI and pushes a new tag upstream on every push to ``master``.
It is therefore necessary to ensure that the library version (see ``pyuavcan/VERSION``) is bumped whenever
It is therefore necessary to ensure that the library version (see ``pycyphal/VERSION``) is bumped whenever
a new commit is merged into ``master``;
otherwise, the automation will fail with an explicit tag conflict error instead of deploying the release.

Expand Down
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
The MIT License (MIT)

Copyright (c) 2019 UAVCAN Consortium
Copyright (c) 2019 OpenCyphal

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
Expand Down
39 changes: 35 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,37 @@
Full-featured UAVCAN stack in Python
Full-featured Cyphal stack in Python
====================================

This library has been renamed into PyCyphal.
Please migrate your software to use PyCyphal instead of PyUAVCAN.
There have been no API changes aside from the renaming.
[![Build status](https://ci.appveyor.com/api/projects/status/2vv83afj3dxqibi5/branch/master?svg=true)](https://ci.appveyor.com/project/Zubax/pycyphal/branch/master)
[![RTFD](https://readthedocs.org/projects/pycyphal/badge/)](https://pycyphal.readthedocs.io/)
[![Coverage Status](https://coveralls.io/repos/github/OpenCyphal/pycyphal/badge.svg)](https://coveralls.io/github/OpenCyphal/pycyphal)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=PyCyphal&metric=alert_status)](https://sonarcloud.io/dashboard?id=PyCyphal)
[![Reliability Rating](https://sonarcloud.io/api/project_badges/measure?project=PyCyphal&metric=reliability_rating)](https://sonarcloud.io/dashboard?id=PyCyphal)
[![Lines of Code](https://sonarcloud.io/api/project_badges/measure?project=PyCyphal&metric=ncloc)](https://sonarcloud.io/dashboard?id=PyCyphal)
[![PyPI - Version](https://img.shields.io/pypi/v/pycyphal.svg)](https://pypi.org/project/pycyphal/)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
[![Forum](https://img.shields.io/discourse/https/forum.opencyphal.org/users.svg)](https://forum.opencyphal.org)

PyCyphal is a full-featured implementation of the Cyphal protocol stack intended for non-embedded,
user-facing applications such as GUI software, diagnostic tools, automation scripts, prototypes, and various R&D cases.

PyCyphal aims to support all features and transport layers of Cyphal,
be portable across all major platforms supporting Python,
and be extensible to permit low-effort experimentation and testing of new protocol capabilities.

It is designed to support **GNU/Linux**, **MS Windows**, and **macOS** as first-class target platforms.
However, the library does not rely on any platform-specific capabilities,
so it should be usable with other systems as well.

[Cyphal](https://opencyphal.org) is an open technology for real-time intravehicular distributed computing
and communication based on modern networking standards (Ethernet, CAN FD, etc.).

<p align="center">
<a href="https://pycyphal.readthedocs.io/"><img src="/docs/static/arch-non-redundant.svg" width="400px"></a>
</p>

**READ THE DOCS: [pycyphal.readthedocs.io](https://pycyphal.readthedocs.io/)**

**Ask questions: [forum.opencyphal.org](https://forum.opencyphal.org/)**

*See also: [**Yakut**](https://github.com/OpenCyphal/yakut) -- a CLI tool for diagnostics and management of
Cyphal networks built on top of PyCyphal.*
2 changes: 1 addition & 1 deletion demo/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
PyUAVCAN demo application
PyCyphal demo application
=========================

This directory contains the demo application.
Expand Down
22 changes: 11 additions & 11 deletions demo/demo_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import asyncio
import logging
import importlib
import pyuavcan
import pycyphal

# Production applications are recommended to compile their DSDL namespaces as part of the build process. The enclosed
# file "setup.py" provides an example of how to do that. The output path we specify here shall match that of "setup.py".
Expand All @@ -20,11 +20,11 @@

try:
import sirius_cyber_corp # This is our vendor-specific root namespace. Custom data types.
import pyuavcan.application # This module requires the root namespace "uavcan" to be transcompiled.
import pycyphal.application # This module requires the root namespace "uavcan" to be transcompiled.
except (ImportError, AttributeError): # Redistributable applications typically don't need this section.
logging.warning("Transcompiling DSDL, this may take a while")
src_dir = pathlib.Path(__file__).resolve().parent
pyuavcan.dsdl.compile_all(
pycyphal.dsdl.compile_all(
[
src_dir / "custom_data_types/sirius_cyber_corp",
src_dir / "public_regulated_data_types/uavcan/",
Expand All @@ -33,7 +33,7 @@
)
importlib.invalidate_caches() # Python runtime requires this.
import sirius_cyber_corp
import pyuavcan.application
import pycyphal.application

# Import other namespaces we're planning to use. Nested namespaces are not auto-imported, so in order to reach,
# say, "uavcan.node.Heartbeat", you have to "import uavcan.node".
Expand All @@ -54,13 +54,13 @@ class DemoApp:
def __init__(self) -> None:
node_info = uavcan.node.GetInfo_1.Response(
software_version=uavcan.node.Version_1(major=1, minor=0),
name="org.uavcan.pyuavcan.demo.demo_app",
name="org.opencyphal.pycyphal.demo.demo_app",
)
# The Node class is basically the central part of the library -- it is the bridge between the application and
# the UAVCAN network. Also, it implements certain standard application-layer functions, such as publishing
# heartbeats and port introspection messages, responding to GetInfo, serving the register API, etc.
# The register file stores the configuration parameters of our node (you can inspect it using SQLite Browser).
self._node = pyuavcan.application.make_node(node_info, DemoApp.REGISTER_FILE)
self._node = pycyphal.application.make_node(node_info, DemoApp.REGISTER_FILE)

# Published heartbeat fields can be configured as follows.
self._node.heartbeat_publisher.mode = uavcan.node.Mode_1.OPERATIONAL # type: ignore
Expand All @@ -84,7 +84,7 @@ def __init__(self) -> None:
try:
srv_least_sq = self._node.get_server(sirius_cyber_corp.PerformLinearLeastSquaresFit_1, "least_squares")
srv_least_sq.serve_in_background(self._serve_linear_least_squares)
except pyuavcan.application.register.MissingRegisterError:
except pycyphal.application.register.MissingRegisterError:
logging.info("The least squares service is disabled by configuration")

# Create another RPC-server using a standard service type for which a fixed service-ID is defined.
Expand All @@ -97,13 +97,13 @@ def __init__(self) -> None:
@staticmethod
async def _serve_linear_least_squares(
request: sirius_cyber_corp.PerformLinearLeastSquaresFit_1.Request,
metadata: pyuavcan.presentation.ServiceRequestMetadata,
metadata: pycyphal.presentation.ServiceRequestMetadata,
) -> sirius_cyber_corp.PerformLinearLeastSquaresFit_1.Response:
logging.info("Least squares request %s from node %d", request, metadata.client_node_id)
sum_x = sum(map(lambda p: p.x, request.points)) # type: ignore
sum_y = sum(map(lambda p: p.y, request.points)) # type: ignore
a = sum_x * sum_y - len(request.points) * sum(map(lambda p: p.x * p.y, request.points)) # type: ignore
b = sum_x * sum_x - len(request.points) * sum(map(lambda p: p.x ** 2, request.points)) # type: ignore
b = sum_x * sum_x - len(request.points) * sum(map(lambda p: p.x**2, request.points)) # type: ignore
try:
slope = a / b
y_intercept = (sum_y - slope * sum_x) / len(request.points)
Expand All @@ -115,7 +115,7 @@ async def _serve_linear_least_squares(
@staticmethod
async def _serve_execute_command(
request: uavcan.node.ExecuteCommand_1.Request,
metadata: pyuavcan.presentation.ServiceRequestMetadata,
metadata: pycyphal.presentation.ServiceRequestMetadata,
) -> uavcan.node.ExecuteCommand_1.Response:
logging.info("Execute command request %s from node %d", request, metadata.client_node_id)
if request.command == uavcan.node.ExecuteCommand_1.Request.COMMAND_FACTORY_RESET:
Expand All @@ -134,7 +134,7 @@ async def run(self) -> None:
temperature_setpoint = 0.0
temperature_error = 0.0

async def on_setpoint(msg: uavcan.si.unit.temperature.Scalar_1, _: pyuavcan.transport.TransferFrom) -> None:
async def on_setpoint(msg: uavcan.si.unit.temperature.Scalar_1, _: pycyphal.transport.TransferFrom) -> None:
nonlocal temperature_setpoint
temperature_setpoint = msg.kelvin

Expand Down
6 changes: 3 additions & 3 deletions demo/launch.orc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
# Shared environment variables for all nodes/processes (can be overridden or selectively removed in local scopes).
YAKUT_COMPILE_OUTPUT: .yakut_compiled
YAKUT_PATH: .yakut_compiled
# Here we use Yakut for compiling DSDL. Normally one should use Nunavut though: https://github.com/UAVCAN/nunavut
# Here we use Yakut for compiling DSDL. Normally one should use Nunavut though: https://github.com/OpenCyphal/nunavut
PYTHONPATH: .yakut_compiled

# Shared registers for all nodes/processes (can be overridden or selectively removed in local scopes).
# See the docs for pyuavcan.application.make_node() to see which registers can be used here.
uavcan:
# Use UAVCAN/UDP:
# Use Cyphal/UDP:
udp.iface: 127.9.0.0
# If you have Ncat or some other TCP broker, you can use UAVCAN/serial tunneled over TCP (in a heterogeneous
# If you have Ncat or some other TCP broker, you can use Cyphal/serial tunneled over TCP (in a heterogeneous
# redundant configuration with UDP or standalone). Ncat launch example: ncat --broker --listen --source-port 50905
serial.iface: "" # socket://127.0.0.1:50905
# It is recommended to explicitly assign unused transports to ensure that previously stored transport
Expand Down
12 changes: 6 additions & 6 deletions demo/plant.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@
import uavcan.si.unit.voltage
import uavcan.si.sample.temperature
import uavcan.time
import pyuavcan
from pyuavcan.application.heartbeat_publisher import Health
from pyuavcan.application import make_node, NodeInfo, register
import pycyphal
from pycyphal.application.heartbeat_publisher import Health
from pycyphal.application import make_node, NodeInfo, register


UPDATE_PERIOD = 0.5
Expand All @@ -21,7 +21,7 @@
saturation = False


async def handle_command(msg: uavcan.si.unit.voltage.Scalar_1, _metadata: pyuavcan.transport.TransferFrom) -> None:
async def handle_command(msg: uavcan.si.unit.voltage.Scalar_1, _metadata: pycyphal.transport.TransferFrom) -> None:
global heater_voltage, saturation
if msg.volt < 0.0:
heater_voltage = 0.0
Expand All @@ -35,7 +35,7 @@ async def handle_command(msg: uavcan.si.unit.voltage.Scalar_1, _metadata: pyuavc


async def main() -> None:
with make_node(NodeInfo(name="org.uavcan.pyuavcan.demo.plant"), "plant.db") as node:
with make_node(NodeInfo(name="org.opencyphal.pycyphal.demo.plant"), "plant.db") as node:
# Expose internal states for diagnostics.
node.registry["status.saturation"] = lambda: saturation # The register type will be deduced as "bit[1]".

Expand All @@ -46,7 +46,7 @@ async def main() -> None:

# Set up the ports.
pub_meas = node.make_publisher(uavcan.si.sample.temperature.Scalar_1, "temperature")
pub_meas.priority = pyuavcan.transport.Priority.HIGH
pub_meas.priority = pycyphal.transport.Priority.HIGH
sub_volt = node.make_subscriber(uavcan.si.unit.voltage.Scalar_1, "voltage")
sub_volt.receive_in_background(handle_command)

Expand Down
2 changes: 1 addition & 1 deletion demo/requirements.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
pyuavcan[transport-can-pythoncan,transport-serial,transport-udp]
pycyphal[transport-can-pythoncan,transport-serial,transport-udp]
6 changes: 3 additions & 3 deletions demo/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
# noinspection PyUnresolvedReferences
class BuildPy(distutils.command.build_py.build_py):
def run(self):
import pyuavcan
import pycyphal

pyuavcan.dsdl.compile_all(
pycyphal.dsdl.compile_all(
[
"public_regulated_data_types/uavcan", # All UAVCAN applications need the standard namespace, always.
"public_regulated_data_types/uavcan", # All Cyphal applications need the standard namespace, always.
"custom_data_types/sirius_cyber_corp",
# "public_regulated_data_types/reg", # Many applications also need the non-standard regulated DSDL.
],
Expand Down
Loading

0 comments on commit 1c45393

Please sign in to comment.