Convert formatting automatically to f-strings
Automatically convert formatting with the following call: flynt -ll 2000 -v frappy* Result: 303/381 auto-converted. Failing conversions will be looked at manually in a follow-up commit. Change-Id: Icd996b27221202faccc15af78e0380cf52ee37f2 Reviewed-on: https://forge.frm2.tum.de/review/c/secop/frappy/+/30900 Tested-by: Jenkins Automated Tests <pedersen+jenkins@frm2.tum.de> Reviewed-by: Georg Brandl <g.brandl@fz-juelich.de> Reviewed-by: Alexander Zaft <a.zaft@fz-juelich.de>
This commit is contained in:
parent
a9d479ba0a
commit
6f95c0d825
@ -112,7 +112,7 @@ class CacheItem(tuple):
|
||||
try:
|
||||
value = datatype.import_value(value)
|
||||
except (KeyError, ValueError, AttributeError):
|
||||
readerror = ValueError('can not import %r as %r' % (value, datatype))
|
||||
readerror = ValueError(f'can not import {value!r} as {datatype!r}')
|
||||
value = None
|
||||
obj = tuple.__new__(cls, (value, timestamp, readerror))
|
||||
try:
|
||||
@ -151,7 +151,7 @@ class CacheItem(tuple):
|
||||
args += (self.timestamp,)
|
||||
if self.readerror:
|
||||
args += (self.readerror,)
|
||||
return 'CacheItem%s' % repr(args)
|
||||
return f'CacheItem{repr(args)}'
|
||||
|
||||
|
||||
class ProxyClient:
|
||||
@ -216,7 +216,7 @@ class ProxyClient:
|
||||
elif cbname == 'nodeStateChange':
|
||||
cbfunc(self.online, self.state)
|
||||
if kwds:
|
||||
raise TypeError('unknown callback: %s' % (', '.join(kwds)))
|
||||
raise TypeError(f"unknown callback: {', '.join(kwds)}")
|
||||
|
||||
def unregister_callback(self, key, *args, **kwds):
|
||||
"""unregister a callback
|
||||
@ -310,11 +310,10 @@ class SecopClient(ProxyClient):
|
||||
if reply:
|
||||
self.secop_version = reply.decode('utf-8')
|
||||
else:
|
||||
raise self.error_map('HardwareError')('no answer to %s' % IDENTREQUEST)
|
||||
raise self.error_map('HardwareError')(f'no answer to {IDENTREQUEST}')
|
||||
|
||||
if not VERSIONFMT.match(self.secop_version):
|
||||
raise self.error_map('HardwareError')('bad answer to %s: %r' %
|
||||
(IDENTREQUEST, self.secop_version))
|
||||
raise self.error_map('HardwareError')(f'bad answer to {IDENTREQUEST}: {self.secop_version!r}')
|
||||
# inform that the other party still uses a legacy identifier
|
||||
# see e.g. Frappy Bug #4659 (https://forge.frm2.tum.de/redmine/issues/4659)
|
||||
if not self.secop_version.startswith(IDENTPREFIX):
|
||||
@ -387,9 +386,9 @@ class SecopClient(ProxyClient):
|
||||
if module_param is None and ':' not in (ident or ''):
|
||||
# allow missing ':value'/':target'
|
||||
if action == WRITEREPLY:
|
||||
module_param = self.internal.get('%s:target' % ident, None)
|
||||
module_param = self.internal.get(f'{ident}:target', None)
|
||||
else:
|
||||
module_param = self.internal.get('%s:value' % ident, None)
|
||||
module_param = self.internal.get(f'{ident}:value', None)
|
||||
if module_param is not None:
|
||||
if action.startswith(ERRORPREFIX):
|
||||
timestamp = data[2].get('t', None)
|
||||
@ -546,7 +545,7 @@ class SecopClient(ProxyClient):
|
||||
iname = self.internalize_name(aname)
|
||||
datatype = get_datatype(aentry['datainfo'], iname)
|
||||
aentry = dict(aentry, datatype=datatype)
|
||||
ident = '%s:%s' % (modname, aname)
|
||||
ident = f'{modname}:{aname}'
|
||||
self.identifier[modname, iname] = ident
|
||||
self.internal[ident] = modname, iname
|
||||
if datatype.IS_COMMAND:
|
||||
|
@ -80,7 +80,7 @@ class Logger:
|
||||
if tm.tm_min != self._minute:
|
||||
self._minute = tm.tm_min
|
||||
print(CLR + time.strftime('--- %H:%M:%S ---', tm))
|
||||
sec = ('%6.3f' % (now % 60.0)).replace(' ', '0')
|
||||
sec = f'{now % 60.0:6.3f}'.replace(' ', '0')
|
||||
print(CLR + sec, str(fmt) % args)
|
||||
else:
|
||||
print(CLR + (str(fmt) % args))
|
||||
@ -101,7 +101,7 @@ class PrettyFloat(float):
|
||||
- always display a decimal point
|
||||
"""
|
||||
def __repr__(self):
|
||||
result = '%.12g' % self
|
||||
result = f'{self:.12g}'
|
||||
if '.' in result or 'e' in result:
|
||||
return result
|
||||
return result + '.'
|
||||
@ -124,7 +124,7 @@ class Module:
|
||||
self._running = None
|
||||
self._status = None
|
||||
props = secnode.modules[name]['properties']
|
||||
self._title = '# %s (%s)' % (props.get('implementation', ''), props.get('interface_classes', [''])[0])
|
||||
self._title = f"# {props.get('implementation', '')} ({props.get('interface_classes', [''])[0]})"
|
||||
|
||||
def _one_line(self, pname, minwid=0):
|
||||
"""return <module>.<param> = <value> truncated to one line"""
|
||||
@ -134,7 +134,7 @@ class Module:
|
||||
vallen = 113 - len(self._name) - len(pname)
|
||||
if len(result) > vallen:
|
||||
result = result[:vallen - 4] + ' ...'
|
||||
return '%s.%s = %s' % (self._name, pname, result)
|
||||
return f'{self._name}.{pname} = {result}'
|
||||
|
||||
def _isBusy(self):
|
||||
return self.status[0] // 100 == StatusType.BUSY // 100
|
||||
@ -188,7 +188,7 @@ class Module:
|
||||
else:
|
||||
self._secnode.log.error('can not set %r on module %s', item, self._name)
|
||||
self._watched_params = params
|
||||
print('--- %s:\nlog: %s, watch: %s' % (self._name, self._log_level, ' '.join(self._watched_params)))
|
||||
print(f"--- {self._name}:\nlog: {self._log_level}, watch: {' '.join(self._watched_params)}")
|
||||
|
||||
def _start_watching(self):
|
||||
for pname in self._watched_params:
|
||||
@ -318,11 +318,11 @@ def watch(*args, **kwds):
|
||||
modules.append(mobj)
|
||||
mobj._set_watching()
|
||||
else:
|
||||
print('do not know %r' % mobj)
|
||||
print(f'do not know {mobj!r}')
|
||||
for key, arg in kwds.items():
|
||||
mobj = getattr(main, key, None)
|
||||
if mobj is None:
|
||||
print('do not know %r' % key)
|
||||
print(f'do not know {key!r}')
|
||||
else:
|
||||
modules.append(mobj)
|
||||
mobj._set_watching(arg)
|
||||
@ -379,7 +379,7 @@ class Client(SecopClient):
|
||||
attrs[pname] = Param(pname, pinfo['datainfo'])
|
||||
for cname in moddesc['commands']:
|
||||
attrs[cname] = Command(cname, modname, self)
|
||||
mobj = type('M_%s' % modname, (Module,), attrs)(modname, self)
|
||||
mobj = type(f'M_{modname}', (Module,), attrs)(modname, self)
|
||||
if 'status' in mobj._parameters:
|
||||
self.register_callback((modname, 'status'), updateEvent=mobj._status_value_update)
|
||||
self.register_callback((modname, 'value'), updateEvent=mobj._status_value_update)
|
||||
@ -405,7 +405,7 @@ class Client(SecopClient):
|
||||
self.log.info('unhandled: %s %s %r', action, ident, data)
|
||||
|
||||
def __repr__(self):
|
||||
return 'Client(%r)' % self.uri
|
||||
return f'Client({self.uri!r})'
|
||||
|
||||
|
||||
class Console(code.InteractiveConsole):
|
||||
|
@ -68,9 +68,7 @@ class Mod(dict):
|
||||
|
||||
# matches name from spec
|
||||
if not re.match(r'^[a-zA-Z]\w{0,62}$', name, re.ASCII):
|
||||
raise ConfigError('Not a valid SECoP Module name: "%s". '
|
||||
'Does it only contain letters, numbers and underscores?'
|
||||
% (name))
|
||||
raise ConfigError(f'Not a valid SECoP Module name: "{name}". Does it only contain letters, numbers and underscores?')
|
||||
# Make parameters out of all keywords
|
||||
groups = {}
|
||||
for key, val in kwds.items():
|
||||
@ -152,8 +150,7 @@ def to_config_path(cfgfile, log):
|
||||
filename = None
|
||||
|
||||
if filename is None:
|
||||
raise ConfigError("Couldn't find cfg file %r in %s"
|
||||
% (cfgfile, generalConfig.confdir))
|
||||
raise ConfigError(f"Couldn't find cfg file {cfgfile!r} in {generalConfig.confdir}")
|
||||
if not filename.endswith('_cfg.py'):
|
||||
log.warning("Config files should end in '_cfg.py': %s", os.path.basename(filename))
|
||||
log.debug('Using config file %s for %s', filename, cfgfile)
|
||||
|
@ -227,7 +227,7 @@ class FloatRange(HasUnit, DataType):
|
||||
raise
|
||||
value = float(value)
|
||||
except Exception:
|
||||
raise WrongTypeError('can not convert %s to a float' % shortrepr(value)) from None
|
||||
raise WrongTypeError(f'can not convert {shortrepr(value)} to a float') from None
|
||||
|
||||
# map +/-infty to +/-max possible number
|
||||
return clamp(-sys.float_info.max, value, sys.float_info.max)
|
||||
@ -241,8 +241,7 @@ class FloatRange(HasUnit, DataType):
|
||||
# silently clamp when outside by not more than prec
|
||||
return clamp(self.min, value, self.max)
|
||||
info = self.exportProperties()
|
||||
raise RangeError('%.14g must be between %g and %g' %
|
||||
(value, info.get('min', float('-inf')), info.get('max', float('inf'))))
|
||||
raise RangeError(f"{value:.14g} must be between {info.get('min', float('-inf')):g} and {info.get('max', float('inf')):g}")
|
||||
|
||||
def __repr__(self):
|
||||
hints = self.get_info()
|
||||
@ -314,7 +313,7 @@ class IntRange(DataType):
|
||||
fvalue = float(value)
|
||||
value = int(value)
|
||||
except Exception:
|
||||
raise WrongTypeError('can not convert %s to an int' % shortrepr(value)) from None
|
||||
raise WrongTypeError(f'can not convert {shortrepr(value)} to an int') from None
|
||||
if round(fvalue) != fvalue:
|
||||
raise WrongTypeError('%r should be an int')
|
||||
return value
|
||||
@ -334,7 +333,7 @@ class IntRange(DataType):
|
||||
args = args[:1]
|
||||
if args[0] == DEFAULT_MIN_INT:
|
||||
args = ()
|
||||
return 'IntRange%s' % repr(args)
|
||||
return f'IntRange{repr(args)}'
|
||||
|
||||
def export_value(self, value):
|
||||
"""returns a python object fit for serialisation"""
|
||||
@ -435,7 +434,7 @@ class ScaledInteger(HasUnit, DataType):
|
||||
raise
|
||||
value = float(value)
|
||||
except Exception:
|
||||
raise WrongTypeError('can not convert %s to float' % shortrepr(value)) from None
|
||||
raise WrongTypeError(f'can not convert {shortrepr(value)} to float') from None
|
||||
intval = int(round(value / self.scale))
|
||||
return float(intval * self.scale) # return 'actual' value (which is more discrete than a float)
|
||||
|
||||
@ -445,11 +444,10 @@ class ScaledInteger(HasUnit, DataType):
|
||||
if self.min - self.scale < value < self.max + self.scale:
|
||||
# silently clamp when outside by not more than self.scale
|
||||
return clamp(self(self.min), result, self(self.max))
|
||||
raise RangeError('%.14g must be between between %g and %g' %
|
||||
(value, self.min, self.max))
|
||||
raise RangeError(f'{value:.14g} must be between between {self.min:g} and {self.max:g}')
|
||||
|
||||
def __repr__(self):
|
||||
hints = self.get_info(scale=float('%g' % self.scale),
|
||||
hints = self.get_info(scale=float(f'{self.scale:g}'),
|
||||
min=int(round(self.min / self.scale)),
|
||||
max=int(round(self.max / self.scale)))
|
||||
return 'ScaledInteger(%s)' % (', '.join('%s=%r' % kv for kv in hints.items()))
|
||||
@ -522,14 +520,14 @@ class EnumType(DataType):
|
||||
return self._enum[value]
|
||||
except (KeyError, TypeError): # TypeError will be raised when value is not hashable
|
||||
if isinstance(value, (int, str)):
|
||||
raise RangeError('%s is not a member of enum %r' % (shortrepr(value), self._enum)) from None
|
||||
raise WrongTypeError('%s must be either int or str for an enum value' % (shortrepr(value))) from None
|
||||
raise RangeError(f'{shortrepr(value)} is not a member of enum {self._enum!r}') from None
|
||||
raise WrongTypeError(f'{shortrepr(value)} must be either int or str for an enum value') from None
|
||||
|
||||
def from_string(self, text):
|
||||
return self(text)
|
||||
|
||||
def format_value(self, value, unit=None):
|
||||
return '%s<%s>' % (self._enum[value].name, self._enum[value].value)
|
||||
return f'{self._enum[value].name}<{self._enum[value].value}>'
|
||||
|
||||
def set_name(self, name):
|
||||
self._enum.name = name
|
||||
@ -571,7 +569,7 @@ class BLOBType(DataType):
|
||||
def __call__(self, value):
|
||||
"""accepts bytes only"""
|
||||
if not isinstance(value, bytes):
|
||||
raise WrongTypeError('%s must be of type bytes' % shortrepr(value))
|
||||
raise WrongTypeError(f'{shortrepr(value)} must be of type bytes')
|
||||
size = len(value)
|
||||
if size < self.minbytes:
|
||||
raise RangeError(
|
||||
@ -636,12 +634,12 @@ class StringType(DataType):
|
||||
def __call__(self, value):
|
||||
"""accepts strings only"""
|
||||
if not isinstance(value, str):
|
||||
raise WrongTypeError('%s has the wrong type!' % shortrepr(value))
|
||||
raise WrongTypeError(f'{shortrepr(value)} has the wrong type!')
|
||||
if not self.isUTF8:
|
||||
try:
|
||||
value.encode('ascii')
|
||||
except UnicodeEncodeError:
|
||||
raise RangeError('%s contains non-ascii character!' % shortrepr(value)) from None
|
||||
raise RangeError(f'{shortrepr(value)} contains non-ascii character!') from None
|
||||
size = len(value)
|
||||
if size < self.minchars:
|
||||
raise RangeError(
|
||||
@ -656,7 +654,7 @@ class StringType(DataType):
|
||||
|
||||
def export_value(self, value):
|
||||
"""returns a python object fit for serialisation"""
|
||||
return '%s' % value
|
||||
return f'{value}'
|
||||
|
||||
def import_value(self, value):
|
||||
"""returns a python object from serialisation"""
|
||||
@ -716,7 +714,7 @@ class BoolType(DataType):
|
||||
return False
|
||||
if value in [1, '1', 'True', 'true', 'yes', 'on', True]:
|
||||
return True
|
||||
raise WrongTypeError('%s is not a boolean value!' % shortrepr(value))
|
||||
raise WrongTypeError(f'{shortrepr(value)} is not a boolean value!')
|
||||
|
||||
def export_value(self, value):
|
||||
"""returns a python object fit for serialisation"""
|
||||
@ -794,8 +792,7 @@ class ArrayOf(DataType):
|
||||
'members': self.members.export_datatype()}
|
||||
|
||||
def __repr__(self):
|
||||
return 'ArrayOf(%s, %s, %s)' % (
|
||||
repr(self.members), self.minlen, self.maxlen)
|
||||
return f'ArrayOf({repr(self.members)}, {self.minlen}, {self.maxlen})'
|
||||
|
||||
def check_type(self, value):
|
||||
try:
|
||||
@ -808,8 +805,7 @@ class ArrayOf(DataType):
|
||||
raise RangeError(
|
||||
'array too big, holds at most %d elements!' % self.maxlen)
|
||||
except TypeError:
|
||||
raise WrongTypeError('%s can not be converted to ArrayOf DataType!'
|
||||
% type(value).__name__) from None
|
||||
raise WrongTypeError(f'{type(value).__name__} can not be converted to ArrayOf DataType!') from None
|
||||
|
||||
def __call__(self, value):
|
||||
"""accepts any sequence, converts to tuple (immutable!)"""
|
||||
@ -841,7 +837,7 @@ class ArrayOf(DataType):
|
||||
def from_string(self, text):
|
||||
value, rem = Parser.parse(text)
|
||||
if rem:
|
||||
raise ProtocolError('trailing garbage: %r' % rem)
|
||||
raise ProtocolError(f'trailing garbage: {rem!r}')
|
||||
return self(value)
|
||||
|
||||
def format_value(self, value, unit=None):
|
||||
@ -854,7 +850,7 @@ class ArrayOf(DataType):
|
||||
unit = members.unit
|
||||
else:
|
||||
innerunit = None
|
||||
res = '[%s]' % (', '.join([self.members.format_value(elem, innerunit) for elem in value]))
|
||||
res = f"[{', '.join([self.members.format_value(elem, innerunit) for elem in value])}]"
|
||||
if unit:
|
||||
return ' '.join([res, unit])
|
||||
return res
|
||||
@ -895,16 +891,15 @@ class TupleOf(DataType):
|
||||
return {'type': 'tuple', 'members': [subtype.export_datatype() for subtype in self.members]}
|
||||
|
||||
def __repr__(self):
|
||||
return 'TupleOf(%s)' % ', '.join([repr(st) for st in self.members])
|
||||
return f"TupleOf({', '.join([repr(st) for st in self.members])})"
|
||||
|
||||
def check_type(self, value):
|
||||
try:
|
||||
if len(value) != len(self.members):
|
||||
raise WrongTypeError(
|
||||
'tuple needs %d elements' % len(self.members))
|
||||
f'tuple needs {len(self.members)} elements')
|
||||
except TypeError:
|
||||
raise WrongTypeError('%s can not be converted to TupleOf DataType!'
|
||||
% type(value).__name__) from None
|
||||
raise WrongTypeError(f'{type(value).__name__} can not be converted to TupleOf DataType!') from None
|
||||
|
||||
def __call__(self, value):
|
||||
"""accepts any sequence, converts to tuple"""
|
||||
@ -936,12 +931,11 @@ class TupleOf(DataType):
|
||||
def from_string(self, text):
|
||||
value, rem = Parser.parse(text)
|
||||
if rem:
|
||||
raise ProtocolError('trailing garbage: %r' % rem)
|
||||
raise ProtocolError(f'trailing garbage: {rem!r}')
|
||||
return self(value)
|
||||
|
||||
def format_value(self, value, unit=None):
|
||||
return '(%s)' % (', '.join([sub.format_value(elem)
|
||||
for sub, elem in zip(self.members, value)]))
|
||||
return f"({', '.join([sub.format_value(elem) for sub, elem in zip(self.members, value)])})"
|
||||
|
||||
def compatible(self, other):
|
||||
if not isinstance(other, TupleOf):
|
||||
@ -998,7 +992,7 @@ class StructOf(DataType):
|
||||
return res
|
||||
|
||||
def __repr__(self):
|
||||
opt = ', optional=%r' % self.optional if self.optional else ''
|
||||
opt = f', optional={self.optional!r}' if self.optional else ''
|
||||
return 'StructOf(%s%s)' % (', '.join(
|
||||
['%s=%s' % (n, repr(st)) for n, st in list(self.members.items())]), opt)
|
||||
|
||||
@ -1008,8 +1002,7 @@ class StructOf(DataType):
|
||||
if set(dict(value)) != set(self.members):
|
||||
raise WrongTypeError('member names do not match') from None
|
||||
except TypeError:
|
||||
raise WrongTypeError('%s can not be converted a StructOf'
|
||||
% type(value).__name__) from None
|
||||
raise WrongTypeError(f'{type(value).__name__} can not be converted a StructOf') from None
|
||||
try:
|
||||
return ImmutableDict((str(k), self.members[k](v))
|
||||
for k, v in list(value.items()))
|
||||
@ -1021,13 +1014,12 @@ class StructOf(DataType):
|
||||
try:
|
||||
superfluous = set(dict(value)) - set(self.members)
|
||||
except TypeError:
|
||||
raise WrongTypeError('%s can not be converted a StructOf'
|
||||
% type(value).__name__) from None
|
||||
raise WrongTypeError(f'{type(value).__name__} can not be converted a StructOf') from None
|
||||
if superfluous - set(self.optional):
|
||||
raise WrongTypeError('struct contains superfluous members: %s' % ', '.join(superfluous))
|
||||
raise WrongTypeError(f"struct contains superfluous members: {', '.join(superfluous)}")
|
||||
missing = set(self.members) - set(value) - set(self.optional)
|
||||
if missing:
|
||||
raise WrongTypeError('missing struct elements: %s' % ', '.join(missing))
|
||||
raise WrongTypeError(f"missing struct elements: {', '.join(missing)}")
|
||||
try:
|
||||
if previous is None:
|
||||
return ImmutableDict((str(k), self.members[k].validate(v))
|
||||
@ -1052,7 +1044,7 @@ class StructOf(DataType):
|
||||
def from_string(self, text):
|
||||
value, rem = Parser.parse(text)
|
||||
if rem:
|
||||
raise ProtocolError('trailing garbage: %r' % rem)
|
||||
raise ProtocolError(f'trailing garbage: {rem!r}')
|
||||
return self(dict(value))
|
||||
|
||||
def format_value(self, value, unit=None):
|
||||
@ -1103,8 +1095,8 @@ class CommandType(DataType):
|
||||
|
||||
def __repr__(self):
|
||||
if self.result is None:
|
||||
return 'CommandType(%s)' % (repr(self.argument) if self.argument else '')
|
||||
return 'CommandType(%s, %s)' % (repr(self.argument), repr(self.result))
|
||||
return f"CommandType({repr(self.argument) if self.argument else ''})"
|
||||
return f'CommandType({repr(self.argument)}, {repr(self.result)})'
|
||||
|
||||
def __call__(self, value):
|
||||
raise ProgrammingError('commands can not be converted to a value')
|
||||
@ -1118,7 +1110,7 @@ class CommandType(DataType):
|
||||
def from_string(self, text):
|
||||
value, rem = Parser.parse(text)
|
||||
if rem:
|
||||
raise ProtocolError('trailing garbage: %r' % rem)
|
||||
raise ProtocolError(f'trailing garbage: {rem!r}')
|
||||
return self(value)
|
||||
|
||||
def format_value(self, value, unit=None):
|
||||
@ -1184,8 +1176,7 @@ class ValueType(DataType):
|
||||
try:
|
||||
return self.validator(value)
|
||||
except Exception as e:
|
||||
raise ConfigError('Validator %s raised %r for value %s' \
|
||||
% (self.validator, e, value)) from e
|
||||
raise ConfigError(f'Validator {self.validator} raised {e!r} for value {value}') from e
|
||||
return value
|
||||
|
||||
def copy(self):
|
||||
@ -1242,7 +1233,7 @@ class OrType(DataType):
|
||||
return t.validate(value) # use always strict validation
|
||||
except Exception:
|
||||
pass
|
||||
raise WrongTypeError("Invalid Value, must conform to one of %s" % (', '.join((str(t) for t in self.types))))
|
||||
raise WrongTypeError(f"Invalid Value, must conform to one of {', '.join(str(t) for t in self.types)}")
|
||||
|
||||
|
||||
Int8 = IntRange(-(1 << 7), (1 << 7) - 1)
|
||||
@ -1264,7 +1255,7 @@ class LimitsType(TupleOf):
|
||||
"""accepts an ordered tuple of numeric member types"""
|
||||
limits = TupleOf.validate(self, value)
|
||||
if limits[1] < limits[0]:
|
||||
raise RangeError('Maximum Value %s must be greater than minimum value %s!' % (limits[1], limits[0]))
|
||||
raise RangeError(f'Maximum Value {limits[1]} must be greater than minimum value {limits[0]}!')
|
||||
return limits
|
||||
|
||||
|
||||
@ -1312,7 +1303,7 @@ class StatusType(TupleOf):
|
||||
first = 'Status' # enum name
|
||||
bad = {n for n in args if n not in StatusType.__dict__ or n.startswith('_')} # avoid built-in attributes
|
||||
if bad:
|
||||
raise ProgrammingError('positional arguments %r must be standard status code names' % bad)
|
||||
raise ProgrammingError(f'positional arguments {bad!r} must be standard status code names')
|
||||
self.enum = Enum(Enum(first, **{n: StatusType.__dict__[n] for n in args}), **kwds)
|
||||
super().__init__(EnumType(self.enum), StringType())
|
||||
|
||||
@ -1374,9 +1365,9 @@ def get_datatype(json, pname=''):
|
||||
kwargs = json.copy()
|
||||
base = kwargs.pop('type')
|
||||
except (TypeError, KeyError, AttributeError):
|
||||
raise WrongTypeError('a data descriptor must be a dict containing a "type" key, not %r' % json) from None
|
||||
raise WrongTypeError(f'a data descriptor must be a dict containing a "type" key, not {json!r}') from None
|
||||
|
||||
try:
|
||||
return DATATYPES[base](pname=pname, **kwargs)
|
||||
except Exception as e:
|
||||
raise WrongTypeError('invalid data descriptor: %r (%s)' % (json, str(e))) from None
|
||||
raise WrongTypeError(f'invalid data descriptor: {json!r} ({str(e)})') from None
|
||||
|
@ -54,7 +54,7 @@ class SECoPError(RuntimeError):
|
||||
res = []
|
||||
res.extend((repr(a) for a in self.args))
|
||||
#res.extend(('%s=%r' % i for i in self.kwds.items()))
|
||||
return '%s(%s)' % (self.name or type(self).__name__, ', '.join(res))
|
||||
return f"{self.name or type(self).__name__}({', '.join(res)})"
|
||||
|
||||
def __str__(self):
|
||||
return self.format(True)
|
||||
@ -76,7 +76,7 @@ class SECoPError(RuntimeError):
|
||||
prefix = '' if self.name2class.get(self.name) == type(self) else type(self).__name__
|
||||
prefix += ''.join(' in ' + m for m in mlist).strip()
|
||||
if prefix:
|
||||
return '%s: %s' % (prefix, super().__str__())
|
||||
return f'{prefix}: {super().__str__()}'
|
||||
return super().__str__()
|
||||
|
||||
def __eq__(self, other):
|
||||
@ -268,7 +268,7 @@ def secop_error(exc):
|
||||
"""turn into InternalError, if not already a SECoPError"""
|
||||
if isinstance(exc, SECoPError):
|
||||
return exc
|
||||
return InternalError('%s: %s' % (type(exc).__name__, exc))
|
||||
return InternalError(f'{type(exc).__name__}: {exc}')
|
||||
|
||||
|
||||
# TODO: check if these are really needed:
|
||||
|
@ -79,7 +79,7 @@ class HasTargetLimits(Feature):
|
||||
min_, max_ = self.abslimits
|
||||
t_min, t_max = self.apply_offset(1, dt.min, dt.max)
|
||||
if t_min > max_ or t_max < min_:
|
||||
raise ConfigError('abslimits not within %s range' % pname)
|
||||
raise ConfigError(f'abslimits not within {pname} range')
|
||||
self.abslimits = clamp(t_min, min_, t_max), clamp(t_min, max_, t_max)
|
||||
super().checkProperties()
|
||||
|
||||
@ -90,8 +90,8 @@ class HasTargetLimits(Feature):
|
||||
min_, max_ = self.apply_offset(-1, *self.abslimits)
|
||||
if not min_ <= value[0] <= value[1] <= max_:
|
||||
if value[0] > value[1]:
|
||||
raise RangeError('invalid interval: %r' % value)
|
||||
raise RangeError('limits not within abs limits [%g, %g]' % (min_, max_))
|
||||
raise RangeError(f'invalid interval: {value!r}')
|
||||
raise RangeError(f'limits not within abs limits [{min_:g}, {max_:g}]')
|
||||
self.limits = value
|
||||
self.saveParameters()
|
||||
return self.limits
|
||||
@ -100,7 +100,7 @@ class HasTargetLimits(Feature):
|
||||
"""check if value is valid"""
|
||||
min_, max_ = self.target_limits
|
||||
if not min_ <= value <= max_:
|
||||
raise RangeError('limits violation: %g outside [%g, %g]' % (value, min_, max_))
|
||||
raise RangeError(f'limits violation: {value:g} outside [{min_:g}, {max_:g}]')
|
||||
|
||||
|
||||
# --- legacy mixins, not agreed as standard ---
|
||||
|
@ -57,13 +57,13 @@ def write_config(file_name, tree_widget):
|
||||
blank_lines += 1
|
||||
value = value.replace('\n\n', '\n.\n')
|
||||
value = value.replace('\n', '\n ')
|
||||
itm_lines[id(itm)] = '[%s %s]\n' % (itm.kind, itm.name) +\
|
||||
itm_lines[id(itm)] = f'[{itm.kind} {itm.name}]\n' +\
|
||||
value_str % (SECTIONS[itm.kind], value)
|
||||
# TODO params and props
|
||||
elif itm.kind == PARAMETER and value:
|
||||
itm_lines[id(itm)] = value_str % (itm.name, value)
|
||||
elif itm.kind == PROPERTY:
|
||||
prop_name = '.%s' % itm.name
|
||||
prop_name = f'.{itm.name}'
|
||||
if par.kind == PARAMETER:
|
||||
prop_name = par.name + prop_name
|
||||
itm_lines[id(itm)] = value_str % (prop_name, value)
|
||||
@ -72,7 +72,7 @@ def write_config(file_name, tree_widget):
|
||||
for key, dict_value in itm_lines.items():
|
||||
if key == id(par):
|
||||
value = value.replace('\n', '\n# ')
|
||||
temp_itm_lines[id(itm)] = '# %s' % value
|
||||
temp_itm_lines[id(itm)] = f'# {value}'
|
||||
temp_itm_lines[key] = dict_value
|
||||
itm_lines.clear()
|
||||
itm_lines.update(temp_itm_lines)
|
||||
@ -166,8 +166,7 @@ def get_comments(node, ifs, mods, file_path):
|
||||
if line.startswith('#'):
|
||||
line = line[1:].strip()
|
||||
if index and all_lines[index-1][0] == '#':
|
||||
current_comment.set_value('%s\n%s' % (current_comment.
|
||||
get_value(), line))
|
||||
current_comment.set_value(f'{current_comment.get_value()}\n{line}')
|
||||
else:
|
||||
current_comment = TreeWidgetItem(COMMENT, '#', line)
|
||||
next_line = get_next_line(index, all_lines)
|
||||
@ -196,12 +195,12 @@ def insert_comment(index, line, all_lines, current_comment, node, all_ifs, all_m
|
||||
# pylint: disable=inconsistent-return-statements
|
||||
def insert_section_comment(line, current_comment, node, all_ifs, all_mods):
|
||||
try:
|
||||
if line.startswith('[%s' % NODE):
|
||||
if line.startswith(f'[{NODE}'):
|
||||
node.insertChild(0, current_comment)
|
||||
elif line.startswith('[%s' % INTERFACE):
|
||||
elif line.startswith(f'[{INTERFACE}'):
|
||||
all_ifs[get_name_of_section(line)]. \
|
||||
insertChild(0, current_comment)
|
||||
elif line.startswith('[%s' % MODULE):
|
||||
elif line.startswith(f'[{MODULE}'):
|
||||
all_mods[get_name_of_section(line)]. \
|
||||
insertChild(0, current_comment)
|
||||
else:
|
||||
@ -219,9 +218,9 @@ def insert_param_prop_comment(index, line, all_lines, current_comment,
|
||||
if not parent:
|
||||
# TODO invalid file
|
||||
pass
|
||||
if parent.startswith('[%s' % NODE):
|
||||
if parent.startswith(f'[{NODE}'):
|
||||
parent_item = node
|
||||
elif parent.startswith('[%s' % INTERFACE):
|
||||
elif parent.startswith(f'[{INTERFACE}'):
|
||||
parent_item = all_ifs[get_name_of_section(parent)]
|
||||
else:
|
||||
parent_item = all_mods[get_name_of_section(parent)]
|
||||
|
@ -166,13 +166,13 @@ class MainWindow(QMainWindow):
|
||||
|
||||
def show_save_message(self, file_name=''):
|
||||
if file_name:
|
||||
file_name = ' in "%s"' % file_name
|
||||
return QMessageBox.question(self, 'Save file?', '''
|
||||
<h2>Do you want to save changes%s?</h2>
|
||||
file_name = f' in "{file_name}"'
|
||||
return QMessageBox.question(self, 'Save file?', f'''
|
||||
<h2>Do you want to save changes{file_name}?</h2>
|
||||
<p>
|
||||
Your changes will be lost if you don't save them!
|
||||
</p>
|
||||
''' % file_name,
|
||||
''',
|
||||
QMessageBox.StandardButton.Cancel |
|
||||
QMessageBox.StandardButton.Close |
|
||||
QMessageBox.StandardButton.Save,
|
||||
|
@ -52,7 +52,7 @@ class TreeWidgetItem(QTreeWidgetItem):
|
||||
self.parameters = parameters or {}
|
||||
self.properties = properties or {}
|
||||
if self.kind and self.kind != 'node':
|
||||
setTreeIcon(self, '%s.png' % self.kind)
|
||||
setTreeIcon(self, f'{self.kind}.png')
|
||||
else:
|
||||
setTreeIcon(self, 'empty.png')
|
||||
font = QFont()
|
||||
|
@ -40,7 +40,7 @@ def loadUi(widget, uiname, subdir='ui'):
|
||||
|
||||
|
||||
def setIcon(widget, icon_name):
|
||||
widget.setIcon(QIcon(':/cfg_editor/%s' % icon_name))
|
||||
widget.setIcon(QIcon(f':/cfg_editor/{icon_name}'))
|
||||
widget.setIconSize(QSize(60, 60))
|
||||
|
||||
|
||||
@ -58,11 +58,11 @@ def set_name_edit_style(invalid, name_edit, button_box=None):
|
||||
|
||||
|
||||
def setTreeIcon(widget, icon_name):
|
||||
widget.setIcon(0, QIcon(':/cfg_editor/%s' % icon_name))
|
||||
widget.setIcon(0, QIcon(f':/cfg_editor/{icon_name}'))
|
||||
|
||||
|
||||
def setActionIcon(widget, icon_name):
|
||||
widget.setIcon(QIcon(':/cfg_editor/%s' % icon_name))
|
||||
widget.setIcon(QIcon(f':/cfg_editor/{icon_name}'))
|
||||
|
||||
|
||||
def get_subtree_nodes(tree_widget_item):
|
||||
@ -117,7 +117,7 @@ def get_modules():
|
||||
if not path.isfile(path.join(base_path, dirname, filename)) or \
|
||||
filename == '__init__.py' or filename[-3:] != '.py':
|
||||
continue
|
||||
module = '%s.%s' % (dirname, filename[:-3])
|
||||
module = f'{dirname}.{filename[:-3]}'
|
||||
module_in_file = False
|
||||
try:
|
||||
__import__(module)
|
||||
|
@ -338,7 +338,7 @@ class AddDialog(QDialog):
|
||||
the value from self.value"""
|
||||
super().__init__(parent)
|
||||
loadUi(self, 'add_dialog.ui')
|
||||
self.setWindowTitle('Add %s' % kind)
|
||||
self.setWindowTitle(f'Add {kind}')
|
||||
self.kind = kind
|
||||
self.invalid_names = invalid_names
|
||||
if self.invalid_names:
|
||||
@ -478,7 +478,7 @@ class TreeComboBox(QComboBox):
|
||||
act_item = act_index.model().itemFromIndex(act_index)
|
||||
value += act_item.text()
|
||||
while act_item.parent():
|
||||
value = '%s.%s' % (act_item.parent().text(), value)
|
||||
value = f'{act_item.parent().text()}.{value}'
|
||||
act_item = act_item.parent()
|
||||
return value
|
||||
|
||||
|
@ -42,7 +42,7 @@ class QSECNode(QObject):
|
||||
self.equipmentId = conn.properties['equipment_id']
|
||||
self.log.info('Switching to logger %s', self.equipmentId)
|
||||
self.log.name = '.'.join((parent_logger.name, self.equipmentId))
|
||||
self.nodename = '%s (%s)' % (self.equipmentId, conn.uri)
|
||||
self.nodename = f'{self.equipmentId} ({conn.uri})'
|
||||
self.modules = conn.modules
|
||||
self.properties = self.conn.properties
|
||||
self.protocolVersion = conn.secop_version
|
||||
@ -106,7 +106,7 @@ class QSECNode(QObject):
|
||||
self.stateChange.emit(self.nodename, online, state)
|
||||
|
||||
def unhandledMessage(self, action, specifier, data):
|
||||
self.unhandledMsg.emit('%s %s %r' % (action, specifier, data))
|
||||
self.unhandledMsg.emit(f'{action} {specifier} {data!r}')
|
||||
|
||||
def terminate_connection(self):
|
||||
self.conn.disconnect()
|
||||
|
@ -153,24 +153,22 @@ class Console(QWidget):
|
||||
return
|
||||
|
||||
self._addLogEntry(
|
||||
'<span style="font-weight:bold">Request:</span> '
|
||||
'<tt>%s</tt>' % toHtmlEscaped(msg),
|
||||
f'<span style="font-weight:bold">Request:</span> <tt>{toHtmlEscaped(msg)}</tt>',
|
||||
raw=True)
|
||||
# msg = msg.split(' ', 2)
|
||||
try:
|
||||
reply = self._node.syncCommunicate(*self._node.decode_message(msg))
|
||||
if msg == 'describe':
|
||||
_, eid, stuff = self._node.decode_message(reply)
|
||||
reply = '%s %s %s' % (_, eid, json.dumps(
|
||||
stuff, indent=2, separators=(',', ':'), sort_keys=True))
|
||||
reply = f"{_} {eid} {json.dumps(stuff, indent=2, separators=(',', ':'), sort_keys=True)}"
|
||||
self._addLogEntry(reply.rstrip('\n'))
|
||||
else:
|
||||
self._addLogEntry(reply.rstrip('\n'))
|
||||
except SECoPError as e:
|
||||
einfo = e.args[0] if len(e.args) == 1 else json.dumps(e.args)
|
||||
self._addLogEntry('%s: %s' % (e.name, einfo), error=True)
|
||||
self._addLogEntry(f'{e.name}: {einfo}', error=True)
|
||||
except Exception as e:
|
||||
self._addLogEntry('error when sending %r: %r' % (msg, e),
|
||||
self._addLogEntry(f'error when sending {msg!r}: {e!r}',
|
||||
error=True)
|
||||
|
||||
self.msgLineEdit.clear()
|
||||
|
@ -75,11 +75,10 @@ class LogWindow(QMainWindow):
|
||||
s = record.getMessage()
|
||||
time = record.created
|
||||
if record.levelno == self.levels['Error']:
|
||||
s = '<b>%s</b>' %s
|
||||
s='<span style="color:%s">[%s] </span><span style="color:%s">%s: %s</span>' \
|
||||
% (self.timecolor.name(), time, \
|
||||
self.messagecolors[record.levelno].name(), \
|
||||
record.name, s)
|
||||
s = f'<b>{s}</b>'
|
||||
s = f'<span style="color:{self.timecolor.name()}">[{time}] </span>' \
|
||||
f'<span style="color:{self.messagecolors[record.levelno].name()}">' \
|
||||
f'{record.name}: {s}</span>'
|
||||
self.logBrowser.append(s)
|
||||
|
||||
def on_logLevel_currentTextChanged(self, level):
|
||||
|
@ -211,7 +211,7 @@ class MainWindow(QMainWindow):
|
||||
except Exception as e:
|
||||
self.log.error('error in addNode: %r', e)
|
||||
QMessageBox.critical(self.parent(),
|
||||
'Connecting to %s failed!' % host, str(e))
|
||||
f'Connecting to {host} failed!', str(e))
|
||||
|
||||
def _addNode(self, host):
|
||||
prevWidget = self._nodeWidgets.get(host)
|
||||
|
@ -34,7 +34,7 @@ class CommandDialog(QDialog):
|
||||
super().__init__(parent)
|
||||
loadUi(self, 'cmddialog.ui')
|
||||
|
||||
self.setWindowTitle('Arguments for %s' % cmdname)
|
||||
self.setWindowTitle(f'Arguments for {cmdname}')
|
||||
# row = 0
|
||||
|
||||
self._labels = []
|
||||
@ -65,15 +65,14 @@ class CommandDialog(QDialog):
|
||||
def showCommandResultDialog(command, args, result, extras=''):
|
||||
m = QMessageBox()
|
||||
args = '' if args is None else repr(args)
|
||||
m.setText('calling: %s(%s)\nyielded: %r\nqualifiers: %s' %
|
||||
(command, args, result, extras))
|
||||
m.setText(f'calling: {command}({args})\nyielded: {result!r}\nqualifiers: {extras}')
|
||||
m.exec()
|
||||
|
||||
|
||||
def showErrorDialog(command, args, error):
|
||||
m = QMessageBox()
|
||||
args = '' if args is None else repr(args)
|
||||
m.setText('calling: %s(%s)\nraised %r' % (command, args, error))
|
||||
m.setText(f'calling: {command}({args})\nraised {error!r}')
|
||||
m.exec()
|
||||
|
||||
|
||||
@ -271,7 +270,7 @@ class ModuleWidget(QWidget):
|
||||
for prop, value in props.items():
|
||||
l = QHBoxLayout()
|
||||
l.setContentsMargins(0,0,0,0)
|
||||
name = QLabel('<b>%s:</b>' % prop.capitalize())
|
||||
name = QLabel(f'<b>{prop.capitalize()}:</b>')
|
||||
val = QLabel(str(value))
|
||||
val.setWordWrap(True)
|
||||
l.addWidget(name)
|
||||
@ -353,7 +352,7 @@ class ModuleWidget(QWidget):
|
||||
return
|
||||
plotButton = QToolButton()
|
||||
plotButton.setIcon(QIcon(':/icons/plot'))
|
||||
plotButton.setToolTip('Plot %s' % param)
|
||||
plotButton.setToolTip(f'Plot {param}')
|
||||
plotAddButton = QToolButton()
|
||||
plotAddButton.setIcon(QIcon(':/icons/plot-add'))
|
||||
plotAddButton.setToolTip('Plot With...')
|
||||
|
@ -81,7 +81,7 @@ class NodeWidget(QWidget):
|
||||
self._detailedParams[module] = {}
|
||||
for param in node.getParameters(module):
|
||||
view = ParameterView(node, module, param)
|
||||
view.setWindowTitle('%s:%s:%s - Properties' % (self._node.equipmentId, module, param))
|
||||
view.setWindowTitle(f'{self._node.equipmentId}:{module}:{param} - Properties')
|
||||
self._detailedParams[module][param] = view
|
||||
viewLayout.addWidget(widget)
|
||||
|
||||
@ -154,7 +154,7 @@ class NodeWidget(QWidget):
|
||||
menu_plot_ext.setEnabled(False)
|
||||
else:
|
||||
for (m, p), plot in self._activePlots.items():
|
||||
opt_ext = menu_plot_ext.addAction("%s:%s" % (m, p))
|
||||
opt_ext = menu_plot_ext.addAction(f"{m}:{p}")
|
||||
opt_ext.triggered.connect(
|
||||
lambda plot=plot: self._requestPlot(item, plot))
|
||||
|
||||
@ -178,7 +178,7 @@ class NodeWidget(QWidget):
|
||||
QInputDialog.InputDialogOption.UseListViewForComboBoxItems)
|
||||
dialog.setComboBoxItems(plots.keys())
|
||||
dialog.setTextValue(list(plots)[0])
|
||||
dialog.setWindowTitle('Plot %s with...' % param)
|
||||
dialog.setWindowTitle(f'Plot {param} with...')
|
||||
dialog.setLabelText('')
|
||||
|
||||
if dialog.exec() == QInputDialog.DialogCode.Accepted:
|
||||
|
@ -38,7 +38,7 @@ class ParameterView(QWidget):
|
||||
|
||||
self._propWidgets = {} # widget cache do avoid garbage collection
|
||||
|
||||
self.paramNameLabel.setText("%s:%s" % (module, parameter))
|
||||
self.paramNameLabel.setText(f"{module}:{parameter}")
|
||||
self._initParameterWidgets()
|
||||
|
||||
# self._node.newData.connect(self._updateValue)
|
||||
|
@ -104,11 +104,11 @@ class PlotWidget(QWidget):
|
||||
|
||||
def addCurve(self, node, module, param):
|
||||
paramData = node._getDescribingParameterData(module, param)
|
||||
name = '%s:%s' % (module, param)
|
||||
name = f'{module}:{param}'
|
||||
unit = paramData.get('unit', '')
|
||||
if unit:
|
||||
unit = '/' + unit
|
||||
curve = self.plot.plot(name='%s%s' % (name, unit))
|
||||
curve = self.plot.plot(name=f'{name}{unit}')
|
||||
if 'min' in paramData and 'max' in paramData:
|
||||
curve.setXRange(paramData['min'], paramData['max'])
|
||||
|
||||
@ -118,7 +118,7 @@ class PlotWidget(QWidget):
|
||||
node.newData.connect(self.update)
|
||||
|
||||
def setCurveColor(self, module, param, color):
|
||||
curve = self.curves['%s:%s' % (module, param)]
|
||||
curve = self.curves[f'{module}:{param}']
|
||||
curve.setPen(color)
|
||||
|
||||
def scrollUpdate(self):
|
||||
@ -129,7 +129,7 @@ class PlotWidget(QWidget):
|
||||
curve.setData(x,y)
|
||||
|
||||
def update(self, module, param, value):
|
||||
name = '%s:%s' % (module, param)
|
||||
name = f'{module}:{param}'
|
||||
if name not in self.curves:
|
||||
return
|
||||
curve = self.curves[name]
|
||||
|
@ -260,5 +260,5 @@ class msg(QDialog):
|
||||
super().reject()
|
||||
|
||||
def done(self, how):
|
||||
print('done(%r)' % how)
|
||||
print(f'done({how!r})')
|
||||
return super().done(how)
|
||||
|
15
frappy/io.py
15
frappy/io.py
@ -55,7 +55,7 @@ class HasIO(Module):
|
||||
io = opts.get('io')
|
||||
super().__init__(name, logger, opts, srv)
|
||||
if self.uri:
|
||||
opts = {'uri': self.uri, 'description': 'communication device for %s' % name,
|
||||
opts = {'uri': self.uri, 'description': f'communication device for {name}',
|
||||
'export': False}
|
||||
ioname = self.ioDict.get(self.uri)
|
||||
if not ioname:
|
||||
@ -66,7 +66,7 @@ class HasIO(Module):
|
||||
self.ioDict[self.uri] = ioname
|
||||
self.io = ioname
|
||||
elif not io:
|
||||
raise ConfigError("Module %s needs a value for either 'uri' or 'io'" % name)
|
||||
raise ConfigError(f"Module {name} needs a value for either 'uri' or 'io'")
|
||||
|
||||
def communicate(self, *args):
|
||||
return self.io.communicate(*args)
|
||||
@ -228,14 +228,14 @@ class StringIO(IOBase):
|
||||
return bytes([value])
|
||||
if isinstance(value, bytes):
|
||||
return value
|
||||
raise ValueError('invalid end_of_line: %s' % repr(value))
|
||||
raise ValueError(f'invalid end_of_line: {repr(value)}')
|
||||
|
||||
def earlyInit(self):
|
||||
super().earlyInit()
|
||||
eol = self.end_of_line
|
||||
if isinstance(eol, (tuple, list)):
|
||||
if len(eol) not in (1, 2):
|
||||
raise ValueError('invalid end_of_line: %s' % eol)
|
||||
raise ValueError(f'invalid end_of_line: {eol}')
|
||||
else:
|
||||
eol = [eol]
|
||||
# eol for read and write might be distinct
|
||||
@ -253,8 +253,7 @@ class StringIO(IOBase):
|
||||
reply = self.communicate(command)
|
||||
if not re.match(regexp, reply):
|
||||
self.closeConnection()
|
||||
raise CommunicationFailedError('bad response: %s does not match %s' %
|
||||
(reply, regexp))
|
||||
raise CommunicationFailedError(f'bad response: {reply} does not match {regexp}')
|
||||
|
||||
@Command(StringType(), result=StringType())
|
||||
def communicate(self, command):
|
||||
@ -340,7 +339,7 @@ def make_bytes(string):
|
||||
|
||||
|
||||
def hexify(bytes_):
|
||||
return ' '.join('%02x' % r for r in bytes_)
|
||||
return ' '.join(f'{r:02x}' for r in bytes_)
|
||||
|
||||
|
||||
class BytesIO(IOBase):
|
||||
@ -365,7 +364,7 @@ class BytesIO(IOBase):
|
||||
reply = self.communicate(make_bytes(request), replylen)
|
||||
if not replypat.match(reply):
|
||||
self.closeConnection()
|
||||
raise CommunicationFailedError('bad response: %r does not match %r' % (reply, expected))
|
||||
raise CommunicationFailedError(f'bad response: {reply!r} does not match {expected!r}')
|
||||
|
||||
@Command((BLOBType(), IntRange(0)), result=BLOBType())
|
||||
def communicate(self, request, replylen): # pylint: disable=arguments-differ
|
||||
|
@ -102,11 +102,11 @@ class GeneralConfig:
|
||||
if cfg.get('confdir') is None:
|
||||
cfg['confdir'] = path.dirname(configfile)
|
||||
for key in mandatory:
|
||||
cfg[key] = environ.get('FRAPPY_%s' % key.upper(), cfg.get(key))
|
||||
cfg[key] = environ.get(f'FRAPPY_{key.upper()}', cfg.get(key))
|
||||
missing_keys = [key for key in mandatory if cfg[key] is None]
|
||||
if missing_keys:
|
||||
if configfile:
|
||||
raise KeyError('missing value for %s in %s' % (' and '.join(missing_keys), configfile))
|
||||
raise KeyError(f"missing value for {' and '.join(missing_keys)} in {configfile}")
|
||||
raise KeyError('missing %s' % ' and '.join('FRAPPY_%s' % k.upper() for k in missing_keys))
|
||||
# this is not customizable
|
||||
cfg['basedir'] = repodir
|
||||
@ -215,7 +215,7 @@ def get_class(spec):
|
||||
|
||||
def mkthread(func, *args, **kwds):
|
||||
t = threading.Thread(
|
||||
name='%s:%s' % (func.__module__, func.__name__),
|
||||
name=f'{func.__module__}:{func.__name__}',
|
||||
target=func,
|
||||
args=args,
|
||||
kwargs=kwds)
|
||||
@ -250,7 +250,7 @@ def formatExtendedTraceback(exc_info=None):
|
||||
linecache.checkcache(filename)
|
||||
line = linecache.getline(filename, tb.tb_lineno, frame.f_globals)
|
||||
if line:
|
||||
item = item + ' %s\n' % line.strip()
|
||||
item = item + f' {line.strip()}\n'
|
||||
ret.append(item)
|
||||
if filename not in ('<script>', '<string>'):
|
||||
ret += formatExtendedFrame(tb.tb_frame)
|
||||
@ -271,7 +271,7 @@ def formatExtendedStack(level=1):
|
||||
linecache.checkcache(filename)
|
||||
line = linecache.getline(filename, lineno, f.f_globals)
|
||||
if line:
|
||||
item = item + ' %s\n' % line.strip()
|
||||
item = item + f' {line.strip()}\n'
|
||||
ret.insert(1, item)
|
||||
if filename != '<script>':
|
||||
ret[2:2] = formatExtendedFrame(f)
|
||||
@ -317,10 +317,10 @@ def parseHostPort(host, defaultport):
|
||||
else:
|
||||
host, port = host
|
||||
if not HOSTNAMEPAT.match(host):
|
||||
raise ValueError('illegal host name %r' % host)
|
||||
raise ValueError(f'illegal host name {host!r}')
|
||||
if 0 < port < 65536:
|
||||
return host, port
|
||||
raise ValueError('illegal port number: %r' % port)
|
||||
raise ValueError(f'illegal port number: {port!r}')
|
||||
|
||||
|
||||
def tcpSocket(host, defaultport, timeout=None):
|
||||
|
@ -68,7 +68,7 @@ class AsynConn:
|
||||
if '/dev' in uri:
|
||||
raise ValueError("the correct uri for a serial port is: "
|
||||
"'serial:///dev/<tty>[?<option>=<value>[&<option>=value ...]]'") from None
|
||||
raise ValueError('invalid hostname %r' % uri) from None
|
||||
raise ValueError(f'invalid hostname {uri!r}') from None
|
||||
iocls = cls.SCHEME_MAP['tcp']
|
||||
return object.__new__(iocls)
|
||||
|
||||
@ -130,7 +130,7 @@ class AsynConn:
|
||||
if timeout:
|
||||
if time.time() < end:
|
||||
continue
|
||||
raise TimeoutError('timeout in readline (%g sec)' % timeout)
|
||||
raise TimeoutError(f'timeout in readline ({timeout:g} sec)')
|
||||
return None
|
||||
self._rxbuffer += data
|
||||
|
||||
@ -149,7 +149,7 @@ class AsynConn:
|
||||
if timeout:
|
||||
if time.time() < end:
|
||||
continue
|
||||
raise TimeoutError('timeout in readbytes (%g sec)' % timeout)
|
||||
raise TimeoutError(f'timeout in readbytes ({timeout:g} sec)')
|
||||
return None
|
||||
self._rxbuffer += data
|
||||
line = self._rxbuffer[:nbytes]
|
||||
@ -261,7 +261,7 @@ class AsynSerial(AsynConn):
|
||||
try:
|
||||
key, value = kv.split('=')
|
||||
except TypeError:
|
||||
raise ConfigError('%r must be <key>=<value>' % kv) from None
|
||||
raise ConfigError(f'{kv!r} must be <key>=<value>') from None
|
||||
if key == 'parity':
|
||||
options[key] = value
|
||||
else:
|
||||
@ -271,7 +271,7 @@ class AsynSerial(AsynConn):
|
||||
name = parity.upper()
|
||||
fullname = self.PARITY_NAMES[name[0]]
|
||||
if not fullname.startswith(name):
|
||||
raise ConfigError('illegal parity: %s' % parity)
|
||||
raise ConfigError(f'illegal parity: {parity}')
|
||||
options['parity'] = name[0]
|
||||
if 'timeout' not in options:
|
||||
options['timeout'] = self.timeout
|
||||
|
@ -37,8 +37,8 @@ def fmt_param(name, param):
|
||||
else:
|
||||
dtinfo = [short_doc(param.datatype), 'rd' if param.readonly else 'wr',
|
||||
None if param.export else 'hidden']
|
||||
dtinfo = '*(%s)* ' % ', '.join(filter(None, dtinfo))
|
||||
return '- **%s** - %s%s\n' % (name, dtinfo, desc)
|
||||
dtinfo = f"*({', '.join(filter(None, dtinfo))})* "
|
||||
return f'- **{name}** - {dtinfo}{desc}\n'
|
||||
|
||||
|
||||
def fmt_command(name, command):
|
||||
@ -46,8 +46,8 @@ def fmt_command(name, command):
|
||||
if '(' in desc[0:2]:
|
||||
dtinfo = '' # note: we expect that desc contains argument list
|
||||
else:
|
||||
dtinfo = '*%s*' % short_doc(command.datatype) + ' -%s ' % ('' if command.export else ' *(hidden)*')
|
||||
return '- **%s**\\ %s%s\n' % (name, dtinfo, desc)
|
||||
dtinfo = f'*{short_doc(command.datatype)}*' + f" -{'' if command.export else ' *(hidden)*'} "
|
||||
return f'- **{name}**\\ {dtinfo}{desc}\n'
|
||||
|
||||
|
||||
def fmt_property(name, prop):
|
||||
@ -58,8 +58,8 @@ def fmt_property(name, prop):
|
||||
dtinfo = [short_doc(prop.datatype), None if prop.export else 'hidden']
|
||||
dtinfo = ', '.join(filter(None, dtinfo))
|
||||
if dtinfo:
|
||||
dtinfo = '*(%s)* ' % dtinfo
|
||||
return '- **%s** - %s%s\n' % (name, dtinfo, desc)
|
||||
dtinfo = f'*({dtinfo})* '
|
||||
return f'- **{name}** - {dtinfo}{desc}\n'
|
||||
|
||||
|
||||
SIMPLETYPES = {
|
||||
@ -78,22 +78,22 @@ def short_doc(datatype, internal=False):
|
||||
# pylint: disable=possibly-unused-variable
|
||||
|
||||
def doc_EnumType(dt):
|
||||
return 'one of %s' % str(tuple(dt._enum.keys()))
|
||||
return f'one of {str(tuple(dt._enum.keys()))}'
|
||||
|
||||
def doc_ArrayOf(dt):
|
||||
return 'array of %s' % short_doc(dt.members, True)
|
||||
return f'array of {short_doc(dt.members, True)}'
|
||||
|
||||
def doc_TupleOf(dt):
|
||||
return 'tuple of (%s)' % ', '.join(short_doc(m, True) for m in dt.members)
|
||||
return f"tuple of ({', '.join(short_doc(m, True) for m in dt.members)})"
|
||||
|
||||
def doc_CommandType(dt):
|
||||
argument = short_doc(dt.argument, True) if dt.argument else ''
|
||||
result = ' -> %s' % short_doc(dt.result, True) if dt.result else ''
|
||||
return '(%s)%s' % (argument, result) # return argument list only
|
||||
result = f' -> {short_doc(dt.result, True)}' if dt.result else ''
|
||||
return f'({argument}){result}' # return argument list only
|
||||
|
||||
def doc_NoneOr(dt):
|
||||
other = short_doc(dt.other, True)
|
||||
return '%s or None' % other if other else None
|
||||
return f'{other} or None' if other else None
|
||||
|
||||
def doc_OrType(dt):
|
||||
types = [short_doc(t, True) for t in dt.types]
|
||||
@ -138,7 +138,7 @@ def append_to_doc(cls, lines, itemcls, name, attrname, fmtfunc):
|
||||
only the first appearance of a tag above is considered
|
||||
"""
|
||||
doc = '\n'.join(lines)
|
||||
title = 'SECoP %s' % name.title()
|
||||
title = f'SECoP {name.title()}'
|
||||
allitems = getattr(cls, attrname, {})
|
||||
fmtdict = {n: fmtfunc(n, p) for n, p in allitems.items() if isinstance(p, itemcls)}
|
||||
head, _, tail = doc.partition('{all %s}' % name)
|
||||
@ -177,7 +177,7 @@ def append_to_doc(cls, lines, itemcls, name, attrname, fmtfunc):
|
||||
fmted.append('- see also %s\n' % (', '.join(':class:`%s.%s`' % (c.__module__, c.__name__)
|
||||
for c in cls.__mro__ if c in clsset)))
|
||||
|
||||
doc = '%s\n\n:%s: %s\n\n%s' % (head, title, ' '.join(fmted), tail)
|
||||
doc = f"{head}\n\n:{title}: {' '.join(fmted)}\n\n{tail}"
|
||||
lines[:] = doc.split('\n')
|
||||
|
||||
|
||||
|
@ -315,16 +315,16 @@ class Enum(dict):
|
||||
|
||||
def __setattr__(self, key, value):
|
||||
if self.name and key != 'name':
|
||||
raise TypeError('Enum %r can not be changed!' % self.name)
|
||||
raise TypeError(f'Enum {self.name!r} can not be changed!')
|
||||
super().__setattr__(key, value)
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if self.name:
|
||||
raise TypeError('Enum %r can not be changed!' % self.name)
|
||||
raise TypeError(f'Enum {self.name!r} can not be changed!')
|
||||
super().__setitem__(key, value)
|
||||
|
||||
def __delitem__(self, key):
|
||||
raise TypeError('Enum %r can not be changed!' % self.name)
|
||||
raise TypeError(f'Enum {self.name!r} can not be changed!')
|
||||
|
||||
def __repr__(self):
|
||||
return 'Enum(%r, %s)' % (self.name, ', '.join('%s=%d' % (m.name, m.value) for m in self.members))
|
||||
|
@ -170,9 +170,9 @@ class SequencerMixin:
|
||||
result = step.func(store, *step.args)
|
||||
if self._seq_stopflag:
|
||||
if result:
|
||||
self._seq_stopped = 'stopped while %s' % step.desc
|
||||
self._seq_stopped = f'stopped while {step.desc}'
|
||||
else:
|
||||
self._seq_stopped = 'stopped after %s' % step.desc
|
||||
self._seq_stopped = f'stopped after {step.desc}'
|
||||
cleanup_func = step.kwds.get('cleanup', None)
|
||||
if callable(cleanup_func):
|
||||
try:
|
||||
@ -188,5 +188,5 @@ class SequencerMixin:
|
||||
except Exception as e:
|
||||
self.log.exception(
|
||||
'error in sequence step %r: %s', step.desc, e)
|
||||
self._seq_error = 'during %s: %s' % (step.desc, e)
|
||||
self._seq_error = f'during {step.desc}: {e}'
|
||||
break
|
||||
|
@ -121,7 +121,7 @@ class StateMachine:
|
||||
cls = type(self)
|
||||
for key, value in kwds.items():
|
||||
if hasattr(cls, key):
|
||||
raise AttributeError('can not set %s.%s' % (cls.__name__, key))
|
||||
raise AttributeError(f'can not set {cls.__name__}.{key}')
|
||||
setattr(self, key, value)
|
||||
|
||||
def _cleanup(self, reason):
|
||||
@ -181,8 +181,7 @@ class StateMachine:
|
||||
break
|
||||
if not callable(ret):
|
||||
ret = self._cleanup(RuntimeError(
|
||||
'%s: return value must be callable, Retry or Finish, not %r'
|
||||
% (self.statefunc.__name__, ret)))
|
||||
f'{self.statefunc.__name__}: return value must be callable, Retry or Finish, not {ret!r}'))
|
||||
except Exception as e:
|
||||
ret = self._cleanup(e)
|
||||
if ret is None:
|
||||
@ -190,7 +189,7 @@ class StateMachine:
|
||||
self._new_state(ret)
|
||||
else:
|
||||
ret = self._cleanup(RuntimeError(
|
||||
'%s: too many states chained - probably infinite loop' % self.statefunc.__name__))
|
||||
f'{self.statefunc.__name__}: too many states chained - probably infinite loop'))
|
||||
if ret:
|
||||
self._new_state(ret)
|
||||
continue
|
||||
|
@ -47,7 +47,7 @@ def check_level(level):
|
||||
return level
|
||||
except KeyError:
|
||||
pass
|
||||
raise ValueError('%r is not a valid level' % level)
|
||||
raise ValueError(f'{level!r} is not a valid level')
|
||||
|
||||
|
||||
class RemoteLogHandler(mlzlog.Handler):
|
||||
@ -113,7 +113,7 @@ class ComLogfileHandler(LogfileHandler):
|
||||
"""handler for logging communication"""
|
||||
|
||||
def format(self, record):
|
||||
return '%s %s' % (self.formatter.formatTime(record), record.getMessage())
|
||||
return f'{self.formatter.formatTime(record)} {record.getMessage()}'
|
||||
|
||||
|
||||
class HasComlog:
|
||||
@ -125,7 +125,7 @@ class HasComlog:
|
||||
def earlyInit(self):
|
||||
super().earlyInit()
|
||||
if self.comlog and generalConfig.initialized and generalConfig.comlog:
|
||||
self._comLog = mlzlog.Logger('COMLOG.%s' % self.name)
|
||||
self._comLog = mlzlog.Logger(f'COMLOG.{self.name}')
|
||||
self._comLog.handlers[:] = []
|
||||
directory = join(logger.logdir, logger.rootname, 'comlog', self.DISPATCHER.name)
|
||||
self._comLog.addHandler(ComLogfileHandler(
|
||||
|
@ -135,7 +135,7 @@ class HasAccessibles(HasProperties):
|
||||
except Exception as e:
|
||||
self.log.debug("read_%s failed with %r", pname, e)
|
||||
if isinstance(e, SECoPError):
|
||||
e.raising_methods.append('%s.read_%s' % (self.name, pname))
|
||||
e.raising_methods.append(f'{self.name}.read_{pname}')
|
||||
self.announceUpdate(pname, err=e)
|
||||
raise
|
||||
self.announceUpdate(pname, value, validate=False)
|
||||
@ -190,7 +190,7 @@ class HasAccessibles(HasProperties):
|
||||
new_value = value if new_value is None else validate(new_value)
|
||||
except Exception as e:
|
||||
if isinstance(e, SECoPError):
|
||||
e.raising_methods.append('%s.write_%s' % (self.name, pname))
|
||||
e.raising_methods.append(f'{self.name}.write_{pname}')
|
||||
self.announceUpdate(pname, err=e)
|
||||
raise
|
||||
self.announceUpdate(pname, new_value, validate=False)
|
||||
@ -209,11 +209,9 @@ class HasAccessibles(HasProperties):
|
||||
if not pname:
|
||||
continue
|
||||
if prefix == 'do':
|
||||
raise ProgrammingError('%r: old style command %r not supported anymore'
|
||||
% (cls.__name__, attrname))
|
||||
raise ProgrammingError(f'{cls.__name__!r}: old style command {attrname!r} not supported anymore')
|
||||
if prefix in ('read', 'write') and attrname not in cls.checkedMethods:
|
||||
raise ProgrammingError('%s.%s defined, but %r is no parameter'
|
||||
% (cls.__name__, attrname, pname))
|
||||
raise ProgrammingError(f'{cls.__name__}.{attrname} defined, but {pname!r} is no parameter')
|
||||
|
||||
try:
|
||||
# update Status type
|
||||
@ -368,12 +366,11 @@ class Module(HasAccessibles):
|
||||
else:
|
||||
self.setProperty(key, value)
|
||||
except BadValueError:
|
||||
errors.append('%s: value %r does not match %r!' %
|
||||
(key, value, self.propertyDict[key].datatype))
|
||||
errors.append(f'{key}: value {value!r} does not match {self.propertyDict[key].datatype!r}!')
|
||||
|
||||
# 3) set automatic properties
|
||||
mycls, = self.__class__.__bases__ # skip the wrapper class
|
||||
myclassname = '%s.%s' % (mycls.__module__, mycls.__name__)
|
||||
myclassname = f'{mycls.__module__}.{mycls.__name__}'
|
||||
self.implementation = myclassname
|
||||
# list of all 'secop' modules
|
||||
# self.interface_classes = [
|
||||
@ -416,20 +413,16 @@ class Module(HasAccessibles):
|
||||
for propname, propvalue in cfg.items():
|
||||
aobj.setProperty(propname, propvalue)
|
||||
except KeyError:
|
||||
errors.append("'%s' has no property '%s'" %
|
||||
(aname, propname))
|
||||
errors.append(f"'{aname}' has no property '{propname}'")
|
||||
except BadValueError as e:
|
||||
errors.append('%s.%s: %s' %
|
||||
(aname, propname, str(e)))
|
||||
errors.append(f'{aname}.{propname}: {str(e)}')
|
||||
else:
|
||||
bad.append(aname)
|
||||
|
||||
# 3) complain about names not found as accessible or property names
|
||||
if bad:
|
||||
errors.append(
|
||||
'%s does not exist (use one of %s)' %
|
||||
(', '.join(bad), ', '.join(list(self.accessibles) +
|
||||
list(self.propertyDict))))
|
||||
f"{', '.join(bad)} does not exist (use one of {', '.join(list(self.accessibles) + list(self.propertyDict))})")
|
||||
# 4) register value for writing, if given
|
||||
# apply default when no value is given (in cfg or as Parameter argument)
|
||||
# or complain, when cfg is needed
|
||||
@ -441,13 +434,13 @@ class Module(HasAccessibles):
|
||||
if not pobj.hasDatatype():
|
||||
head, _, postfix = pname.rpartition('_')
|
||||
if postfix not in ('min', 'max', 'limits'):
|
||||
errors.append('%s needs a datatype' % pname)
|
||||
errors.append(f'{pname} needs a datatype')
|
||||
continue
|
||||
# when datatype is not given, properties are set automagically
|
||||
pobj.setProperty('readonly', False)
|
||||
baseparam = self.parameters.get(head)
|
||||
if not baseparam:
|
||||
errors.append('parameter %r is given, but not %r' % (pname, head))
|
||||
errors.append(f'parameter {pname!r} is given, but not {head!r}')
|
||||
continue
|
||||
dt = baseparam.datatype
|
||||
if dt is None:
|
||||
@ -459,16 +452,15 @@ class Module(HasAccessibles):
|
||||
pobj.setProperty('datatype', dt)
|
||||
pobj.setProperty('default', getattr(dt, postfix))
|
||||
if not pobj.description:
|
||||
pobj.setProperty('description', 'limit for %s' % pname)
|
||||
pobj.setProperty('description', f'limit for {pname}')
|
||||
|
||||
if pobj.value is None:
|
||||
if pobj.needscfg:
|
||||
errors.append('%r has no default '
|
||||
'value and was not given in config!' % pname)
|
||||
errors.append(f'{pname!r} has no default value and was not given in config!')
|
||||
if pobj.default is None:
|
||||
# we do not want to call the setter for this parameter for now,
|
||||
# this should happen on the first read
|
||||
pobj.readerror = ConfigError('parameter %r not initialized' % pname)
|
||||
pobj.readerror = ConfigError(f'parameter {pname!r} not initialized')
|
||||
# above error will be triggered on activate after startup,
|
||||
# when not all hardware parameters are read because of startup timeout
|
||||
pobj.default = pobj.datatype.default
|
||||
@ -504,7 +496,7 @@ class Module(HasAccessibles):
|
||||
try:
|
||||
aobj.checkProperties()
|
||||
except (ConfigError, ProgrammingError) as e:
|
||||
errors.append('%s: %s' % (aname, e))
|
||||
errors.append(f'{aname}: {e}')
|
||||
if errors:
|
||||
raise ConfigError(errors)
|
||||
|
||||
@ -832,8 +824,8 @@ class Module(HasAccessibles):
|
||||
max_ = getattr(self, parametername + '_max', float('inf'))
|
||||
if not min_ <= value <= max_:
|
||||
if min_ > max_:
|
||||
raise RangeError('invalid limits: [%g, %g]' % (min_, max_))
|
||||
raise RangeError('limits violation: %g outside [%g, %g]' % (value, min_, max_))
|
||||
raise RangeError(f'invalid limits: [{min_:g}, {max_:g}]')
|
||||
raise RangeError(f'limits violation: {value:g} outside [{min_:g}, {max_:g}]')
|
||||
|
||||
|
||||
class Readable(Module):
|
||||
|
@ -92,8 +92,8 @@ class Accessible(HasProperties):
|
||||
def __repr__(self):
|
||||
props = []
|
||||
for k, v in sorted(self.propertyValues.items()):
|
||||
props.append('%s=%r' % (k, v))
|
||||
return '%s(%s)' % (self.__class__.__name__, ', '.join(props))
|
||||
props.append(f'{k}={v!r}')
|
||||
return f"{self.__class__.__name__}({', '.join(props)})"
|
||||
|
||||
|
||||
class Parameter(Accessible):
|
||||
@ -227,7 +227,7 @@ class Parameter(Accessible):
|
||||
elif predefined_cls is None:
|
||||
self.export = '_' + self.name
|
||||
else:
|
||||
raise ProgrammingError('can not use %r as name of a Parameter' % self.name)
|
||||
raise ProgrammingError(f'can not use {self.name!r} as name of a Parameter')
|
||||
if 'export' in self.ownProperties:
|
||||
# avoid export=True overrides export=<name>
|
||||
self.ownProperties['export'] = self.export
|
||||
@ -317,10 +317,9 @@ class Parameter(Accessible):
|
||||
try:
|
||||
self.datatype.setProperty(key, value)
|
||||
except KeyError:
|
||||
raise ProgrammingError('cannot set %s on parameter with datatype %s'
|
||||
% (key, type(self.datatype).__name__)) from None
|
||||
raise ProgrammingError(f'cannot set {key} on parameter with datatype {type(self.datatype).__name__}') from None
|
||||
except BadValueError as e:
|
||||
raise ProgrammingError('property %s: %s' % (key, str(e))) from None
|
||||
raise ProgrammingError(f'property {key}: {str(e)}') from None
|
||||
|
||||
def checkProperties(self):
|
||||
super().checkProperties()
|
||||
@ -395,8 +394,7 @@ class Command(Accessible):
|
||||
def __set_name__(self, owner, name):
|
||||
self.name = name
|
||||
if self.func is None:
|
||||
raise ProgrammingError('Command %s.%s must be used as a method decorator' %
|
||||
(owner.__name__, name))
|
||||
raise ProgrammingError(f'Command {owner.__name__}.{name} must be used as a method decorator')
|
||||
|
||||
self.datatype = CommandType(self.argument, self.result)
|
||||
if self.export is True:
|
||||
@ -406,7 +404,7 @@ class Command(Accessible):
|
||||
elif predefined_cls is None:
|
||||
self.export = '_' + name
|
||||
else:
|
||||
raise ProgrammingError('can not use %r as name of a Command' % name) from None
|
||||
raise ProgrammingError(f'can not use {name!r} as name of a Command') from None
|
||||
if 'export' in self.ownProperties:
|
||||
# avoid export=True overrides export=<name>
|
||||
self.ownProperties['export'] = self.export
|
||||
@ -419,7 +417,7 @@ class Command(Accessible):
|
||||
if obj is None:
|
||||
return self
|
||||
if not self.func:
|
||||
raise ProgrammingError('Command %s not properly configured' % self.name) from None
|
||||
raise ProgrammingError(f'Command {self.name} not properly configured') from None
|
||||
return self.func.__get__(obj, owner)
|
||||
|
||||
def __call__(self, func):
|
||||
@ -452,7 +450,7 @@ class Command(Accessible):
|
||||
|
||||
this is needed when the @Command is missing on a method overriding a command"""
|
||||
if not callable(value):
|
||||
raise ProgrammingError('%s = %r is overriding a Command' % (self.name, value))
|
||||
raise ProgrammingError(f'{self.name} = {value!r} is overriding a Command')
|
||||
self.func = value
|
||||
if value.__doc__:
|
||||
self.description = inspect.cleandoc(value.__doc__)
|
||||
@ -478,7 +476,7 @@ class Command(Accessible):
|
||||
super().setProperty('result', command.result)
|
||||
super().setProperty(key, value)
|
||||
except ValueError as e:
|
||||
raise ProgrammingError('property %s: %s' % (key, str(e))) from None
|
||||
raise ProgrammingError(f'property {key}: {str(e)}') from None
|
||||
|
||||
def do(self, module_obj, argument):
|
||||
"""perform function call
|
||||
@ -504,7 +502,7 @@ class Command(Accessible):
|
||||
res = func(argument)
|
||||
else:
|
||||
if argument is not None:
|
||||
raise WrongTypeError('%s.%s takes no arguments' % (module_obj.__class__.__name__, self.name))
|
||||
raise WrongTypeError(f'{module_obj.__class__.__name__}.{self.name} takes no arguments')
|
||||
res = func()
|
||||
if self.result:
|
||||
return self.result(res)
|
||||
@ -515,7 +513,7 @@ class Command(Accessible):
|
||||
|
||||
def __repr__(self):
|
||||
result = super().__repr__()
|
||||
return result[:-1] + ', %r)' % self.func if self.func else result
|
||||
return result[:-1] + f', {self.func!r})' if self.func else result
|
||||
|
||||
|
||||
# list of predefined accessibles with their type
|
||||
|
@ -111,7 +111,7 @@ class Parser:
|
||||
return None, text
|
||||
res, rem = self.parse_sub(text)
|
||||
if res is None:
|
||||
print('remtuple %r %r %r' % (rem, text, bra))
|
||||
print(f'remtuple {rem!r} {text!r} {bra!r}')
|
||||
if rem[0] == bra:
|
||||
# allow trailing separator
|
||||
return tuple(reslist), rem[1:].strip()
|
||||
@ -175,5 +175,5 @@ class Parser:
|
||||
def parse(self, orgtext):
|
||||
res, rem = self.parse_sub(orgtext)
|
||||
if rem and rem[0] in ',;':
|
||||
return self.parse_sub('[%s]' % orgtext)
|
||||
return self.parse_sub(f'[{orgtext}]')
|
||||
return res, rem
|
||||
|
@ -74,7 +74,7 @@ class PersistentMixin(Module):
|
||||
super().__init__(name, logger, cfgdict, srv)
|
||||
persistentdir = os.path.join(generalConfig.logdir, 'persistent')
|
||||
os.makedirs(persistentdir, exist_ok=True)
|
||||
self.persistentFile = os.path.join(persistentdir, '%s.%s.json' % (self.DISPATCHER.equipment_id, self.name))
|
||||
self.persistentFile = os.path.join(persistentdir, f'{self.DISPATCHER.equipment_id}.{self.name}.json')
|
||||
self.initData = {} # "factory" settings
|
||||
loaded = self.loadPersistentData()
|
||||
for pname in self.parameters:
|
||||
|
@ -39,7 +39,7 @@ class HasDescriptors(Object):
|
||||
bad = [k for k, v in cls.__dict__.items()
|
||||
if isinstance(v, tuple) and len(v) == 1 and hasattr(v[0], '__set_name__')]
|
||||
if bad:
|
||||
raise ProgrammingError('misplaced trailing comma after %s.%s' % (cls.__name__, '/'.join(bad)))
|
||||
raise ProgrammingError(f"misplaced trailing comma after {cls.__name__}.{'/'.join(bad)}")
|
||||
|
||||
|
||||
# storage for 'properties of a property'
|
||||
@ -94,19 +94,19 @@ class Property:
|
||||
return type(self)(**self.__dict__)
|
||||
|
||||
def __repr__(self):
|
||||
extras = ['default=%s' % repr(self.default)]
|
||||
extras = [f'default={repr(self.default)}']
|
||||
if self.export:
|
||||
extras.append('extname=%r' % self.extname)
|
||||
extras.append('export=%r' % self.export)
|
||||
extras.append(f'extname={self.extname!r}')
|
||||
extras.append(f'export={self.export!r}')
|
||||
if self.mandatory:
|
||||
extras.append('mandatory=True')
|
||||
if not self.settable:
|
||||
extras.append('settable=False')
|
||||
if self.value is not UNSET:
|
||||
extras.append('value=%s' % repr(self.value))
|
||||
extras.append(f'value={repr(self.value)}')
|
||||
if not self.name:
|
||||
extras.append('name=%r' % self.name)
|
||||
return 'Property(%r, %s, %s)' % (self.description, self.datatype, ', '.join(extras))
|
||||
extras.append(f'name={self.name!r}')
|
||||
return f"Property({self.description!r}, {self.datatype}, {', '.join(extras)})"
|
||||
|
||||
|
||||
class HasProperties(HasDescriptors):
|
||||
@ -147,10 +147,8 @@ class HasProperties(HasDescriptors):
|
||||
po.value = po.datatype.validate(value)
|
||||
except BadValueError:
|
||||
if callable(value):
|
||||
raise ProgrammingError('method %s.%s collides with property of %s' %
|
||||
(cls.__name__, pn, base.__name__)) from None
|
||||
raise ProgrammingError('can not set property %s.%s to %r' %
|
||||
(cls.__name__, pn, value)) from None
|
||||
raise ProgrammingError(f'method {cls.__name__}.{pn} collides with property of {base.__name__}') from None
|
||||
raise ProgrammingError(f'can not set property {cls.__name__}.{pn} to {value!r}') from None
|
||||
cls.propertyDict[pn] = po
|
||||
|
||||
def checkProperties(self):
|
||||
@ -160,14 +158,14 @@ class HasProperties(HasDescriptors):
|
||||
try:
|
||||
self.propertyValues[pn] = po.datatype.validate(self.propertyValues[pn])
|
||||
except (KeyError, BadValueError):
|
||||
raise ConfigError('%s needs a value of type %r!' % (pn, po.datatype)) from None
|
||||
raise ConfigError(f'{pn} needs a value of type {po.datatype!r}!') from None
|
||||
for pn, po in self.propertyDict.items():
|
||||
if pn.startswith('min'):
|
||||
maxname = 'max' + pn[3:]
|
||||
minval = self.propertyValues.get(pn, po.default)
|
||||
maxval = self.propertyValues.get(maxname, minval)
|
||||
if minval > maxval:
|
||||
raise ConfigError('%s=%r must be <= %s=%r for %r' % (pn, minval, maxname, maxval, self))
|
||||
raise ConfigError(f'{pn}={minval!r} must be <= {maxname}={maxval!r} for {self!r}')
|
||||
|
||||
def getProperties(self):
|
||||
return self.propertyDict
|
||||
|
@ -53,10 +53,10 @@ from frappy.protocol.messages import COMMANDREPLY, DESCRIPTIONREPLY, \
|
||||
|
||||
def make_update(modulename, pobj):
|
||||
if pobj.readerror:
|
||||
return (ERRORPREFIX + EVENTREPLY, '%s:%s' % (modulename, pobj.export),
|
||||
return (ERRORPREFIX + EVENTREPLY, f'{modulename}:{pobj.export}',
|
||||
# error-report !
|
||||
[pobj.readerror.name, str(pobj.readerror), {'t': pobj.timestamp}])
|
||||
return (EVENTREPLY, '%s:%s' % (modulename, pobj.export),
|
||||
return (EVENTREPLY, f'{modulename}:{pobj.export}',
|
||||
[pobj.export_value(), {'t': pobj.timestamp}])
|
||||
|
||||
|
||||
@ -114,7 +114,7 @@ class Dispatcher:
|
||||
if ':' not in eventname:
|
||||
# also remove 'more specific' subscriptions
|
||||
for k, v in self._subscriptions.items():
|
||||
if k.startswith('%s:' % eventname):
|
||||
if k.startswith(f'{eventname}:'):
|
||||
v.discard(conn)
|
||||
if eventname in self._subscriptions:
|
||||
self._subscriptions[eventname].discard(conn)
|
||||
@ -151,7 +151,7 @@ class Dispatcher:
|
||||
return self._modules[modulename]
|
||||
if modulename in list(self._modules.values()):
|
||||
return modulename
|
||||
raise NoSuchModuleError('Module %r does not exist on this SEC-Node!' % modulename)
|
||||
raise NoSuchModuleError(f'Module {modulename!r} does not exist on this SEC-Node!')
|
||||
|
||||
def remove_module(self, modulename_or_obj):
|
||||
moduleobj = self.get_module(modulename_or_obj)
|
||||
@ -160,7 +160,7 @@ class Dispatcher:
|
||||
self._export.remove(modulename)
|
||||
self._modules.pop(modulename)
|
||||
self._subscriptions.pop(modulename, None)
|
||||
for k in [kk for kk in self._subscriptions if kk.startswith('%s:' % modulename)]:
|
||||
for k in [kk for kk in self._subscriptions if kk.startswith(f'{modulename}:')]:
|
||||
self._subscriptions.pop(k, None)
|
||||
|
||||
def list_module_names(self):
|
||||
@ -201,25 +201,25 @@ class Dispatcher:
|
||||
# command is also accepted
|
||||
result = result['accessibles'][pname]
|
||||
elif pname:
|
||||
raise NoSuchParameterError('Module %r has no parameter %r' % (modname, pname))
|
||||
raise NoSuchParameterError(f'Module {modname!r} has no parameter {pname!r}')
|
||||
elif not modname or modname == '.':
|
||||
result['equipment_id'] = self.equipment_id
|
||||
result['firmware'] = 'FRAPPY - The Python Framework for SECoP'
|
||||
result['version'] = '2021.02'
|
||||
result.update(self.nodeprops)
|
||||
else:
|
||||
raise NoSuchModuleError('Module %r does not exist' % modname)
|
||||
raise NoSuchModuleError(f'Module {modname!r} does not exist')
|
||||
return result
|
||||
|
||||
def _execute_command(self, modulename, exportedname, argument=None):
|
||||
moduleobj = self.get_module(modulename)
|
||||
if moduleobj is None:
|
||||
raise NoSuchModuleError('Module %r does not exist' % modulename)
|
||||
raise NoSuchModuleError(f'Module {modulename!r} does not exist')
|
||||
|
||||
cname = moduleobj.accessiblename2attr.get(exportedname)
|
||||
cobj = moduleobj.commands.get(cname)
|
||||
if cobj is None:
|
||||
raise NoSuchCommandError('Module %r has no command %r' % (modulename, cname or exportedname))
|
||||
raise NoSuchCommandError(f'Module {modulename!r} has no command {cname or exportedname!r}')
|
||||
|
||||
if cobj.argument:
|
||||
argument = cobj.argument.import_value(argument)
|
||||
@ -233,18 +233,16 @@ class Dispatcher:
|
||||
def _setParameterValue(self, modulename, exportedname, value):
|
||||
moduleobj = self.get_module(modulename)
|
||||
if moduleobj is None:
|
||||
raise NoSuchModuleError('Module %r does not exist' % modulename)
|
||||
raise NoSuchModuleError(f'Module {modulename!r} does not exist')
|
||||
|
||||
pname = moduleobj.accessiblename2attr.get(exportedname)
|
||||
pobj = moduleobj.parameters.get(pname)
|
||||
if pobj is None:
|
||||
raise NoSuchParameterError('Module %r has no parameter %r' % (modulename, pname or exportedname))
|
||||
raise NoSuchParameterError(f'Module {modulename!r} has no parameter {pname or exportedname!r}')
|
||||
if pobj.constant is not None:
|
||||
raise ReadOnlyError("Parameter %s:%s is constant and can not be changed remotely"
|
||||
% (modulename, pname))
|
||||
raise ReadOnlyError(f"Parameter {modulename}:{pname} is constant and can not be changed remotely")
|
||||
if pobj.readonly:
|
||||
raise ReadOnlyError("Parameter %s:%s can not be changed remotely"
|
||||
% (modulename, pname))
|
||||
raise ReadOnlyError(f"Parameter {modulename}:{pname} can not be changed remotely")
|
||||
|
||||
# validate!
|
||||
value = pobj.datatype.validate(value, previous=pobj.value)
|
||||
@ -256,12 +254,12 @@ class Dispatcher:
|
||||
def _getParameterValue(self, modulename, exportedname):
|
||||
moduleobj = self.get_module(modulename)
|
||||
if moduleobj is None:
|
||||
raise NoSuchModuleError('Module %r does not exist' % modulename)
|
||||
raise NoSuchModuleError(f'Module {modulename!r} does not exist')
|
||||
|
||||
pname = moduleobj.accessiblename2attr.get(exportedname)
|
||||
pobj = moduleobj.parameters.get(pname)
|
||||
if pobj is None:
|
||||
raise NoSuchParameterError('Module %r has no parameter %r' % (modulename, pname or exportedname))
|
||||
raise NoSuchParameterError(f'Module {modulename!r} has no parameter {pname or exportedname!r}')
|
||||
if pobj.constant is not None:
|
||||
# really needed? we could just construct a readreply instead....
|
||||
# raise ReadOnlyError('This parameter is constant and can not be accessed remotely.')
|
||||
@ -293,11 +291,11 @@ class Dispatcher:
|
||||
action, specifier, data = '_ident', None, None
|
||||
|
||||
self.log.debug('Looking for handle_%s', action)
|
||||
handler = getattr(self, 'handle_%s' % action, None)
|
||||
handler = getattr(self, f'handle_{action}', None)
|
||||
|
||||
if handler:
|
||||
return handler(conn, specifier, data)
|
||||
raise ProtocolError('unhandled message: %s' % repr(msg))
|
||||
raise ProtocolError(f'unhandled message: {repr(msg)}')
|
||||
|
||||
# now the (defined) handlers for the different requests
|
||||
def handle_help(self, conn, specifier, data):
|
||||
@ -351,13 +349,13 @@ class Dispatcher:
|
||||
if ':' in specifier:
|
||||
modulename, exportedname = specifier.split(':', 1)
|
||||
if modulename not in self._export:
|
||||
raise NoSuchModuleError('Module %r does not exist' % modulename)
|
||||
raise NoSuchModuleError(f'Module {modulename!r} does not exist')
|
||||
moduleobj = self.get_module(modulename)
|
||||
if exportedname is not None:
|
||||
pname = moduleobj.accessiblename2attr.get(exportedname, True)
|
||||
if pname and pname not in moduleobj.accessibles:
|
||||
# what if we try to subscribe a command here ???
|
||||
raise NoSuchParameterError('Module %r has no parameter %r' % (modulename, pname))
|
||||
raise NoSuchParameterError(f'Module {modulename!r} has no parameter {pname!r}')
|
||||
modules = [(modulename, pname)]
|
||||
else:
|
||||
modules = [(modulename, None)]
|
||||
@ -392,7 +390,7 @@ class Dispatcher:
|
||||
|
||||
def send_log_msg(self, conn, modname, level, msg):
|
||||
"""send log message """
|
||||
conn.send_reply((LOG_EVENT, '%s:%s' % (modname, level), msg))
|
||||
conn.send_reply((LOG_EVENT, f'{modname}:{level}', msg))
|
||||
|
||||
def set_all_log_levels(self, conn, level):
|
||||
for modobj in self._modules.values():
|
||||
|
@ -88,17 +88,14 @@ REQUEST2REPLY = {
|
||||
}
|
||||
|
||||
|
||||
HelpMessage = """Try one of the following:
|
||||
'%s' to query protocol version
|
||||
'%s' to read the description
|
||||
'%s <module>[:<parameter>]' to request reading a value
|
||||
'%s <module>[:<parameter>] value' to request changing a value
|
||||
'%s <module>[:<command>]' to execute a command
|
||||
'%s <nonce>' to request a heartbeat response
|
||||
'%s' to activate async updates
|
||||
'%s' to deactivate updates
|
||||
'%s [<module>] <loglevel>' to activate logging events
|
||||
""" % (IDENTREQUEST, DESCRIPTIONREQUEST, READREQUEST,
|
||||
WRITEREQUEST, COMMANDREQUEST, HEARTBEATREQUEST,
|
||||
ENABLEEVENTSREQUEST, DISABLEEVENTSREQUEST,
|
||||
LOGGING_REQUEST)
|
||||
HelpMessage = f"""Try one of the following:
|
||||
'{IDENTREQUEST}' to query protocol version
|
||||
'{DESCRIPTIONREQUEST}' to read the description
|
||||
'{READREQUEST} <module>[:<parameter>]' to request reading a value
|
||||
'{WRITEREQUEST} <module>[:<parameter>] value' to request changing a value
|
||||
'{COMMANDREQUEST} <module>[:<command>]' to execute a command
|
||||
'{HEARTBEATREQUEST} <nonce>' to request a heartbeat response
|
||||
'{ENABLEEVENTSREQUEST}' to activate async updates
|
||||
'{DISABLEEVENTSREQUEST}' to deactivate updates
|
||||
'{LOGGING_REQUEST} [<module>] <loglevel>' to activate logging events
|
||||
"""
|
||||
|
@ -55,11 +55,11 @@ class SecopClient(frappy.client.SecopClient):
|
||||
return name
|
||||
|
||||
def updateEvent(self, module, parameter, value, timestamp, readerror):
|
||||
specifier = '%s:%s' % (module, parameter)
|
||||
specifier = f'{module}:{parameter}'
|
||||
if readerror:
|
||||
msg = ERRORPREFIX + EVENTREPLY, specifier, (readerror.name, str(readerror), dict(t=timestamp))
|
||||
msg = ERRORPREFIX + EVENTREPLY, specifier, (readerror.name, str(readerror), {'t': timestamp})
|
||||
else:
|
||||
msg = EVENTREPLY, specifier, (value, dict(t=timestamp))
|
||||
msg = EVENTREPLY, specifier, (value, {'t': timestamp})
|
||||
self.dispatcher.broadcast_event(msg)
|
||||
|
||||
def nodeStateChange(self, online, state):
|
||||
@ -74,7 +74,7 @@ class SecopClient(frappy.client.SecopClient):
|
||||
if module is None:
|
||||
self.dispatcher.restart()
|
||||
self._shutdown = True
|
||||
raise frappy.errors.SECoPError('descriptive data for node %r has changed' % self.nodename)
|
||||
raise frappy.errors.SECoPError(f'descriptive data for node {self.nodename!r} has changed')
|
||||
|
||||
|
||||
class Router(frappy.protocol.dispatcher.Dispatcher):
|
||||
@ -139,7 +139,7 @@ class Router(frappy.protocol.dispatcher.Dispatcher):
|
||||
data = node.descriptive_data.copy()
|
||||
modules = data.pop('modules')
|
||||
equipment_id = data.pop('equipment_id', 'unknown')
|
||||
node_description.append('--- %s ---\n%s' % (equipment_id, data.pop('description', '')))
|
||||
node_description.append(f"--- {equipment_id} ---\n{data.pop('description', '')}")
|
||||
node_description.append('\n'.join('%s: %r' % kv for kv in data.items()))
|
||||
for modname, moddesc in modules.items():
|
||||
if modname in allmodules:
|
||||
@ -154,12 +154,12 @@ class Router(frappy.protocol.dispatcher.Dispatcher):
|
||||
super().handle_activate(conn, specifier, data)
|
||||
for node in self.nodes:
|
||||
for (module, parameter), (value, t, readerror) in node.cache.items():
|
||||
spec = '%s:%s' % (module, parameter)
|
||||
spec = f'{module}:{parameter}'
|
||||
if readerror:
|
||||
reply = ERRORPREFIX + EVENTREPLY, spec, (readerror.name, str(readerror), dict(t=t))
|
||||
reply = ERRORPREFIX + EVENTREPLY, spec, (readerror.name, str(readerror), {'t': t})
|
||||
else:
|
||||
datatype = node.modules[module]['parameters'][parameter]['datatype']
|
||||
reply = EVENTREPLY, spec, [datatype.export_value(value), dict(t=t)]
|
||||
reply = EVENTREPLY, spec, [datatype.export_value(value), {'t': t}]
|
||||
self.broadcast_event(reply)
|
||||
return ENABLEEVENTSREPLY, None, None
|
||||
|
||||
@ -175,7 +175,7 @@ class Router(frappy.protocol.dispatcher.Dispatcher):
|
||||
node = self.node_by_module[module]
|
||||
if node.online:
|
||||
return node.request(READREQUEST, specifier, data)
|
||||
return ERRORPREFIX + READREQUEST, specifier, SecopClient.disconnectedError + (dict(t=node.disconnect_time),)
|
||||
return ERRORPREFIX + READREQUEST, specifier, SecopClient.disconnectedError + ({'t': node.disconnect_time},)
|
||||
|
||||
def handle_change(self, conn, specifier, data):
|
||||
module = specifier.split(':')[0]
|
||||
|
@ -40,7 +40,7 @@ class ProxyModule(HasIO, Module):
|
||||
enablePoll = False
|
||||
|
||||
def ioClass(self, name, logger, opts, srv):
|
||||
opts['description'] = 'secnode %s on %s' % (opts.get('module', name), opts['uri'])
|
||||
opts['description'] = f"secnode {opts.get('module', name)} on {opts['uri']}"
|
||||
return SecNode(name, logger, opts, srv)
|
||||
|
||||
def updateEvent(self, module, parameter, value, timestamp, readerror):
|
||||
@ -179,7 +179,7 @@ def proxy_class(remote_class, name=None):
|
||||
proxycls.accessibles = {}
|
||||
break
|
||||
else:
|
||||
raise ConfigError('%r is no SECoP module class' % remote_class)
|
||||
raise ConfigError(f'{remote_class!r} is no SECoP module class')
|
||||
|
||||
attrs = rcls.propertyDict.copy()
|
||||
|
||||
@ -220,7 +220,7 @@ def proxy_class(remote_class, name=None):
|
||||
attrs[aname] = cobj(cfunc)
|
||||
|
||||
else:
|
||||
raise ConfigError('do not now about %r in %s.accessibles' % (aobj, remote_class))
|
||||
raise ConfigError(f'do not now about {aobj!r} in {remote_class}.accessibles')
|
||||
|
||||
return type(name+"_", (proxycls,), attrs)
|
||||
|
||||
@ -235,8 +235,6 @@ def Proxy(name, logger, cfgdict, srv):
|
||||
remote_class = remote_class['value']
|
||||
|
||||
if 'description' not in cfgdict:
|
||||
cfgdict['description'] = 'remote module %s on %s' % (
|
||||
cfgdict.get('module', name),
|
||||
cfgdict.get('io', {'value:': '?'})['value'])
|
||||
cfgdict['description'] = f"remote module {cfgdict.get('module', name)} on {cfgdict.get('io', {'value:': '?'})['value']}"
|
||||
|
||||
return proxy_class(remote_class)(name, logger, cfgdict, srv)
|
||||
|
@ -87,7 +87,7 @@ class Handler:
|
||||
if (func.__module__, func.__qualname__) in self.method_names:
|
||||
# make sure method name is not used twice
|
||||
# (else __set_name__ will not be called)
|
||||
raise ProgrammingError('duplicate method %r' % func.__qualname__)
|
||||
raise ProgrammingError(f'duplicate method {func.__qualname__!r}')
|
||||
self.func = func
|
||||
func.wrapped = False
|
||||
self.method_names.add((func.__module__, func.__qualname__))
|
||||
@ -113,8 +113,8 @@ class Handler:
|
||||
wrapped.poll = getattr(wrapped, 'poll', self.poll)
|
||||
func = getattr(owner, method_name, None)
|
||||
if func and method_name in owner.__dict__:
|
||||
raise ProgrammingError('superfluous method %s.%s (overwritten by %s)'
|
||||
% (owner.__name__, method_name, self.__class__.__name__))
|
||||
raise ProgrammingError(f'superfluous method {owner.__name__}.' \
|
||||
f'{method_name} (overwritten by {self.__class__.__name__})')
|
||||
setattr(owner, method_name, wrapped)
|
||||
|
||||
def wrap(self, key):
|
||||
|
@ -123,8 +123,7 @@ class Server:
|
||||
self.run()
|
||||
|
||||
def unknown_options(self, cls, options):
|
||||
return ("%s class don't know how to handle option(s): %s" %
|
||||
(cls.__name__, ', '.join(options)))
|
||||
return f"{cls.__name__} class don't know how to handle option(s): {', '.join(options)}"
|
||||
|
||||
def run(self):
|
||||
while self._restart:
|
||||
@ -189,24 +188,24 @@ class Server:
|
||||
cls = get_class(classname)
|
||||
except Exception as e:
|
||||
if str(e) == 'no such class':
|
||||
errors.append('%s not found' % classname)
|
||||
errors.append(f'{classname} not found')
|
||||
else:
|
||||
failed.add(pymodule)
|
||||
if failure_traceback is None:
|
||||
failure_traceback = traceback.format_exc()
|
||||
errors.append('error importing %s' % classname)
|
||||
errors.append(f'error importing {classname}')
|
||||
else:
|
||||
try:
|
||||
modobj = cls(modname, self.log.getChild(modname), opts, self)
|
||||
self.modules[modname] = modobj
|
||||
except ConfigError as e:
|
||||
errors.append('error creating module %s:' % modname)
|
||||
errors.append(f'error creating module {modname}:')
|
||||
for errtxt in e.args[0] if isinstance(e.args[0], list) else [e.args[0]]:
|
||||
errors.append(' ' + errtxt)
|
||||
except Exception:
|
||||
if failure_traceback is None:
|
||||
failure_traceback = traceback.format_exc()
|
||||
errors.append('error creating %s' % modname)
|
||||
errors.append(f'error creating {modname}')
|
||||
|
||||
missing_super = set()
|
||||
# all objs created, now start them up and interconnect
|
||||
@ -216,8 +215,7 @@ class Server:
|
||||
# also call earlyInit on the modules
|
||||
modobj.earlyInit()
|
||||
if not modobj.earlyInitDone:
|
||||
missing_super.add('%s was not called, probably missing super call'
|
||||
% modobj.earlyInit.__qualname__)
|
||||
missing_super.add(f'{modobj.earlyInit.__qualname__} was not called, probably missing super call')
|
||||
|
||||
# handle attached modules
|
||||
for modname, modobj in self.modules.items():
|
||||
@ -231,10 +229,10 @@ class Server:
|
||||
if isinstance(attobj, propobj.basecls):
|
||||
attached_modules[propname] = attobj
|
||||
else:
|
||||
errors.append('attached module %s=%r must inherit from %r'
|
||||
% (propname, attname, propobj.basecls.__qualname__))
|
||||
errors.append(f'attached module {propname}={attname!r} '\
|
||||
f'must inherit from {propobj.basecls.__qualname__!r}')
|
||||
except SECoPError as e:
|
||||
errors.append('module %s, attached %s: %s' % (modname, propname, str(e)))
|
||||
errors.append(f'module {modname}, attached {propname}: {str(e)}')
|
||||
modobj.attachedModules = attached_modules
|
||||
|
||||
# call init on each module after registering all
|
||||
@ -242,22 +240,20 @@ class Server:
|
||||
try:
|
||||
modobj.initModule()
|
||||
if not modobj.initModuleDone:
|
||||
missing_super.add('%s was not called, probably missing super call'
|
||||
% modobj.initModule.__qualname__)
|
||||
missing_super.add(f'{modobj.initModule.__qualname__} was not called, probably missing super call')
|
||||
except Exception as e:
|
||||
if failure_traceback is None:
|
||||
failure_traceback = traceback.format_exc()
|
||||
errors.append('error initializing %s: %r' % (modname, e))
|
||||
errors.append(f'error initializing {modname}: {e!r}')
|
||||
|
||||
if not self._testonly:
|
||||
start_events = MultiEvent(default_timeout=30)
|
||||
for modname, modobj in self.modules.items():
|
||||
# startModule must return either a timeout value or None (default 30 sec)
|
||||
start_events.name = 'module %s' % modname
|
||||
start_events.name = f'module {modname}'
|
||||
modobj.startModule(start_events)
|
||||
if not modobj.startModuleDone:
|
||||
missing_super.add('%s was not called, probably missing super call'
|
||||
% modobj.startModule.__qualname__)
|
||||
missing_super.add(f'{modobj.startModule.__qualname__} was not called, probably missing super call')
|
||||
errors.extend(missing_super)
|
||||
|
||||
if errors:
|
||||
|
@ -37,7 +37,7 @@ class SimBase:
|
||||
if extra_params:
|
||||
for k in extra_params['value'].split(','):
|
||||
k = k.strip()
|
||||
attrs[k] = Parameter('extra_param: %s' % k.strip(),
|
||||
attrs[k] = Parameter(f'extra_param: {k.strip()}',
|
||||
datatype=FloatRange(),
|
||||
default=0.0)
|
||||
|
||||
@ -54,7 +54,7 @@ class SimBase:
|
||||
|
||||
attrs['write_' + k] = writer
|
||||
|
||||
return object.__new__(type('SimBase_%s' % devname, (cls,), attrs))
|
||||
return object.__new__(type(f'SimBase_{devname}', (cls,), attrs))
|
||||
|
||||
def initModule(self):
|
||||
super().initModule()
|
||||
|
@ -85,11 +85,11 @@ class HasStates:
|
||||
if sm.next_task:
|
||||
if isinstance(sm.next_task, Stop):
|
||||
if newstate and status is not None:
|
||||
status = status[0], 'stopping (%s)' % status[1]
|
||||
status = status[0], f'stopping ({status[1]})'
|
||||
elif newstate:
|
||||
# restart case
|
||||
if status is not None:
|
||||
status = sm.status[0], 'restarting (%s)' % status[1]
|
||||
status = sm.status[0], f'restarting ({status[1]})'
|
||||
else:
|
||||
# start case
|
||||
status = self.get_status(sm.next_task.newstate, BUSY)
|
||||
|
@ -66,7 +66,7 @@ class Ls370Sim(Communicator):
|
||||
self._data['RDGST?%d' % channel] = '0'
|
||||
|
||||
def communicate(self, command):
|
||||
self.comLog('> %s' % command)
|
||||
self.comLog(f'> {command}')
|
||||
|
||||
chunks = command.split(';')
|
||||
reply = []
|
||||
@ -86,7 +86,7 @@ class Ls370Sim(Communicator):
|
||||
self.data[qcmd] = arg
|
||||
break
|
||||
reply = ';'.join(reply)
|
||||
self.comLog('< %s' % reply)
|
||||
self.comLog(f'< {reply}')
|
||||
return reply
|
||||
|
||||
|
||||
|
@ -74,7 +74,7 @@ class Switch(Drivable):
|
||||
|
||||
def write_target(self, value):
|
||||
# could tell HW
|
||||
self.status = (self.Status.BUSY, 'switching %s' % value.name.upper())
|
||||
self.status = (self.Status.BUSY, f'switching {value.name.upper()}')
|
||||
# note: setting self.target to the new value is done after this....
|
||||
|
||||
def read_status(self):
|
||||
@ -284,8 +284,7 @@ class Label(Readable):
|
||||
|
||||
dev_ts = self.DISPATCHER.get_module(self.subdev_ts)
|
||||
if dev_ts:
|
||||
strings.append('at %.3f %s' %
|
||||
(dev_ts.read_value(), dev_ts.parameters['value'].datatype.unit))
|
||||
strings.append(f"at {dev_ts.read_value():.3f} {dev_ts.parameters['value'].datatype.unit}")
|
||||
else:
|
||||
strings.append('No connection to sample temp!')
|
||||
|
||||
@ -299,7 +298,7 @@ class Label(Readable):
|
||||
state = 'Persistent' if mf_mode else 'Non-persistent'
|
||||
else:
|
||||
state = mf_stat[1] or 'ramping'
|
||||
strings.append('%s at %.1f %s' % (state, mf_val, mf_unit))
|
||||
strings.append(f'{state} at {mf_val:.1f} {mf_unit}')
|
||||
else:
|
||||
strings.append('No connection to magnetic field!')
|
||||
|
||||
|
@ -117,8 +117,7 @@ class GarfieldMagnet(SequencerMixin, Drivable):
|
||||
minfield = -maxfield
|
||||
if not minfield <= field <= maxfield:
|
||||
raise ValueError(self,
|
||||
'requested field %g T out of range %g..%g T' %
|
||||
(field, minfield, maxfield))
|
||||
f'requested field {field:g} T out of range {minfield:g}..{maxfield:g} T')
|
||||
while minfield <= field <= maxfield:
|
||||
# binary search
|
||||
trycurr = 0.5 * (mincurr + maxcurr)
|
||||
@ -171,8 +170,7 @@ class GarfieldMagnet(SequencerMixin, Drivable):
|
||||
amin, amax = self.abslimits
|
||||
if umin > umax:
|
||||
raise ValueError(
|
||||
self, 'user minimum (%s) above the user '
|
||||
'maximum (%s)' % (umin, umax))
|
||||
self, f'user minimum ({umin}) above the user maximum ({umax})')
|
||||
if umin < amin - abs(amin * 1e-12):
|
||||
umin = amin
|
||||
if umax > amax + abs(amax * 1e-12):
|
||||
@ -265,16 +263,13 @@ class GarfieldMagnet(SequencerMixin, Drivable):
|
||||
cleanup=self._ramp_current_cleanup))
|
||||
seq.append(
|
||||
Step(
|
||||
'set polarity %s' %
|
||||
wanted_polarity,
|
||||
f'set polarity {wanted_polarity}',
|
||||
0.3,
|
||||
self._set_polarity,
|
||||
wanted_polarity)) # no cleanup
|
||||
seq.append(
|
||||
Step(
|
||||
'ramping to %.3fT (%.2fA)' %
|
||||
(target,
|
||||
wanted_current),
|
||||
f'ramping to {target:.3f}T ({wanted_current:.2f}A)',
|
||||
0.3,
|
||||
self._ramp_current,
|
||||
wanted_current,
|
||||
|
@ -123,13 +123,11 @@ def describe_dev_error(exc):
|
||||
m = re.search(r'Command (\w+) not allowed when the '
|
||||
r'device is in (\w+) state', fulldesc)
|
||||
if m:
|
||||
fulldesc = 'executing %r not allowed in state %s' \
|
||||
% (m.group(1), m.group(2))
|
||||
fulldesc = f'executing {m.group(1)!r} not allowed in state {m.group(2)}'
|
||||
elif reason == 'API_DeviceNotExported':
|
||||
m = re.search(r'Device ([\w/]+) is not', fulldesc)
|
||||
if m:
|
||||
fulldesc = 'Tango device %s is not exported, is the server ' \
|
||||
'running?' % m.group(1)
|
||||
fulldesc = f'Tango device {m.group(1)} is not exported, is the server running?'
|
||||
elif reason == 'API_CorbaException':
|
||||
if 'TRANSIENT_CallTimedout' in fulldesc:
|
||||
fulldesc = 'Tango client-server call timed out'
|
||||
@ -139,15 +137,14 @@ def describe_dev_error(exc):
|
||||
elif reason == 'API_CantConnectToDevice':
|
||||
m = re.search(r'connect to device ([\w/]+)', fulldesc)
|
||||
if m:
|
||||
fulldesc = 'connection to Tango device %s failed, is the server ' \
|
||||
'running?' % m.group(1)
|
||||
fulldesc = f'connection to Tango device {m.group(1)} failed, is the server running?'
|
||||
elif reason == 'API_CommandTimedOut':
|
||||
if 'acquire serialization' in fulldesc:
|
||||
fulldesc = 'Tango call timed out waiting for lock on server'
|
||||
|
||||
# append origin if wanted
|
||||
if origin:
|
||||
fulldesc += ' in %s' % origin
|
||||
fulldesc += f' in {origin}'
|
||||
return fulldesc
|
||||
|
||||
|
||||
@ -568,8 +565,7 @@ class AnalogOutput(PyTangoDevice, Drivable):
|
||||
amin, amax = self.abslimits
|
||||
if umin > umax:
|
||||
raise ValueError(
|
||||
self, 'user minimum (%s) above the user '
|
||||
'maximum (%s)' % (umin, umax))
|
||||
self, f'user minimum ({umin}) above the user maximum ({umax})')
|
||||
if umin < amin - abs(amin * 1e-12):
|
||||
umin = amin
|
||||
if umax > amax + abs(amax * 1e-12):
|
||||
@ -831,7 +827,7 @@ class NamedDigitalInput(DigitalInput):
|
||||
mapping = eval(mapping)
|
||||
self.accessibles['value'].setProperty('datatype', EnumType('value', **mapping))
|
||||
except Exception as e:
|
||||
raise ValueError('Illegal Value for mapping: %r' % self.mapping) from e
|
||||
raise ValueError(f'Illegal Value for mapping: {self.mapping!r}') from e
|
||||
|
||||
def read_value(self):
|
||||
value = self._dev.value
|
||||
@ -909,7 +905,7 @@ class NamedDigitalOutput(DigitalOutput):
|
||||
self.accessibles['value'].setProperty('datatype', EnumType('value', **mapping))
|
||||
self.accessibles['target'].setProperty('datatype', EnumType('target', **mapping))
|
||||
except Exception as e:
|
||||
raise ValueError('Illegal Value for mapping: %r' % self.mapping) from e
|
||||
raise ValueError(f'Illegal Value for mapping: {self.mapping!r}') from e
|
||||
|
||||
def write_target(self, value):
|
||||
# map from enum-str to integer value
|
||||
|
@ -84,9 +84,9 @@ class Capacitance(HasIO, Readable):
|
||||
return self.voltage
|
||||
|
||||
def write_freq(self, value):
|
||||
self.value = self.parse_reply(self.communicate('FR %g;SI' % value))
|
||||
self.value = self.parse_reply(self.communicate(f'FR {value:g};SI'))
|
||||
return self.freq
|
||||
|
||||
def write_voltage(self, value):
|
||||
self.value = self.parse_reply(self.communicate('V %g;SI' % value))
|
||||
self.value = self.parse_reply(self.communicate(f'V {value:g};SI'))
|
||||
return self.voltage
|
||||
|
@ -84,13 +84,13 @@ class HeLevel(HasIO, Readable):
|
||||
return self.query('hem')
|
||||
|
||||
def write_empty_length(self, value):
|
||||
return self.query('hem=%g' % value)
|
||||
return self.query(f'hem={value:g}')
|
||||
|
||||
def read_full_length(self):
|
||||
return self.query('hfu')
|
||||
|
||||
def write_full_length(self, value):
|
||||
return self.query('hfu=%g' % value)
|
||||
return self.query(f'hfu={value:g}')
|
||||
|
||||
def read_sample_rate(self):
|
||||
return self.query('hf')
|
||||
|
@ -145,7 +145,7 @@ class ChannelSwitcher(Drivable):
|
||||
|
||||
def write_target(self, channel):
|
||||
if channel not in self._channels:
|
||||
raise ValueError('%r is no valid channel' % channel)
|
||||
raise ValueError(f'{channel!r} is no valid channel')
|
||||
if channel == self.target and self._channels[channel].enabled:
|
||||
return channel
|
||||
chan = self._channels[channel]
|
||||
|
@ -31,11 +31,12 @@ def make_cvt_list(dt, tail=''):
|
||||
tail is a postfix to be appended in case of tuples and structs
|
||||
"""
|
||||
if isinstance(dt, (EnumType, IntRange, BoolType)):
|
||||
return[(int, tail, dict(type='NUM'))]
|
||||
return[(int, tail, {type: 'NUM'})]
|
||||
if isinstance(dt, (FloatRange, ScaledInteger)):
|
||||
return [(dt.import_value, tail, dict(type='NUM', unit=dt.unit, period=5) if dt.unit else {})]
|
||||
return [(dt.import_value, tail,
|
||||
{'type': 'NUM', 'unit': dt.unit, 'period': 5} if dt.unit else {})]
|
||||
if isinstance(dt, StringType):
|
||||
return [(lambda x: x, tail, dict(type='STR'))]
|
||||
return [(lambda x: x, tail, {'type': 'STR'})]
|
||||
if isinstance(dt, TupleOf):
|
||||
items = enumerate(dt.members)
|
||||
elif isinstance(dt, StructOf):
|
||||
@ -44,7 +45,7 @@ def make_cvt_list(dt, tail=''):
|
||||
return [] # ArrayType, BlobType and TextType are ignored: too much data, probably not used
|
||||
result = []
|
||||
for subkey, elmtype in items:
|
||||
for fun, tail_, opts in make_cvt_list(elmtype, '%s.%s' % (tail, subkey)):
|
||||
for fun, tail_, opts in make_cvt_list(elmtype, f'{tail}.{subkey}'):
|
||||
result.append((lambda v, k=subkey, f=fun: f(v[k]), tail_, opts))
|
||||
return result
|
||||
|
||||
@ -122,7 +123,7 @@ class FrappyHistoryWriter(frappyhistory.FrappyWriter):
|
||||
def send_reply(self, msg):
|
||||
action, ident, value = msg
|
||||
if not action.endswith('update'):
|
||||
print('unknown async message %r' % msg)
|
||||
print(f'unknown async message {msg!r}')
|
||||
return
|
||||
now = self._init_time or time.time() # on initialisation, use the same timestamp for all
|
||||
if action == 'update':
|
||||
|
@ -78,7 +78,7 @@ class SourceMeter(HasIO, Module):
|
||||
def write_ilimit(self, value):
|
||||
if self.mode == 'current':
|
||||
return self.ilimit
|
||||
return float(self.communicate('smua.source.limiti = %g print(smua.source.limiti)' % value))
|
||||
return float(self.communicate(f'smua.source.limiti = {value:g} print(smua.source.limiti)'))
|
||||
|
||||
def read_vlimit(self):
|
||||
if self.mode == 'voltage':
|
||||
@ -88,7 +88,7 @@ class SourceMeter(HasIO, Module):
|
||||
def write_vlimit(self, value):
|
||||
if self.mode == 'voltage':
|
||||
return self.ilimit
|
||||
return float(self.communicate('smua.source.limitv = %g print(smua.source.limitv)' % value))
|
||||
return float(self.communicate(f'smua.source.limitv = {value:g} print(smua.source.limitv)'))
|
||||
|
||||
|
||||
class Power(HasIO, Readable):
|
||||
@ -130,7 +130,7 @@ class Current(HasIO, Writable):
|
||||
raise ValueError('current exceeds limit')
|
||||
if not self.active:
|
||||
self.sourcemeter.write_mode('current') # triggers update_mode -> set active to True
|
||||
value = float(self.communicate('smua.source.leveli = %g print(smua.source.leveli)' % value))
|
||||
value = float(self.communicate(f'smua.source.leveli = {value:g} print(smua.source.leveli)'))
|
||||
return value
|
||||
|
||||
def read_limit(self):
|
||||
@ -176,7 +176,7 @@ class Voltage(HasIO, Writable):
|
||||
raise ValueError('voltage exceeds limit')
|
||||
if not self.active:
|
||||
self.sourcemeter.write_mode('voltage') # triggers update_mode -> set active to True
|
||||
value = float(self.communicate('smua.source.levelv = %g print(smua.source.levelv)' % value))
|
||||
value = float(self.communicate(f'smua.source.levelv = {value:g} print(smua.source.levelv)'))
|
||||
return value
|
||||
|
||||
def read_limit(self):
|
||||
|
@ -40,7 +40,7 @@ SELF = 0
|
||||
def as_float(value):
|
||||
if isinstance(value, str):
|
||||
return float(VALUE_UNIT.match(value).group(1))
|
||||
return '%g' % value
|
||||
return f'{value:g}'
|
||||
|
||||
|
||||
def as_string(value):
|
||||
@ -78,9 +78,9 @@ class MercuryChannel(HasIO):
|
||||
head, sep, tail = adr.partition(':')
|
||||
for i, (channel_type, slot) in enumerate(zip(self.channel_type.split(','), self.slot.split(','))):
|
||||
if head == str(i):
|
||||
return 'DEV:%s:%s%s%s' % (slot, channel_type, sep, tail)
|
||||
return f'DEV:{slot}:{channel_type}{sep}{tail}'
|
||||
if head == channel_type:
|
||||
return 'DEV:%s:%s%s%s' % (slot, head, sep, tail)
|
||||
return f'DEV:{slot}:{head}{sep}{tail}'
|
||||
return adr
|
||||
|
||||
def multiquery(self, adr, names=(), convert=as_float):
|
||||
@ -101,9 +101,9 @@ class MercuryChannel(HasIO):
|
||||
-> query command will be READ:DEV:DB3.G1:PRES:SIG:PERC
|
||||
"""
|
||||
adr = self._complete_adr(adr)
|
||||
cmd = 'READ:%s:%s' % (adr, ':'.join(names))
|
||||
cmd = f"READ:{adr}:{':'.join(names)}"
|
||||
reply = self.communicate(cmd)
|
||||
head = 'STAT:%s:' % adr
|
||||
head = f'STAT:{adr}:'
|
||||
try:
|
||||
assert reply.startswith(head)
|
||||
replyiter = iter(reply[len(head):].split(':'))
|
||||
@ -111,7 +111,7 @@ class MercuryChannel(HasIO):
|
||||
assert keys == tuple(names)
|
||||
return tuple(convert(r) for r in result)
|
||||
except (AssertionError, AttributeError, ValueError):
|
||||
raise HardwareError('invalid reply %r to cmd %r' % (reply, cmd)) from None
|
||||
raise HardwareError(f'invalid reply {reply!r} to cmd {cmd!r}') from None
|
||||
|
||||
def multichange(self, adr, values, convert=as_float):
|
||||
"""set parameter(s) in mercury syntax
|
||||
@ -129,10 +129,10 @@ class MercuryChannel(HasIO):
|
||||
-> change command will be SET:DEV:DB6.T1:TEMP:LOOP:P:5:I:2:D:0
|
||||
"""
|
||||
adr = self._complete_adr(adr)
|
||||
params = ['%s:%s' % (k, convert(v)) for k, v in values]
|
||||
cmd = 'SET:%s:%s' % (adr, ':'.join(params))
|
||||
params = [f'{k}:{convert(v)}' for k, v in values]
|
||||
cmd = f"SET:{adr}:{':'.join(params)}"
|
||||
reply = self.communicate(cmd)
|
||||
head = 'STAT:SET:%s:' % adr
|
||||
head = f'STAT:SET:{adr}:'
|
||||
|
||||
try:
|
||||
assert reply.startswith(head)
|
||||
@ -142,7 +142,7 @@ class MercuryChannel(HasIO):
|
||||
assert any(v == 'VALID' for v in valid)
|
||||
return tuple(convert(r) for r in result)
|
||||
except (AssertionError, AttributeError, ValueError) as e:
|
||||
raise HardwareError('invalid reply %r to cmd %r' % (reply, cmd)) from e
|
||||
raise HardwareError(f'invalid reply {reply!r} to cmd {cmd!r}') from e
|
||||
|
||||
def query(self, adr, convert=as_float):
|
||||
"""query a single parameter
|
||||
|
@ -72,7 +72,7 @@ class MotorValve(PersistentMixin, Drivable):
|
||||
|
||||
def write_target(self, target):
|
||||
if self.status[0] == ERROR:
|
||||
raise HardwareError('%s: need refrun' % self.status[1])
|
||||
raise HardwareError(f'{self.status[1]}: need refrun')
|
||||
self.target = target
|
||||
self._state.start(self.goto_target, count=3)
|
||||
return self.target
|
||||
|
@ -80,7 +80,7 @@ class Main(Communicator):
|
||||
def communicate(self, command):
|
||||
"""GPIB command"""
|
||||
with self.lock:
|
||||
self.comLog('> %s' % command)
|
||||
self.comLog(f'> {command}')
|
||||
reply = self._ppms_device.send(command)
|
||||
self.comLog("< %s", reply)
|
||||
return reply
|
||||
@ -151,7 +151,7 @@ class PpmsBase(HasIO, Readable):
|
||||
"""write command and check if result is OK"""
|
||||
reply = self.communicate(command)
|
||||
if reply != 'OK':
|
||||
raise HardwareError('bad reply %r to command %r' % (reply, command))
|
||||
raise HardwareError(f'bad reply {reply!r} to command {command!r}')
|
||||
|
||||
|
||||
class PpmsDrivable(Drivable, PpmsBase):
|
||||
@ -447,12 +447,12 @@ class Temp(PpmsDrivable):
|
||||
if status[0] == StatusType.IDLE:
|
||||
status = (status[0], 'stopped')
|
||||
else:
|
||||
status = (status[0], 'stopping (%s)' % status[1])
|
||||
status = (status[0], f'stopping ({status[1]})')
|
||||
if self._expected_target_time:
|
||||
# handle timeout
|
||||
if self.isDriving(status):
|
||||
if now > self._expected_target_time + self.timeout:
|
||||
status = (StatusType.WARN, 'timeout while %s' % status[1])
|
||||
status = (StatusType.WARN, f'timeout while {status[1]}')
|
||||
else:
|
||||
self._expected_target_time = 0
|
||||
self.status = status
|
||||
@ -492,7 +492,7 @@ class Temp(PpmsDrivable):
|
||||
if newtarget != self.target:
|
||||
self.log.debug('stop at %s K', newtarget)
|
||||
self.write_target(newtarget)
|
||||
self.status = self.status[0], 'stopping (%s)' % self.status[1]
|
||||
self.status = self.status[0], f'stopping ({self.status[1]})'
|
||||
self._stopped = True
|
||||
|
||||
|
||||
@ -577,7 +577,7 @@ class Field(PpmsDrivable):
|
||||
if status[0] == StatusType.IDLE:
|
||||
status = (status[0], 'stopped')
|
||||
else:
|
||||
status = (status[0], 'stopping (%s)' % status[1])
|
||||
status = (status[0], f'stopping ({status[1]})')
|
||||
self.status = status
|
||||
|
||||
def write_target(self, target):
|
||||
@ -620,7 +620,7 @@ class Field(PpmsDrivable):
|
||||
if newtarget != self.target:
|
||||
self.log.debug('stop at %s T', newtarget)
|
||||
self.write_target(newtarget)
|
||||
self.status = (self.status[0], 'stopping (%s)' % self.status[1])
|
||||
self.status = (self.status[0], f'stopping ({self.status[1]})')
|
||||
self._stopped = True
|
||||
|
||||
|
||||
@ -698,7 +698,7 @@ class Position(PpmsDrivable):
|
||||
if status[0] == StatusType.IDLE:
|
||||
status = (status[0], 'stopped')
|
||||
else:
|
||||
status = (status[0], 'stopping (%s)' % status[1])
|
||||
status = (status[0], f'stopping ({status[1]})')
|
||||
self.status = status
|
||||
|
||||
def write_target(self, target):
|
||||
@ -722,5 +722,5 @@ class Position(PpmsDrivable):
|
||||
if newtarget != self.target:
|
||||
self.log.debug('stop at %s T', newtarget)
|
||||
self.write_target(newtarget)
|
||||
self.status = (self.status[0], 'stopping (%s)' % self.status[1])
|
||||
self.status = (self.status[0], f'stopping ({self.status[1]})')
|
||||
self._stopped = True
|
||||
|
@ -48,7 +48,7 @@ class NamedList:
|
||||
return setattr(self, self.__keys__[index], value)
|
||||
|
||||
def __repr__(self):
|
||||
return ",".join("%.7g" % val for val in self.aslist())
|
||||
return ",".join(f"{val:.7g}" for val in self.aslist())
|
||||
|
||||
|
||||
class PpmsSim:
|
||||
@ -198,10 +198,10 @@ class PpmsSim:
|
||||
|
||||
def getdat(self, mask):
|
||||
mask = int(mask) & 0x8000ff # all channels up to i2 plus ts
|
||||
output = ['%d' % mask, '%.2f' % (time.time() - self.start)]
|
||||
output = ['%d' % mask, f'{time.time() - self.start:.2f}']
|
||||
for i, chan in self.CHANNELS.items():
|
||||
if (1 << i) & mask:
|
||||
output.append("%.7g" % getattr(self, chan))
|
||||
output.append(f"{getattr(self, chan):.7g}")
|
||||
return ",".join(output)
|
||||
|
||||
|
||||
@ -219,12 +219,12 @@ class QDevice:
|
||||
name, args = command.split('?')
|
||||
name += args.strip()
|
||||
result = getattr(self.sim, name.lower()).aslist()
|
||||
result = ",".join("%.7g" % arg for arg in result)
|
||||
result = ",".join(f"{arg:.7g}" for arg in result)
|
||||
# print(command, '/', result)
|
||||
else:
|
||||
# print(command)
|
||||
name, args = command.split()
|
||||
args = json.loads("[%s]" % args)
|
||||
args = json.loads(f"[{args}]")
|
||||
if name.startswith('BRIDGE') or name.startswith('DRVOUT'):
|
||||
name = name + str(int(args[0]))
|
||||
getattr(self.sim, name.lower()).setvalues(args)
|
||||
|
@ -121,7 +121,7 @@ class CalCurve:
|
||||
# then try adding all kinds as extension
|
||||
for nam in calibname, calibname.upper(), calibname.lower():
|
||||
for kind in KINDS:
|
||||
filename = join(path.strip(), '%s.%s' % (nam, kind))
|
||||
filename = join(path.strip(), f'{nam}.{kind}')
|
||||
if exists(filename):
|
||||
break
|
||||
else:
|
||||
@ -148,7 +148,7 @@ class CalCurve:
|
||||
for line in f:
|
||||
parser.parse(line)
|
||||
except Exception as e:
|
||||
raise ValueError('calib curve %s: %s' % (calibspec, e)) from e
|
||||
raise ValueError(f'calib curve {calibspec}: {e}') from e
|
||||
self.convert_x = nplog if parser.logx else linear
|
||||
self.convert_y = npexp if parser.logy else linear
|
||||
x = np.asarray(parser.xdata)
|
||||
@ -157,11 +157,11 @@ class CalCurve:
|
||||
x = np.flip(x)
|
||||
y = np.flip(y)
|
||||
elif np.any(x[:-1] >= x[1:]): # some not increasing
|
||||
raise ValueError('calib curve %s is not monotonic' % calibspec)
|
||||
raise ValueError(f'calib curve {calibspec} is not monotonic')
|
||||
try:
|
||||
self.spline = splrep(x, y, s=0, k=min(3, len(x) - 1))
|
||||
except (ValueError, TypeError) as e:
|
||||
raise ValueError('invalid calib curve %s' % calibspec) from e
|
||||
raise ValueError(f'invalid calib curve {calibspec}') from e
|
||||
|
||||
def __call__(self, value):
|
||||
"""convert value
|
||||
@ -194,7 +194,7 @@ class Sensor(Readable):
|
||||
self.rawsensor.registerCallbacks(self, ['status']) # auto update status
|
||||
self._calib = CalCurve(self.calib)
|
||||
if self.description == '_':
|
||||
self.description = '%r calibrated with curve %r' % (self.rawsensor, self.calib)
|
||||
self.description = f'{self.rawsensor!r} calibrated with curve {self.calib!r}'
|
||||
|
||||
def doPoll(self):
|
||||
self.read_status()
|
||||
|
@ -334,9 +334,9 @@ class Motor(PersistentMixin, HasIO, Drivable):
|
||||
return IDLE, ''
|
||||
if self.auto_reset:
|
||||
self._need_reset = True
|
||||
return IDLE, 'stalled: %s' % reason
|
||||
return IDLE, f'stalled: {reason}'
|
||||
self.log.error('out of tolerance by %.3g (%s)', diff, reason)
|
||||
return ERROR, 'out of tolerance (%s)' % reason
|
||||
return ERROR, f'out of tolerance ({reason})'
|
||||
|
||||
def write_target(self, target):
|
||||
for _ in range(2): # for auto reset
|
||||
@ -345,8 +345,7 @@ class Motor(PersistentMixin, HasIO, Drivable):
|
||||
abs(target - self.encoder) > self.move_limit + self.tolerance):
|
||||
# pylint: disable=bad-string-format-type
|
||||
# pylint wrongly does not recognise encoder as a descriptor
|
||||
raise RangeError('can not move more than %g deg (%g -> %g)' %
|
||||
(self.move_limit, self.encoder, target))
|
||||
raise RangeError(f'can not move more than {self.move_limit:g} deg ({self.encoder:g} -> {target:g})')
|
||||
diff = self.encoder - self.steppos
|
||||
if self._need_reset:
|
||||
if self.auto_reset:
|
||||
@ -359,7 +358,7 @@ class Motor(PersistentMixin, HasIO, Drivable):
|
||||
if self.status[0] == IDLE:
|
||||
continue
|
||||
raise HardwareError('auto reset failed')
|
||||
raise HardwareError('need reset (%s)' % self.status[1])
|
||||
raise HardwareError(f'need reset ({self.status[1]})')
|
||||
break
|
||||
if abs(diff) > self.tolerance:
|
||||
if abs(diff) > self.encoder_tolerance and self.has_encoder:
|
||||
|
Loading…
x
Reference in New Issue
Block a user