Source code for fastcs.transports.epics.util

import re

from fastcs.controllers import ControllerAPI
from fastcs.util import snake_to_pascal

EPICS_MAX_NAME_LENGTH = 60
"""Maximum length of an EPICS PV name, enforced by both CA and PVA transports."""


[docs] def pv_prefix_from_path(path: list[str]) -> str: """Derive an EPICS PV prefix from a controller path. The first segment (the controller id) is used verbatim; later segments are converted snake_case → PascalCase. Joined with ':'. """ if not path: raise ValueError("Cannot derive a PV prefix from an empty path") return ":".join([path[0]] + [snake_to_pascal(node) for node in path[1:]])
[docs] def validate_epics_pv_id( controller_api: ControllerAPI, *, transport_label: str, id_re: re.Pattern[str], ) -> None: """Reject controller ids that wouldn't be safe in an EPICS PV name. Rejects ids with characters not matched by ``id_re`` and rejects setups where the longest derivable PV prefix already exceeds the ``EPICS_MAX_NAME_LENGTH`` PV name limit. ``transport_label`` is the transport-specific tag (e.g. ``"EPICS CA id"``) that appears in the illegal-characters error message. """ name = controller_api.path[0] if not id_re.fullmatch(name): raise ValueError( f"Controller id {name!r} is not a valid {transport_label}; " "only alphanumerics, '-' and '_' are allowed" ) longest_prefix = max( len(pv_prefix_from_path(api.path)) for api in controller_api.walk_api() ) if longest_prefix > EPICS_MAX_NAME_LENGTH: raise ValueError( f"Controller id {name!r} produces a PV prefix of " f"{longest_prefix} characters, which exceeds the EPICS " f"{EPICS_MAX_NAME_LENGTH}-character PV name limit" )