Skip to content

Commit 4069b59

Browse files
committed
Switch to tempfile + dbLoadRecords as a strategy
1 parent 8b868eb commit 4069b59

File tree

5 files changed

+45
-600
lines changed

5 files changed

+45
-600
lines changed

softioc/__init__.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
iocshRegisterCommon, registerRecordDeviceDriver, pdbbase
77

88
# Do this as early as possible, in case we happen to use cothread
9-
# as it's harmless if we don't
9+
# This will set the CATOOLS_LIBCA_PATH environment variable in case we use
10+
# cothread.catools. It works even if we don't have cothread installed
1011
import epicscorelibs.path.cothread # noqa
1112

1213
# This import will also pull in the extension, which is needed

softioc/builder.py

+2-15
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
import os
22
import numpy
3+
from .softioc import dbLoadDatabase
34

45
from epicsdbbuilder import *
5-
from epicsdbbuilder.recordset import recordset
66

77
InitialiseDbd()
88
LoadDbdFile(os.path.join(os.path.dirname(__file__), 'device.dbd'))
99

10-
from . import pythonSoftIoc, imports # noqa
10+
from . import pythonSoftIoc # noqa
1111
PythonDevice = pythonSoftIoc.PythonDevice()
1212

1313

14-
def dbLoadDatabase(database, path = None, substitutions = None):
15-
'''Loads a database file and applies any given substitutions.'''
16-
imports.dbLoadDatabase(database, path, substitutions)
17-
18-
1914
# ----------------------------------------------------------------------------
2015
# Wrappers for PythonDevice record constructors.
2116
#
@@ -185,14 +180,6 @@ def WaveformOut(name, *value, **fields):
185180

186181
_DatabaseWritten = False
187182

188-
def AddDatabaseLine(line, macros={}):
189-
'''Add a single line to the produced database, substituting $(k) for v for
190-
each entry in macros'''
191-
for k, v in macros.items():
192-
line = line.replace("$(%s)" % k, v)
193-
recordset.AddBodyLine(line)
194-
195-
196183
def LoadDatabase():
197184
'''This should be called after all the builder records have been created,
198185
but before calling iocInit(). The database is loaded into EPICS memory,

softioc/softioc.py

+29-15
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import os
22
import sys
33
from ctypes import *
4+
from tempfile import NamedTemporaryFile
45

56
from epicsdbbuilder.recordset import recordset
67

7-
from . import imports, device, builder
8+
from . import imports, device
89

910
__all__ = ['dbLoadDatabase', 'iocInit', 'interactive_ioc']
1011

@@ -240,35 +241,48 @@ def __call__(self):
240241
exit = Exiter()
241242
command_names.append('exit')
242243

243-
# For backwards compatibility
244-
dbLoadDatabase = builder.dbLoadDatabase
244+
def dbLoadDatabase(database, path = None, substitutions = None):
245+
'''Loads a database file and applies any given substitutions.'''
246+
imports.dbLoadDatabase(database, path, substitutions)
245247

246248

247-
def _add_records_from_file(dir, file, macros):
248-
# This is very naive, for instance macros are added to but never removed,
249-
# but it works well enough for devIocStats
250-
with open(os.path.join(dir, file)) as f:
249+
250+
def _add_records_from_file(dirname, file, substitutions):
251+
# This is very naive, it loads all includes before their parents which
252+
# possibly can put them out of order, but it works well enough for
253+
# devIocStats
254+
with open(os.path.join(dirname, file)) as f:
255+
lines, include_subs = [], ""
251256
for line in f.readlines():
252257
line = line.rstrip()
253258
if line.startswith('substitute'):
254-
# substitute "QUEUE=scanOnce, QUEUE_CAPS=SCANONCE
255-
for sub in line.split('"')[1].split(','):
256-
k, v = sub.split('=')
257-
macros[k.strip()] = v.strip()
259+
# substitute "QUEUE=scanOnce, QUEUE_CAPS=SCANONCE"
260+
# keep hold of the substitutions
261+
include_subs = line.split('"')[1]
258262
elif line.startswith('include'):
259263
# include "iocQueue.db"
260-
_add_records_from_file(dir, line.split('"')[1], macros)
264+
subs = substitutions
265+
if substitutions and include_subs:
266+
subs = substitutions + ", " + include_subs
267+
else:
268+
subs = substitutions + include_subs
269+
_add_records_from_file(dirname, line.split('"')[1], subs)
261270
else:
262271
# A record line
263-
builder.AddDatabaseLine(line, macros)
272+
lines.append(line)
273+
# Write a tempfile and load it
274+
with NamedTemporaryFile(suffix='.db', delete=False) as f:
275+
f.write(os.linesep.join(lines).encode())
276+
dbLoadDatabase(f.name, substitutions=substitutions)
277+
os.unlink(f.name)
264278

265279

266280
def devIocStats(ioc_name):
267281
'''This will load a template for the devIocStats library with the specified
268282
IOC name. This should be called before `iocInit`'''
269-
macros = dict(IOCNAME=ioc_name, TODFORMAT='%m/%d/%Y %H:%M:%S')
283+
substitutions = 'IOCNAME=' + ioc_name + ', TODFORMAT=%m/%d/%Y %H:%M:%S'
270284
iocstats_dir = os.path.join(os.path.dirname(__file__), 'iocStatsDb')
271-
_add_records_from_file(iocstats_dir, 'ioc.template', macros)
285+
_add_records_from_file(iocstats_dir, 'ioc.template', substitutions)
272286

273287

274288
def interactive_ioc(context = {}, call_exit = True):

0 commit comments

Comments
 (0)