diff --git a/setup.py b/setup.py index 34157bce..bb4a5c40 100644 --- a/setup.py +++ b/setup.py @@ -61,10 +61,6 @@ devIocStats_src, devIocStats_os, devIocStats_default ], dsos = [ - 'epicscorelibs.lib.qsrv', - 'epicscorelibs.lib.pvAccessIOC', - 'epicscorelibs.lib.pvAccess', - 'epicscorelibs.lib.pvData', 'epicscorelibs.lib.dbRecStd', 'epicscorelibs.lib.dbCore', 'epicscorelibs.lib.ca', @@ -95,6 +91,8 @@ def install_for_development(self): install_requires = [ # Dependency version declared in pyproject.toml epicscorelibs.version.abi_requires(), + "pvxslibs>=1.2.1a1", + "setuptools_dso>=2.4", "numpy", "epicsdbbuilder>=1.4" ], diff --git a/softioc/__init__.py b/softioc/__init__.py index 2fb60947..019d7a56 100644 --- a/softioc/__init__.py +++ b/softioc/__init__.py @@ -1,10 +1,6 @@ '''Python soft IOC module.''' import os -from epicscorelibs import path -from epicscorelibs.ioc import \ - iocshRegisterCommon, registerRecordDeviceDriver, pdbbase - # Do this as early as possible, in case we happen to use cothread # This will set the CATOOLS_LIBCA_PATH environment variable in case we use # cothread.catools. It works even if we don't have cothread installed @@ -12,17 +8,44 @@ # This import will also pull in the extension, which is needed # before we call iocshRegisterCommon -from .imports import dbLoadDatabase from ._version_git import __version__ +from .imports import dbLoadDatabase + +def load_dbd(): + import ctypes + from epicscorelibs import path + from epicscorelibs.ioc import \ + iocshRegisterCommon, registerRecordDeviceDriver, pdbbase + import pvxslibs.path + from setuptools_dso.runtime import find_dso + + dbd_paths = ':'.join([ + os.path.join(path.base_path, 'dbd'), + pvxslibs.path.dbd_path, + os.path.join(os.path.dirname(__file__), "iocStats", "devIocStats"), + ]) + dbds = [ + 'base.dbd', # must be first + 'devIocStats.dbd', + 'pvxsIoc.dbd', + ] + + # Need to do this before calling anything in device.py + iocshRegisterCommon() + for dbd in dbds: + dbLoadDatabase(dbd, dbd_paths, None) + + from ._extension import install_pv_logging + dbRecStd = ctypes.CDLL(find_dso('epicscorelibs.lib.dbRecStd'), ctypes.RTLD_GLOBAL) + pvxsIoc = ctypes.CDLL(find_dso('pvxslibs.lib.pvxsIoc'), ctypes.RTLD_GLOBAL) + + # must explicitly enable QSRV while "Feature Preview" + os.environ.setdefault('PVXS_QSRV_ENABLE', 'YES') -# Need to do this before calling anything in device.py -iocshRegisterCommon() -for dbd in ('base.dbd', 'PVAServerRegister.dbd', 'qsrv.dbd'): - dbLoadDatabase(dbd, os.path.join(path.base_path, 'dbd'), None) -iocStats = os.path.join(os.path.dirname(__file__), "iocStats", "devIocStats") -dbLoadDatabase('devIocStats.dbd', iocStats, None) + if registerRecordDeviceDriver(pdbbase): + raise RuntimeError('Error registering') -if registerRecordDeviceDriver(pdbbase): - raise RuntimeError('Error registering') +load_dbd() +del load_dbd __all__ = ['__version__'] diff --git a/softioc/softioc.py b/softioc/softioc.py index 884b72da..a8a5d53e 100644 --- a/softioc/softioc.py +++ b/softioc/softioc.py @@ -272,6 +272,41 @@ def call_f(*args): and any other value means yes.''', lib=imports.Com) +class IOCSh(object): + class Caller: + ''' + Wrapper around iocshCmd() to translate eg. + iocsh.dbpr("MY-DEVICE-PREFIX:AI", 2) + into + iocshCmd("dbpr MY-DEVICE-PREFIX:AI 2") + ''' + iocshCmd = imports.Com.iocshCmd + iocshCmd.argtypes = (auto_encode,) + iocshCmd.restype = c_int + def __init__(self, name): + self.name = name + def __call__(self, *args): + cmd = [self.name] + for arg in args: + # TODO escape quote chars once this would work. + # https://github.com/epics-base/epics-base/issues/362 + if isinstance(arg, str) and arg.find(' ')!=-1: + arg = f'"{arg}"' + else: + arg = str(arg) + cmd.append(arg) + cmd = ' '.join(cmd) + ret = self.iocshCmd(cmd) + if ret!=0: + raise RuntimeError(ret) + def __getattr__(self, name): + if name.startswith('__'): + return super().__getattr__(name) + else: + return self.Caller(name) +IOCSh.__doc__ = IOCSh.Caller.__doc__ +iocsh = IOCSh() +command_names.append('iocsh') # Hacked up exit object so that when soft IOC framework sends us an exit command # we actually exit.