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
6 changes: 4 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
sudo: false
language: python
dist: xenial
python:
- "2.7"
- "3.5"
- "3.6"
- "3.7"
- "3.8"

install:
- pip install pipenv
- pipenv install --dev
- pipenv install --dev --skip-lock

script:
- pipenv run python -m pytest --cov-report term-missing --cov=pytac
- pipenv run flake8
# Run black if it has been installed (Python 3.6 and up).
- if pipenv run which black > /dev/null 2>&1 ; then pipenv run black --check pytac test; fi

after_success:
- coveralls
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ sphinx = "*"
sphinx-rtd-theme = "*"
pytest-lazy-fixture = "*"
testfixtures = "*"
black = {version = "==19.10b0", markers = "python_version>='3.6'" }

[packages]
numpy = "*"
Expand Down
2 changes: 2 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
:target: https://badge.fury.io/py/pytac
.. image:: https://img.shields.io/pypi/pyversions/pytac.svg
:target: https://badge.fury.io/py/pytac
.. image:: https://img.shields.io/badge/code%20style-black-000000.svg
:target: https://github.com/ambv/black


Python Toolkit for Accelerator Controls (Pytac) is a Python library for working
Expand Down
39 changes: 28 additions & 11 deletions pytac/__init__.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,38 @@
"""Pytac: Python Toolkit for Accelerator Controls."""
# PV types.
SP = 'setpoint'
RB = 'readback'
SP = "setpoint"
RB = "readback"
# Unit systems.
ENG = 'engineering'
PHYS = 'physics'
ENG = "engineering"
PHYS = "physics"
# Data Source types.
SIM = 'simulation'
LIVE = 'live'
SIM = "simulation"
LIVE = "live"
# Default argument flag.
DEFAULT = 'default'
DEFAULT = "default"


from . import (data_source, device, element, exceptions, lattice, load_csv,
units, utils) # noqa: E402
from . import ( # noqa: 402
data_source,
device,
element,
exceptions,
lattice,
load_csv,
units,
utils,
)

"""Error 402 is suppressed as we cannot import these modules at the top of the
file as the strings above must be set first or the imports will fail.
"""
__all__ = ["data_source", "device", "element", "exceptions", "lattice",
"load_csv", "units", "utils"]
__all__ = [
"data_source",
"device",
"element",
"exceptions",
"lattice",
"load_csv",
"units",
"utils",
]
13 changes: 7 additions & 6 deletions pytac/cothread_cs.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class CothreadControlSystem(ControlSystem):

**Methods:**
"""

def __init__(self, timeout=1.0):
self._timeout = timeout

Expand All @@ -35,7 +36,7 @@ def get_single(self, pv, throw=True):
try:
return caget(pv, timeout=self._timeout, throw=True)
except ca_nothing:
error_msg = 'Cannot connect to {}.'.format(pv)
error_msg = "Cannot connect to {}.".format(pv)
if throw:
raise ControlSystemException(error_msg)
else:
Expand All @@ -62,15 +63,15 @@ def get_multiple(self, pvs, throw=True):
failures = []
for result in results:
if isinstance(result, ca_nothing):
logging.warning('Cannot connect to {}.'.format(result.name))
logging.warning("Cannot connect to {}.".format(result.name))
if throw:
failures.append(result)
else:
return_values.append(None)
else:
return_values.append(result)
if throw and failures:
error_msg = '{} caget calls failed.'.format(len(failures))
error_msg = "{} caget calls failed.".format(len(failures))
raise ControlSystemException(error_msg)
return return_values

Expand All @@ -93,7 +94,7 @@ def set_single(self, pv, value, throw=True):
caput(pv, value, timeout=self._timeout, throw=True)
return True
except ca_nothing:
error_msg = 'Cannot connect to {}.'.format(pv)
error_msg = "Cannot connect to {}.".format(pv)
if throw:
raise ControlSystemException(error_msg)
else:
Expand Down Expand Up @@ -128,12 +129,12 @@ def set_multiple(self, pvs, values, throw=True):
if not stat.ok:
return_values.append(False)
failures.append(stat)
logging.warning('Cannot connect to {}.'.format(stat.name))
logging.warning("Cannot connect to {}.".format(stat.name))
else:
return_values.append(True)
if failures:
if throw:
error_msg = '{} caput calls failed.'.format(len(failures))
error_msg = "{} caput calls failed.".format(len(failures))
raise ControlSystemException(error_msg)
else:
return return_values
1 change: 1 addition & 0 deletions pytac/cs.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class ControlSystem(object):

**Methods:**
"""

def get_single(self, pv, throw):
"""Get the value of a given PV.

Expand Down
83 changes: 50 additions & 33 deletions pytac/data_source.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Module containing pytac data source classes."""
import pytac
from pytac.exceptions import (DataSourceException, FieldException,
HandleException)
from pytac.exceptions import DataSourceException, FieldException, HandleException


class DataSource(object):
Expand All @@ -17,6 +16,7 @@ class DataSource(object):

**Methods:**
"""

def get_fields(self):
"""Get all the fields represented by this data source.

Expand Down Expand Up @@ -75,6 +75,7 @@ class DataSourceManager(object):

**Methods:**
"""

def __init__(self):
self._data_sources = {}
self._uc = {}
Expand Down Expand Up @@ -125,8 +126,9 @@ def add_device(self, field, device, uc):
self._data_sources[pytac.LIVE].add_device(field, device)
self._uc[field] = uc
except KeyError:
raise DataSourceException("No device data source on manager {0}."
.format(self))
raise DataSourceException(
"No device data source on manager {0}.".format(self)
)

def get_device(self, field):
"""Get the device for the given field.
Expand All @@ -147,8 +149,9 @@ def get_device(self, field):
try:
return self._data_sources[pytac.LIVE].get_device(field)
except KeyError:
raise DataSourceException("No device data source on manager {0}."
.format(self))
raise DataSourceException(
"No device data source on manager {0}.".format(self)
)

def get_unitconv(self, field):
"""Get the unit conversion option for the specified field.
Expand All @@ -165,8 +168,10 @@ def get_unitconv(self, field):
try:
return self._uc[field]
except KeyError:
raise FieldException("No unit conversion option for field {0} on "
"manager {1}.".format(field, self))
raise FieldException(
"No unit conversion option for field {0} on "
"manager {1}.".format(field, self)
)

def set_unitconv(self, field, uc):
"""set the unit conversion option for the specified field.
Expand All @@ -177,8 +182,14 @@ def set_unitconv(self, field, uc):
"""
self._uc[field] = uc

def get_value(self, field, handle=pytac.RB, units=pytac.DEFAULT,
data_source=pytac.DEFAULT, throw=True):
def get_value(
self,
field,
handle=pytac.RB,
units=pytac.DEFAULT,
data_source=pytac.DEFAULT,
throw=True,
):
"""Get the value for a field.

Returns the value of a field on the manager. This value is uniquely
Expand Down Expand Up @@ -209,17 +220,25 @@ def get_value(self, field, handle=pytac.RB, units=pytac.DEFAULT,
try:
data_source = self._data_sources[data_source]
value = data_source.get_value(field, handle, throw)
return self._uc[field].convert(value, origin=data_source.units,
target=units)
return self._uc[field].convert(
value, origin=data_source.units, target=units
)
except KeyError:
raise DataSourceException("No data source type {0} on manager {1}."
.format(data_source, self))
raise DataSourceException(
"No data source type {0} on manager {1}.".format(data_source, self)
)
except FieldException:
raise FieldException("No field {0} on manager {1}.".format(field,
self))

def set_value(self, field, value, handle=pytac.SP, units=pytac.DEFAULT,
data_source=pytac.DEFAULT, throw=True):
raise FieldException("No field {0} on manager {1}.".format(field, self))

def set_value(
self,
field,
value,
handle=pytac.SP,
units=pytac.DEFAULT,
data_source=pytac.DEFAULT,
throw=True,
):
"""Set the value for a field.

This sets a value on the machine or the simulation. If handle,units or
Expand Down Expand Up @@ -248,18 +267,18 @@ def set_value(self, field, value, handle=pytac.SP, units=pytac.DEFAULT,
try:
data_source = self._data_sources[data_source]
except KeyError:
raise DataSourceException("No data source type {0} on manager {1}."
.format(data_source, self))
raise DataSourceException(
"No data source type {0} on manager {1}.".format(data_source, self)
)
try:
value = self._uc[field].convert(value, origin=units,
target=data_source.units)
value = self._uc[field].convert(
value, origin=units, target=data_source.units
)
data_source.set_value(field, value, throw)
except KeyError:
raise FieldException("No field {0} on manager {1}.".format(field,
self))
raise FieldException("No field {0} on manager {1}.".format(field, self))
except FieldException:
raise FieldException("No field {0} on manager {1}.".format(field,
self))
raise FieldException("No field {0} on manager {1}.".format(field, self))


class DeviceDataSource(DataSource):
Expand All @@ -275,6 +294,7 @@ class DeviceDataSource(DataSource):

**Methods:**
"""

def __init__(self):
self._devices = {}
self.units = pytac.ENG
Expand Down Expand Up @@ -303,8 +323,7 @@ def get_device(self, field):
try:
return self._devices[field]
except KeyError:
raise FieldException("No field {0} on data source {1}."
.format(field, self))
raise FieldException("No field {0} on data source {1}.".format(field, self))

def get_fields(self):
"""Get all the fields from the data_source.
Expand Down Expand Up @@ -333,8 +352,7 @@ def get_value(self, field, handle, throw=True):
try:
return self._devices[field].get_value(handle, throw)
except KeyError:
raise FieldException("No field {0} on data source {1}."
.format(field, self))
raise FieldException("No field {0} on data source {1}.".format(field, self))

def set_value(self, field, value, throw=True):
"""Set the value of a readback or setpoint PV for a field from the
Expand All @@ -352,5 +370,4 @@ def set_value(self, field, value, throw=True):
try:
self._devices[field].set_value(value, throw)
except KeyError:
raise FieldException("No field {0} on data source {1}."
.format(field, self))
raise FieldException("No field {0} on data source {1}.".format(field, self))
Loading