.. py:module:: epicsdbbuilder Database Builder API ==================== Initialisation -------------- .. function:: InitialiseDbd(epics_base, host_arch=None) This must be called once before calling any other functions. `epics_base` must be an absolute path to the directory containing EPICS base, in particular this directory must contain both ``dbd/base.dbd`` and ``lib/``. This function will load the base EPICS dbd file. The host architecture can normally be computed automatically, but if this computation fails this can be specified by setting `host_arch`. .. function:: LoadDbdFile(dbdfile, on_use=None) This can be called before creating records to load extra databases. If `on_use` is not ``None`` it must be a callable taking one argument, and it will be called for each record that is created using records defined by this dbd. Record Output ------------- .. function:: WriteRecords(filename, header=None) This should be called after creating all records. The generated records will be written out to the file `filename`. If `header` is left unspecified then a standard disclaimer header will be generated::: # This file was automatically generated on Fri 27 Feb 2015 15:31:14 GMT. # # *** Please do not edit this file: edit the source file instead. *** Note that the leading ``#`` comments are added to any header that is passed .. function:: Disclaimer(source=None, normalise_path=True) This function generates the disclaimer above. If a source file name is passed then it is included in the disclaimer. Unless `normalise_path` is set to ``False`` the `source` argument will normalised by calling ``os.path.abspath(source)``; this allows the caller to simply pass ``__file__`` as the source argument with the desired result. .. function:: CountRecords() Returns the number of records that have currently been created. .. function:: ResetRecords() Resets the list of records to be written. This can be used to write multiple databases. Building Databases ------------------ .. data:: records This instance has a method for each record type, of the form: .. method:: records.type(name, **kargs) .. x** (vim fix) Here `name` will be used to construct the record name according to the record naming rules currently in force and any field can be given a value by assigning it in `kargs`. See :class:`epicsdbbuilder.recordbase.Record` for more details of these methods. Note that fields can be assigned either in the constructor or subsequently, and fields can be used as links:: r = records.ai('NAME', INP = '@input') r.DESC = 'This is an ai record' r.FLNK = records.calc('NP1', CALC = 'A+1', INP = r.VAL) .. class:: Parameter(name, description='', default=None) When using :func:`TemplateRecordNames` this can be used to create template parameters with the given `name`. If `description` is given then this will be printed in the header. If a `default` string is given it will be used as the parameter default value, otherwise the parameter will be created with no default value. .. function:: ImportRecord(name) This generates a record reference without adding an entry into the generated database. Use this when linking to records outside of the database. .. function:: LookupRecord(full_name) Returns a reference to a record which has already been created. Record Naming ------------- Record naming works as follows. Every time a record is created with a call the appropriate method of :data:`records` the name argument passed to that method is passed through the currently configured :func:`RecordName` method. If none of the functions named here are called then the default naming convention is applied: in this case record names are used unmodified. There is a simple "high level" API layered over a slightly more general interface. High Level API ~~~~~~~~~~~~~~ Use one of the following functions for normal configuration: .. function:: SetSimpleRecordNames(prefix='', separator=':') In this case the given `prefix` and `separator` are added in front of any record name. If no arguments are given then the effect is the same as the default naming convention which is to use names unchanged. .. function:: SetTemplateRecordNames(prefix=None, separator=':') This is useful for generating template databases. If `prefix` is not specified then a :class:`Parameter` instance with name ``DEVICE`` is created and prefixed together with the `separator` to each record name. .. function:: RecordName(name) Applies the current record name conversion to compute a full record name. .. function:: SetPrefix(prefix) The currently configured prefix can be changed. This function will only work if a :class:`SimpleRecordNames` or similar naming mechanism is installed. .. function:: PushPrefix(prefix) PopPrefix() These two functions manage a stack of record name prefixes, which will be separated by `separator` before being appended to the record name. .. function:: SetSeparator(separator) This function can be used to change the prefix separator. General Interface ~~~~~~~~~~~~~~~~~ More generally any callable object can be used for record name generation. .. function:: SetRecordNames(names) This sets up a record naming convention. The argument passed will be called each time a new record is created. This function should take a name as argument and return the full name to be written to the generated database. The default naming mechanism uses the record name unmodified. When this method is called the previously establishing record naming convention is returned. .. class:: SimpleRecordNames(prefix='', separator=':', check=True) This implements a minimal naming convention. If no `prefix` is specified record names are generated unchanged, otherwise the given `prefix` and `separator` are contatenated to the front of the passed argument. If `check` is set the the resulting name is checked for length. Supports the following methods. .. method:: __call__(name) Returns `prefix` + `separator` + `name`. If `prefix` is currently ``None`` then an error will be generated. .. method:: SetPrefix(prefix) Allows the prefix to be modified. This can be called via the global :func:`SetPrefix` method. .. method:: PushPrefix(prefix) PopPrefix() These two functions manage a stack of record name prefixes, which will be separated by `separator` before being appended to the record name. Can be called via the corresponding global functions. .. class:: TemplateRecordNames(prefix=None, separator=':') Subclasses :class:`SimpleRecordNames` to automatically add a ``$(DEVICE)`` template to the prefix stack. .. function:: GetRecordNames() Returns the current record naming convention. Helper Functions and Classes ---------------------------- .. function:: CA(record) CP(record) CPP(record) NP(record) PP(record) MS(record) MSS(record) MSI(record) NMS(record) Used for record links to add the appropriate processing annotation to the link. Example (Python source):: other_record = records.ai('other') my_record.INP = PP(MS(other_record)) Example (Generated DB):: field(INP, "other PP MS") .. class:: ConstArray(iterator) Used for **Constant Link Values** available since EPICS 3.16.1. Constant Link Values is an EPICS feature which allows passing an list of strings or a list of numbers as a constant into a field which contains a DB link (e.g. `INP`). See EPICS Release Notes (Section "Constant Link Values") for more details and supported use. ConstArray will accept any iterable (e.g. a list) which can generate a non-empty list of values of the same type. Allowed types are: * strings and parameters (i.e. :py:class:`epicsdbbuilder.Parameter`) * numbers (integers, floating-point, :py:class:`decimal.Decimal`, and booleans. Booleans will convert to `0` (`False`) or `1` (`True`) automatically. Known limitations: * No field type or record type check. ConstArray can be assigned to any field despite the field or the record type does not support Constant Link Values. Use it with link fields (e.g. `INP`) of record types `stringin`, `stringout`, `lso`, `lsi`, `printf`, `waveform`, `subArray`, and `aai`. Any other use is undefined and a warning may or may not appear while loading the DB (e.g. assigning `["1.23"]` to INP of the record type `ai` will print a warning while assigning `[1.23]` to INP of the record type `ai` will treat it as a CA link without any warning on EPICS 7.0.3.1). Always refer to EPICS Release Notes (section "Constant Link Values"). Example (Python source):: r = records.lsi('r', INP=ConstArray(['Plain String not DBLINK'])) Example (generated DB):: field(INP, ["Plain String not DBLINK"]) .. function:: create_fanout(name, *records, **args) Creates one or more fanout records (as necessary) to fan processing out to all records in `records`. The first fanout record is named `name`, for others a sequence number is appended to `name`. .. function:: create_dfanout(name, *records, **args) Creates one or more dfanout records as necessary to fan a data output to a the list of records in `records`. Record Class ------------ .. py:currentmodule:: epicsdbbuilder.recordbase .. class:: Record A subclass of this class is created for each record type and used to populate :data:`epicsdbbuilder.records`: for example, ``records.ai`` is a subclass of :class:`Record` used to generate ``ai`` records. .. method:: __init__(name, **kargs) .. x** (vim fix) The argument `name` is used to construct the record name. Any field appropriate for this record type can be named in `kargs`, for example:: records.ai('NAME', VAL = 42, PINI = 'YES') .. method:: add_alias(alias) This method causes an EPICS ``alias`` statement to be added to the database giving `alias` as an alternative name for this record. The `alias` argument is used unchanged. .. method:: add_metadata(metadata) This adds metadata entries to the created record. Metadata entries are lines beginning with ``#%`` placed in the db file immediately above the record definition, and can be used by processing tools.