update documentation

This commit is contained in:
Michael Davidsaver
2014-06-16 17:55:15 -04:00
parent 9b5b9687b4
commit ee2cb409c2
11 changed files with 121 additions and 33 deletions

8
README.md Normal file
View File

@ -0,0 +1,8 @@
pyDevSup
========
EPICS Device support in Python.
See [documentation](http://mdavidsaver.github.io/pyDevSup)
For file [releases](http://sourceforge.net/projects/epics/files/pyDevSup)

View File

@ -53,29 +53,28 @@ class _Record(object):
def scan(self, sync=False, reason=None, force=0):
"""Scan this record.
:param sync: scan in current thread (``True``), or queue (``False``).
:param sync: scan in current thread (``True``), or queue to a worker (``False``).
:param reason: Reason object passed to :meth:`process <DeviceSupport.process>` (sync=True only)
:param force: Record processing condtion (0=Passive, 1=Force, 2=I/O Intr)
:throws: ``RuntimeError`` when ``sync=True``, but ``force`` prevents scanning.
If ``sync`` is False then a
scan request is queued to run in another thread..
If ``sync`` is True then the record
is scannined immidately on the current thread.
If ``sync`` is False then a scan request is queued to run in another thread..
If ``sync`` is True then the record is scanned immediately on the current thread.
For ``reason`` argument must be used in conjunction with ``sync=True``
on records with Python device support. This provides a means
of providing extra contextual information to the record's
:meth:`process <DeviceSupport.process>` method.
``force`` is used to decide if the record will actuall be processed,
``force`` is used to decide if the record will actually be processed,
``force=0`` will only process records with SCAN=Passive.
``force=1`` will process any record if at all possible.
``force=2`` will only process records with Python device support and
SCAN=I/O Intr.
It is **never** safe to use ``sync=True`` while holding record locks,
including from within a *process* method.
.. important::
It is **never** safe to use ``sync=True`` while holding record locks,
including from within a *process* method.
"""
def asyncStart(self):
@ -154,7 +153,7 @@ class _Field(object):
def putval(self, val):
"""Update the field value
Must be an Int, Float or str. Strings will be truncated to 39 charactors.
Must be an Int, Float or str. Strings will be truncated to 39 characters.
"""
def getarray(self):
@ -179,11 +178,11 @@ class _Field(object):
"""Set the number of active elements in field's array.
Requires that the underlying field be an array.
Must be less than the maximum length of the field.
Must be greater than one and less than or equal to the maximum length of the field.
"""
def getAlarm(self):
"""Returns a tuple (severity, status) with the condtion of the linked field.
"""Returns a tuple (severity, status) with the condition of the linked field.
Only works for fields of type DBF_INLINK.
"""

View File

@ -23,7 +23,7 @@ def getRecord(name):
full record name.
The result is cached so the future calls will return the same instance.
This is the prefered way to get :class:`Record` instances.
This is the preferred way to get :class:`Record` instances.
>>> R = getRecord("my:record:name")
Record("my:record:name")
@ -38,7 +38,7 @@ def getRecord(name):
class IOScanListBlock(object):
"""A list of records which will be processed together.
This convienence class to handle the accounting to
This convenience class to handle the accounting to
maintain a list of records.
"""
def __init__(self):
@ -218,7 +218,7 @@ class Record(_dbapi._Record):
"""Lookup field in this record
:rtype: :class:`Field`
:throws: KeyError for non-existant fields.
:throws: KeyError for non-existent fields.
The returned object is cached so future calls will
return the same instance.
@ -248,6 +248,9 @@ class Record(_dbapi._Record):
Has not effect if the TSE field is not set to -2.
All inputs must be referenced to the posix epoch.
If a datetime is provided, it must use the local system
timezone.
"""
if hasattr(ts, 'timetuple'):
ts = time.mktime(ts.timetuple())
@ -296,7 +299,7 @@ class Field(_dbapi._Field):
"""Get timestamp of link target.
Only works for DBF_INLINK fields.
Returns the time in seconds since the posix epoch.
Returns the time in seconds since the POSIX epoch.
:rtype: float
"""

View File

@ -17,7 +17,7 @@ __all__ = [
'build'
]
# Reason code to cause a record to read a new value from a table paramter
# Reason code to cause a record to read a new value from a table parameter
_INTERNAL = object()
# action types
@ -40,7 +40,7 @@ def _add_action(self, act, fn):
class Parameter(object):
"""Define a parameter in a table.
When a sub-class of TableBase is instancianted, parameters become
When a sub-class of TableBase is instantiated, parameters become
py:class:`_ParamInstance` instances.
>>> class MyTable(TableBase):
@ -100,7 +100,7 @@ class Parameter(object):
class ParameterGroup(object):
"""A helper for defining actions on groups of parameters
When a sub-class of TableBase is instancianted, parameter groups become
When a sub-class of TableBase is instantiated, parameter groups become
py:class:`_ParamGroupInstance` instances.
>>> class MyTable(TableBase):
@ -116,7 +116,7 @@ class ParameterGroup(object):
self.params, self.name = params, name
def onproc(self, fn):
"""Decorator run a member function action whenever
a device support attached to any paramter in the group processes.
a device support attached to any parameter in the group processes.
>>> class MyTable(TableBase):
A, B = Parameter(), Parameter()
@ -133,7 +133,7 @@ class ParameterGroup(object):
"Decorator to run an action when any parameters has an invalid value"
return _add_action(self, (any, lambda p:not p.isvalid), fn)
def oncondition(self, fmap, freduce=all):
"""Decorator for a custom condtion.
"""Decorator for a custom condition.
The condition is specified in two parts, a map function, and a reduce function.
The map function is applied to each parameter in the group. Then a list
@ -265,7 +265,7 @@ class TableBase(object):
Sub-class this and populate with :py:class:`Parameter` and :py:class:`ParameterGroup`.
When a table is instanciated it must be given a unique name.
#When a table is instantiated it must be given a unique name.
>>> class MyTable(TableBase):
...
@ -282,7 +282,7 @@ class TableBase(object):
self._parameters = {}
# Find Parameters and ParameterGroup in the class dictionary
# and place approprate things in the instance dictionary
# and place appropriate things in the instance dictionary
rparams = {}
rgroups = {}
for k,v in self.__class__.__dict__.items():

View File

@ -16,12 +16,12 @@ devsup Package
.. module:: devsup.db
.. autofunction:: devsup.db.getRecord
.. autofunction:: getRecord
:class:`Record` Class
^^^^^^^^^^^^^^^^^^^^^
.. class:: devsup.db.Record
.. class:: Record
Allows access to a single record instance.
*Record* instances can be created for any record in
@ -65,7 +65,7 @@ devsup Package
:class:`Field` Class
^^^^^^^^^^^^^^^^^^^^
.. autoclass:: devsup.db.Field
.. autoclass:: Field
.. automethod:: name
@ -77,18 +77,22 @@ devsup Package
.. automethod:: getarray
.. automethod:: getarraylen
.. automethod:: putarraylen
.. automethod:: fieldinfo
.. automethod:: getTime
.. automethod:: getAlarm
.. autoclass:: devsup.db.IOScanListBlock
.. autoclass:: IOScanListBlock
:members:
:inherited-members:
:undoc-members:
.. autoclass:: devsup.db.IOScanListThread
.. autoclass:: IOScanListThread
:members: add, interrupt

View File

@ -62,8 +62,8 @@ The following should be added to individual EPICS Makefiles. ::
include $(TOP)/configure/RULES
include $(PYDEVSUP)/configure/RULES_PY
This will add or ammend several make variables. The ``USR_*FLAGS`` variables
may be extended with approprate flags for building python modules. The ``PY_VER``
This will add or amend several make variables. The ``USR_*FLAGS`` variables
may be extended with appropriate flags for building python modules. The ``PY_VER``
variable is defined with the Python version number found in install directories (eg "2.7").
The ``PY_LD_VER`` variable is defined with the python library version number (eg "3.2mu"),
which may be the same as ``PY_VER``.
@ -94,7 +94,7 @@ Additional .py files can be installed as follows. ::
Building extensions
-------------------
For convienance, additional Python extensions can be build by the EPICS
For convenience, additional Python extensions can be build by the EPICS
build system. In this example the extension name is "_myextname" and
the resulting library is expected to provide the an initialization function
named "init_myextname". ::

View File

@ -0,0 +1,60 @@
Getting Started
===============
Counter
-------
Consider a simple EPICS database with one record. Call it :download:`cntrec.db <../testApp/cntrec.db>`
.. literalinclude:: ../testApp/cntrec.db
This is creating a single record which will use the "Python Device" support code (aka this package).
It will attempt to scan (call the process method) one a second.
The *INP* field is parsed and the first work identifies the Python module which will provide
the logic behind this record (everything after the first word is passed to the module :py:func:`build` function.
Now create :download:`cntrec.db <../testApp/cntmod.py>` with the following.
.. literalinclude:: ../testApp/cntmod.py
This module is expected to provide a special callable :py:func:`build`.
We also provide a constructor and method :py:meth:`detach <DeviceSupport.detach>`
which don't do anything.
The :py:meth:`process <DeviceSupport.process>` method increments the *VAL* field of the attached :py:class:`Record <devsup.db.Record>`.
Start this IOC with. ::
$ ./bin/linux-x86_64/softIocPy2.7 -d cntrec.db
Starting iocInit
...
iocRun: All initialization complete
epics>dbl
test:count
epics>
Now in another terminal run.::
$ camonitor test:count
...
test:count 2014-06-16 16:48:22.891825 9
test:count 2014-06-16 16:48:23.891967 10
test:count 2014-06-16 16:48:24.892137 11
test:count 2014-06-16 16:48:25.892286 12
It may be necessary to run *export EPICS_CA_ADDR_LIST=localhost* first.
Additional examples and applications
------------------------------------
This module comes with several examples in *testApp* as well as three complete applications.
logApp
Observes a line based text file as new lines are appended.
Writes each line to a charactor array PV.
Special handling of caPutLog files.
pidMonApp
Monitors the PID file created by a UNIX daemon.
weatherApp
Retreives weather reports via the *pymetar* module.

View File

@ -15,6 +15,7 @@ Contents:
.. toctree::
:maxdepth: 4
gettingstarted
environment
devsup
interfaces

View File

@ -55,7 +55,7 @@ and the string "some other string".
of the methods which all Python device support instances must provide.
These methods will be called during the course of IOC processing.
Execptions raised by these methods are printed to the IOC console,
Exceptions raised by these methods are printed to the IOC console,
but will otherwise be ignored.
The module :mod:`devsup.interfaces` provides a Zope Interface
@ -76,7 +76,7 @@ and the string "some other string".
:param reason: ``None`` or an object provided when processing was requested.
This method is called whenever the associated record needs to be updated
in responce to a request. The source of this request is typically determined
in response to a request. The source of this request is typically determined
by the record's SCAN field.
The actions taken by this method will depend heavily on the application.
@ -120,7 +120,7 @@ and the string "some other string".
def allowScan(self, record):
return self.a_scan.add(record)
Which is most cases can be abbriviated to ::
Which in most cases can be abbriviated to ::
class MySup(object):
def __init__(self):

8
testApp/cntmod.py Normal file
View File

@ -0,0 +1,8 @@
class MySupport:
def __init__(self, rec, link):
pass
def detach(self, rec):
pass
def process(self, rec, reason):
rec.VAL = rec.VAL + 1
build = MySupport

5
testApp/cntrec.db Normal file
View File

@ -0,0 +1,5 @@
record(longin, "test:count") {
field(DTYP, "Python Device")
field(INP , "@cntmod")
field(SCAN, "1 second")
}