Remove py2 support

Change-Id: Ieeaeb3b8efcae004e94aea6c1d2703c9782a8650
Reviewed-on: https://forge.frm2.tum.de/review/c/sine2020/secop/playground/+/21320
Tested-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
Reviewed-by: Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
This commit is contained in:
Enrico Faulhaber 2019-09-25 17:45:26 +02:00
parent 04032079d7
commit 70a9c42a7a
59 changed files with 458 additions and 667 deletions

View File

@ -11,7 +11,7 @@ demo:
@ps aux|grep [s]ecop-server|awk '{print $$2}'|xargs kill
build:
python setup.py build
python3 setup.py build
clean:
find . -name '*.pyc' -delete
@ -19,20 +19,20 @@ clean:
$(MAKE) -C doc clean
install: build
python setup.py install
python3 setup.py install
test:
ifdef T
python $(shell which pytest) -v test -l -k $(T)
python3 $(shell which pytest) -v test -l -k $(T)
else
python $(shell which pytest) -v test -l
python3 $(shell which pytest) -v test -l
endif
test-verbose:
python $(shell which pytest) -v test -s
python3 $(shell which pytest) -v test -s
test-coverage:
python $(shell which pytest) -v test --cov=secop
python3 $(shell which pytest) -v test --cov=secop
doc:
$(MAKE) -C doc html

View File

@ -21,7 +21,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
import os
from os import path

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# *****************************************************************************
#

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# pylint: disable=invalid-name
# -*- coding: utf-8 -*-
# *****************************************************************************

View File

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
# *****************************************************************************
#

View File

@ -21,19 +21,11 @@
# *****************************************************************************
"""basic validators (for properties)"""
from __future__ import division, print_function
import re
from secop.errors import ProgrammingError
try:
# py2
unicode
except NameError:
# py3
unicode = str # pylint: disable=redefined-builtin
def FloatProperty(value):
return float(value)
@ -43,80 +35,80 @@ def PositiveFloatProperty(value):
value = float(value)
if value > 0:
return value
raise ValueError(u'Value must be >0 !')
raise ValueError('Value must be >0 !')
def NonNegativeFloatProperty(value):
value = float(value)
if value >= 0:
return value
raise ValueError(u'Value must be >=0 !')
raise ValueError('Value must be >=0 !')
def IntProperty(value):
if int(value) == float(value):
return int(value)
raise ValueError(u'Can\'t convert %r to int!' % value)
raise ValueError('Can\'t convert %r to int!' % value)
def PositiveIntProperty(value):
value = IntProperty(value)
if value > 0:
return value
raise ValueError(u'Value must be >0 !')
raise ValueError('Value must be >0 !')
def NonNegativeIntProperty(value):
value = IntProperty(value)
if value >= 0:
return value
raise ValueError(u'Value must be >=0 !')
raise ValueError('Value must be >=0 !')
def BoolProperty(value):
try:
if value.lower() in [u'0', u'false', u'no', u'off',]:
if value.lower() in ['0', 'false', 'no', 'off',]:
return False
if value.lower() in [u'1', u'true', u'yes', u'on', ]:
if value.lower() in ['1', 'true', 'yes', 'on', ]:
return True
except AttributeError: # was no string
if bool(value) == value:
return value
raise ValueError(u'%r is no valid boolean: try one of True, False, "on", "off",...' % value)
raise ValueError('%r is no valid boolean: try one of True, False, "on", "off",...' % value)
def StringProperty(value):
return unicode(value)
return str(value)
def UnitProperty(value):
# probably too simple!
for s in unicode(value):
if s.lower() not in u'°abcdefghijklmnopqrstuvwxyz':
raise ValueError(u'%r is not a valid unit!')
for s in str(value):
if s.lower() not in '°abcdefghijklmnopqrstuvwxyz':
raise ValueError('%r is not a valid unit!')
def FmtStrProperty(value, regexp=re.compile(r'^%\.?\d+[efg]$')):
value=unicode(value)
value=str(value)
if regexp.match(value):
return value
raise ValueError(u'%r is not a valid fmtstr!' % value)
raise ValueError('%r is not a valid fmtstr!' % value)
def OneOfProperty(*args):
# literally oneof!
if not args:
raise ProgrammingError(u'OneOfProperty needs some argumets to check against!')
raise ProgrammingError('OneOfProperty needs some argumets to check against!')
def OneOfChecker(value):
if value not in args:
raise ValueError(u'Value must be one of %r' % list(args))
raise ValueError('Value must be one of %r' % list(args))
return value
return OneOfChecker
def NoneOr(checker):
if not callable(checker):
raise ProgrammingError(u'NoneOr needs a basic validator as Argument!')
raise ProgrammingError('NoneOr needs a basic validator as Argument!')
def NoneOrChecker(value):
if value is None:
return None
@ -126,13 +118,13 @@ def NoneOr(checker):
def EnumProperty(**kwds):
if not kwds:
raise ProgrammingError(u'EnumProperty needs a mapping!')
raise ProgrammingError('EnumProperty needs a mapping!')
def EnumChecker(value):
if value in kwds:
return kwds[value]
if value in kwds.values():
return value
raise ValueError(u'Value must be one of %r' % list(kwds))
raise ValueError('Value must be one of %r' % list(kwds))
return EnumChecker
def TupleProperty(*checkers):
@ -140,16 +132,16 @@ def TupleProperty(*checkers):
checkers = [None]
for c in checkers:
if not callable(c):
raise ProgrammingError(u'TupleProperty needs basic validators as Arguments!')
raise ProgrammingError('TupleProperty needs basic validators as Arguments!')
def TupleChecker(values):
if len(values)==len(checkers):
return tuple(c(v) for c, v in zip(checkers, values))
raise ValueError(u'Value needs %d elements!' % len(checkers))
raise ValueError('Value needs %d elements!' % len(checkers))
return TupleChecker
def ListOfProperty(checker):
if not callable(checker):
raise ProgrammingError(u'ListOfProperty needs a basic validator as Argument!')
raise ProgrammingError('ListOfProperty needs a basic validator as Argument!')
def ListOfChecker(values):
return [checker(v) for v in values]
return ListOfChecker

View File

@ -23,7 +23,6 @@
# nothing here yet.
from __future__ import print_function
import code
import socket

View File

@ -21,9 +21,9 @@
# *****************************************************************************
"""Define Client side proxies"""
from __future__ import division, print_function
import json
import queue
import socket
import threading
import time
@ -43,15 +43,6 @@ from secop.protocol.messages import BUFFERREQUEST, COMMANDREQUEST, \
HEARTBEATREQUEST, HELPREQUEST, IDENTREQUEST, READREPLY, \
READREQUEST, REQUEST2REPLY, WRITEREPLY, WRITEREQUEST
try:
# py3
import queue
except ImportError:
# py2
import Queue as queue
class TCPConnection(object):
# disguise a TCP connection as serial one

View File

@ -23,7 +23,6 @@
# pylint: disable=abstract-method
from __future__ import division, print_function
from base64 import b64decode, b64encode
@ -31,22 +30,15 @@ from secop.errors import ProgrammingError, ProtocolError, BadValueError
from secop.lib.enum import Enum
from secop.parse import Parser
try:
# py2
unicode
except NameError:
# py3
unicode = str # pylint: disable=redefined-builtin
# Only export these classes for 'from secop.datatypes import *'
__all__ = [
u'DataType',
u'FloatRange', u'IntRange',
u'BoolType', u'EnumType',
u'BLOBType', u'StringType',
u'TupleOf', u'ArrayOf', u'StructOf',
u'CommandType',
'DataType',
'FloatRange', 'IntRange',
'BoolType', 'EnumType',
'BLOBType', 'StringType',
'TupleOf', 'ArrayOf', 'StructOf',
'CommandType',
]
# *DEFAULT* limits for IntRange/ScaledIntegers transport serialisation
@ -58,8 +50,8 @@ Parser = Parser()
# base class for all DataTypes
class DataType(object):
IS_COMMAND = False
unit = u''
fmtstr = u'%r'
unit = ''
fmtstr = '%r'
default = None
def __call__(self, value):
@ -90,7 +82,7 @@ class DataType(object):
return value
def format_value(self, value, unit=None):
"""format a value of this type into a unicode string
"""format a value of this type into a str string
This is intended for 'nice' formatting for humans and is NOT
the opposite of :meth:`from_string`
@ -128,23 +120,23 @@ class FloatRange(DataType):
def __init__(self, minval=None, maxval=None, unit=None, fmtstr=None,
absolute_resolution=None, relative_resolution=None,):
self._defaults = {}
self.set_prop('min', minval, float(u'-inf'), float)
self.set_prop('max', maxval, float(u'+inf'), float)
self.set_prop('unit', unit, u'', unicode)
self.set_prop('fmtstr', fmtstr, u'%g', unicode)
self.set_prop('min', minval, float('-inf'), float)
self.set_prop('max', maxval, float('+inf'), float)
self.set_prop('unit', unit, '', str)
self.set_prop('fmtstr', fmtstr, '%g', str)
self.set_prop('absolute_resolution', absolute_resolution, 0.0, float)
self.set_prop('relative_resolution', relative_resolution, 1.2e-7, float)
self.default = 0 if self.min <= 0 <= self.max else self.min
# check values
if self.min > self.max:
raise BadValueError(u'max must be larger then min!')
raise BadValueError('max must be larger then min!')
if '%' not in self.fmtstr:
raise BadValueError(u'Invalid fmtstr!')
raise BadValueError('Invalid fmtstr!')
if self.absolute_resolution < 0:
raise BadValueError(u'absolute_resolution MUST be >=0')
raise BadValueError('absolute_resolution MUST be >=0')
if self.relative_resolution < 0:
raise BadValueError(u'relative_resolution MUST be >=0')
raise BadValueError('relative_resolution MUST be >=0')
def export_datatype(self):
return self.get_info(type='double')
@ -153,11 +145,11 @@ class FloatRange(DataType):
try:
value = float(value)
except Exception:
raise BadValueError(u'Can not __call__ %r to float' % value)
raise BadValueError('Can not __call__ %r to float' % value)
prec = max(abs(value * self.relative_resolution), self.absolute_resolution)
if self.min - prec <= value <= self.max + prec:
return min(max(value, self.min), self.max)
raise BadValueError(u'%.14g should be a float between %.14g and %.14g' %
raise BadValueError('%.14g should be a float between %.14g and %.14g' %
(value, self.min, self.max))
def __repr__(self):
@ -166,7 +158,7 @@ class FloatRange(DataType):
hints['minval'] = hints.pop('min')
if 'max' in hints:
hints['maxval'] = hints.pop('max')
return u'FloatRange(%s)' % (', '.join('%s=%r' % (k,v) for k,v in hints.items()))
return 'FloatRange(%s)' % (', '.join('%s=%r' % (k,v) for k,v in hints.items()))
def export_value(self, value):
"""returns a python object fit for serialisation"""
@ -184,7 +176,7 @@ class FloatRange(DataType):
if unit is None:
unit = self.unit
if unit:
return u' '.join([self.fmtstr % value, unit])
return ' '.join([self.fmtstr % value, unit])
return self.fmtstr % value
@ -196,11 +188,11 @@ class IntRange(DataType):
self.max = DEFAULT_MAX_INT if maxval is None else int(maxval)
self.default = 0 if self.min <= 0 <= self.max else self.min
# a unit on an int is now allowed in SECoP, but do we need them in Frappy?
# self.set_prop('unit', unit, u'', unicode)
# self.set_prop('unit', unit, '', str)
# check values
if self.min > self.max:
raise BadValueError(u'Max must be larger then min!')
raise BadValueError('Max must be larger then min!')
def export_datatype(self):
return dict(type='int', min=self.min, max=self.max)
@ -209,17 +201,17 @@ class IntRange(DataType):
try:
value = int(value)
if value < self.min:
raise BadValueError(u'%r should be an int between %d and %d' %
raise BadValueError('%r should be an int between %d and %d' %
(value, self.min, self.max or 0))
if value > self.max:
raise BadValueError(u'%r should be an int between %d and %d' %
raise BadValueError('%r should be an int between %d and %d' %
(value, self.min or 0, self.max))
return value
except Exception:
raise BadValueError(u'Can not convert %r to int' % value)
raise BadValueError('Can not convert %r to int' % value)
def __repr__(self):
return u'IntRange(%d, %d)' % (self.min, self.max)
return 'IntRange(%d, %d)' % (self.min, self.max)
def export_value(self, value):
"""returns a python object fit for serialisation"""
@ -234,7 +226,7 @@ class IntRange(DataType):
return self(value)
def format_value(self, value, unit=None):
return u'%d' % value
return '%d' % value
class ScaledInteger(DataType):
@ -248,9 +240,9 @@ class ScaledInteger(DataType):
self._defaults = {}
self.scale = float(scale)
if not self.scale > 0:
raise BadValueError(u'Scale MUST be positive!')
self.set_prop('unit', unit, u'', unicode)
self.set_prop('fmtstr', fmtstr, u'%g', unicode)
raise BadValueError('Scale MUST be positive!')
self.set_prop('unit', unit, '', str)
self.set_prop('fmtstr', fmtstr, '%g', str)
self.set_prop('absolute_resolution', absolute_resolution, self.scale, float)
self.set_prop('relative_resolution', relative_resolution, 1.2e-7, float)
@ -260,13 +252,13 @@ class ScaledInteger(DataType):
# check values
if self.min > self.max:
raise BadValueError(u'Max must be larger then min!')
raise BadValueError('Max must be larger then min!')
if '%' not in self.fmtstr:
raise BadValueError(u'Invalid fmtstr!')
raise BadValueError('Invalid fmtstr!')
if self.absolute_resolution < 0:
raise BadValueError(u'absolute_resolution MUST be >=0')
raise BadValueError('absolute_resolution MUST be >=0')
if self.relative_resolution < 0:
raise BadValueError(u'relative_resolution MUST be >=0')
raise BadValueError('relative_resolution MUST be >=0')
# Remark: Datatype.copy() will round min, max to a multiple of self.scale
# this should be o.k.
@ -279,13 +271,13 @@ class ScaledInteger(DataType):
try:
value = float(value)
except Exception:
raise BadValueError(u'Can not convert %r to float' % value)
raise BadValueError('Can not convert %r to float' % value)
prec = max(self.scale, abs(value * self.relative_resolution),
self.absolute_resolution)
if self.min - prec <= value <= self.max + prec:
value = min(max(value, self.min), self.max)
else:
raise BadValueError(u'%g should be a float between %g and %g' %
raise BadValueError('%g should be a float between %g and %g' %
(value, self.min, self.max))
intval = int((value + self.scale * 0.5) // self.scale)
value = float(intval * self.scale)
@ -295,7 +287,7 @@ class ScaledInteger(DataType):
hints = self.get_info(scale='%g' % self.scale,
min = int((self.min + self.scale * 0.5) // self.scale),
max = int((self.max + self.scale * 0.5) // self.scale))
return u'ScaledInteger(%s)' % (', '.join('%s=%r' % kv for kv in hints.items()))
return 'ScaledInteger(%s)' % (', '.join('%s=%r' % kv for kv in hints.items()))
def export_value(self, value):
"""returns a python object fit for serialisation"""
@ -314,17 +306,17 @@ class ScaledInteger(DataType):
if unit is None:
unit = self.unit
if unit:
return u' '.join([self.fmtstr % value, unit])
return ' '.join([self.fmtstr % value, unit])
return self.fmtstr % value
class EnumType(DataType):
def __init__(self, enum_or_name='', **kwds):
if u'members' in kwds:
if 'members' in kwds:
kwds = dict(kwds)
kwds.update(kwds[u'members'])
kwds.pop(u'members')
kwds.update(kwds['members'])
kwds.pop('members')
self._enum = Enum(enum_or_name, **kwds)
self.default = self._enum[self._enum.members[0]]
@ -336,7 +328,7 @@ class EnumType(DataType):
return {'type': 'enum', 'members':dict((m.name, m.value) for m in self._enum.members)}
def __repr__(self):
return u"EnumType(%r, %s)" % (self._enum.name, ', '.join(u'%s=%d' %(m.name, m.value) for m in self._enum.members))
return u"EnumType(%r, %s)" % (self._enum.name, ', '.join('%s=%d' %(m.name, m.value) for m in self._enum.members))
def export_value(self, value):
"""returns a python object fit for serialisation"""
@ -351,13 +343,13 @@ class EnumType(DataType):
try:
return self._enum[value]
except (KeyError, TypeError): # TypeError will be raised when value is not hashable
raise BadValueError(u'%r is not a member of enum %r' % (value, self._enum))
raise BadValueError('%r is not a member of enum %r' % (value, self._enum))
def from_string(self, text):
return self(text)
def format_value(self, value, unit=None):
return u'%s<%s>' % (self._enum[value].name, self._enum[value].value)
return '%s<%s>' % (self._enum[value].name, self._enum[value].value)
class BLOBType(DataType):
@ -373,28 +365,28 @@ class BLOBType(DataType):
self.set_prop('minbytes', minbytes, 0, int)
self.maxbytes = int(maxbytes)
if self.minbytes < 0:
raise BadValueError(u'sizes must be bigger than or equal to 0!')
raise BadValueError('sizes must be bigger than or equal to 0!')
elif self.minbytes > self.maxbytes:
raise BadValueError(u'maxbytes must be bigger than or equal to minbytes!')
raise BadValueError('maxbytes must be bigger than or equal to minbytes!')
self.default = b'\0' * self.minbytes
def export_datatype(self):
return self.get_info(type='blob', maxbytes=self.maxbytes)
def __repr__(self):
return u'BLOBType(%d, %d)' % (self.minbytes, self.maxbytes)
return 'BLOBType(%d, %d)' % (self.minbytes, self.maxbytes)
def __call__(self, value):
"""return the validated (internal) value or raise"""
if not isinstance(value, bytes):
raise BadValueError(u'%r has the wrong type!' % value)
raise BadValueError('%r has the wrong type!' % value)
size = len(value)
if size < self.minbytes:
raise BadValueError(
u'%r must be at least %d bytes long!' % (value, self.minbytes))
'%r must be at least %d bytes long!' % (value, self.minbytes))
if size > self.maxbytes:
raise BadValueError(
u'%r must be at most %d bytes long!' % (value, self.maxbytes))
'%r must be at most %d bytes long!' % (value, self.maxbytes))
return value
def export_value(self, value):
@ -425,49 +417,49 @@ class StringType(DataType):
self.set_prop('maxchars', maxchars, self.MAXCHARS, int)
self.set_prop('isUTF8', isUTF8, False, bool)
if self.minchars < 0:
raise BadValueError(u'sizes must be bigger than or equal to 0!')
raise BadValueError('sizes must be bigger than or equal to 0!')
elif self.minchars > self.maxchars:
raise BadValueError(u'maxchars must be bigger than or equal to minchars!')
self.default = u' ' * self.minchars
raise BadValueError('maxchars must be bigger than or equal to minchars!')
self.default = ' ' * self.minchars
def export_datatype(self):
return self.get_info(type='string')
def __repr__(self):
return u'StringType(%s)' % (', '.join('%s=%r' % kv for kv in self.get_info().items()))
return 'StringType(%s)' % (', '.join('%s=%r' % kv for kv in self.get_info().items()))
def __call__(self, value):
"""return the validated (internal) value or raise"""
if type(value) not in (unicode, str):
raise BadValueError(u'%r has the wrong type!' % value)
if not isinstance(value, str):
raise BadValueError('%r has the wrong type!' % value)
if not self.isUTF8:
try:
value.encode('ascii')
except UnicodeEncodeError:
raise BadValueError(u'%r contains non-ascii character!' % value)
raise BadValueError('%r contains non-ascii character!' % value)
size = len(value)
if size < self.minchars:
raise BadValueError(
u'%r must be at least %d bytes long!' % (value, self.minchars))
'%r must be at least %d bytes long!' % (value, self.minchars))
if size > self.maxchars:
raise BadValueError(
u'%r must be at most %d bytes long!' % (value, self.maxchars))
if u'\0' in value:
'%r must be at most %d bytes long!' % (value, self.maxchars))
if '\0' in value:
raise BadValueError(
u'Strings are not allowed to embed a \\0! Use a Blob instead!')
'Strings are not allowed to embed a \\0! Use a Blob instead!')
return value
def export_value(self, value):
"""returns a python object fit for serialisation"""
return u'%s' % value
return '%s' % value
def import_value(self, value):
"""returns a python object from serialisation"""
# XXX: do we keep it as unicode str, or convert it to something else? (UTF-8 maybe?)
return unicode(value)
# XXX: do we keep it as str str, or convert it to something else? (UTF-8 maybe?)
return str(value)
def from_string(self, text):
value = unicode(text)
value = str(text)
return self(value)
def format_value(self, value, unit=None):
@ -485,7 +477,7 @@ class TextType(StringType):
super(TextType, self).__init__(0, maxchars)
def __repr__(self):
return u'TextType(%d, %d)' % (self.minchars, self.maxchars)
return 'TextType(%d, %d)' % (self.minchars, self.maxchars)
def copy(self):
# DataType.copy will not work, because it is exported as 'string'
@ -500,15 +492,15 @@ class BoolType(DataType):
return {'type': 'bool'}
def __repr__(self):
return u'BoolType()'
return 'BoolType()'
def __call__(self, value):
"""return the validated (internal) value or raise"""
if value in [0, u'0', u'False', u'false', u'no', u'off', False]:
if value in [0, '0', 'False', 'false', 'no', 'off', False]:
return False
if value in [1, u'1', u'True', u'true', u'yes', u'on', True]:
if value in [1, '1', 'True', 'true', 'yes', 'on', True]:
return True
raise BadValueError(u'%r is not a boolean value!' % value)
raise BadValueError('%r is not a boolean value!' % value)
def export_value(self, value):
"""returns a python object fit for serialisation"""
@ -539,7 +531,7 @@ class ArrayOf(DataType):
def __init__(self, members, minlen=0, maxlen=None, unit=None):
if not isinstance(members, DataType):
raise BadValueError(
u'ArrayOf only works with a DataType as first argument!')
'ArrayOf only works with a DataType as first argument!')
# one argument -> exactly that size
# argument default to 100
if maxlen is None:
@ -551,11 +543,11 @@ class ArrayOf(DataType):
self.minlen = int(minlen)
self.maxlen = int(maxlen)
if self.minlen < 0:
raise BadValueError(u'sizes must be > 0')
raise BadValueError('sizes must be > 0')
elif self.maxlen < 1:
raise BadValueError(u'Maximum size must be >= 1!')
raise BadValueError('Maximum size must be >= 1!')
elif self.minlen > self.maxlen:
raise BadValueError(u'maxlen must be bigger than or equal to minlen!')
raise BadValueError('maxlen must be bigger than or equal to minlen!')
self.default = [members.default] * self.minlen
def export_datatype(self):
@ -563,7 +555,7 @@ class ArrayOf(DataType):
members=self.members.export_datatype())
def __repr__(self):
return u'ArrayOf(%s, %s, %s)' % (
return 'ArrayOf(%s, %s, %s)' % (
repr(self.members), self.minlen, self.maxlen)
def __call__(self, value):
@ -572,15 +564,15 @@ class ArrayOf(DataType):
# check number of elements
if self.minlen is not None and len(value) < self.minlen:
raise BadValueError(
u'Array too small, needs at least %d elements!' %
'Array too small, needs at least %d elements!' %
self.minlen)
if self.maxlen is not None and len(value) > self.maxlen:
raise BadValueError(
u'Array too big, holds at most %d elements!' % self.minlen)
'Array too big, holds at most %d elements!' % self.minlen)
# apply subtype valiation to all elements and return as list
return [self.members(elem) for elem in value]
raise BadValueError(
u'Can not convert %s to ArrayOf DataType!' % repr(value))
'Can not convert %s to ArrayOf DataType!' % repr(value))
def export_value(self, value):
"""returns a python object fit for serialisation"""
@ -593,13 +585,13 @@ class ArrayOf(DataType):
def from_string(self, text):
value, rem = Parser.parse(text)
if rem:
raise ProtocolError(u'trailing garbage: %r' % rem)
raise ProtocolError('trailing garbage: %r' % rem)
return self(value)
def format_value(self, value, unit=None):
if unit is None:
unit = self.unit or self.members.unit
res = u'[%s]' % (', '.join([self.members.format_value(elem, u'') for elem in value]))
res = '[%s]' % (', '.join([self.members.format_value(elem, '') for elem in value]))
if unit:
return ' '.join([res, unit])
return res
@ -609,11 +601,11 @@ class TupleOf(DataType):
def __init__(self, *members):
if not members:
raise BadValueError(u'Empty tuples are not allowed!')
raise BadValueError('Empty tuples are not allowed!')
for subtype in members:
if not isinstance(subtype, DataType):
raise BadValueError(
u'TupleOf only works with DataType objs as arguments!')
'TupleOf only works with DataType objs as arguments!')
self.members = members
self.default = tuple(el.default for el in members)
@ -621,7 +613,7 @@ class TupleOf(DataType):
return dict(type='tuple', members=[subtype.export_datatype() for subtype in self.members])
def __repr__(self):
return u'TupleOf(%s)' % u', '.join([repr(st) for st in self.members])
return 'TupleOf(%s)' % ', '.join([repr(st) for st in self.members])
def __call__(self, value):
"""return the validated value or raise"""
@ -629,13 +621,13 @@ class TupleOf(DataType):
try:
if len(value) != len(self.members):
raise BadValueError(
u'Illegal number of Arguments! Need %d arguments.' %
'Illegal number of Arguments! Need %d arguments.' %
(len(self.members)))
# validate elements and return as list
return [sub(elem)
for sub, elem in zip(self.members, value)]
except Exception as exc:
raise BadValueError(u'Can not validate:', unicode(exc))
raise BadValueError('Can not validate:', str(exc))
def export_value(self, value):
"""returns a python object fit for serialisation"""
@ -648,11 +640,11 @@ class TupleOf(DataType):
def from_string(self, text):
value, rem = Parser.parse(text)
if rem:
raise ProtocolError(u'trailing garbage: %r' % rem)
raise ProtocolError('trailing garbage: %r' % rem)
return self(value)
def format_value(self, value, unit=None):
return u'(%s)' % (', '.join([sub.format_value(elem)
return '(%s)' % (', '.join([sub.format_value(elem)
for sub, elem in zip(self.members, value)]))
@ -661,19 +653,19 @@ class StructOf(DataType):
def __init__(self, optional=None, **members):
self.members = members
if not members:
raise BadValueError(u'Empty structs are not allowed!')
raise BadValueError('Empty structs are not allowed!')
self.optional = list(optional or [])
for name, subtype in list(members.items()):
if not isinstance(subtype, DataType):
raise ProgrammingError(
u'StructOf only works with named DataType objs as keyworded arguments!')
if not isinstance(name, (unicode, str)):
'StructOf only works with named DataType objs as keyworded arguments!')
if not isinstance(name, str):
raise ProgrammingError(
u'StructOf only works with named DataType objs as keyworded arguments!')
'StructOf only works with named DataType objs as keyworded arguments!')
for name in self.optional:
if name not in members:
raise ProgrammingError(
u'Only members of StructOf may be declared as optional!')
'Only members of StructOf may be declared as optional!')
self.default = dict((k,el.default) for k, el in members.items())
def export_datatype(self):
@ -685,8 +677,8 @@ class StructOf(DataType):
def __repr__(self):
opt = self.optional if self.optional else ''
return u'StructOf(%s%s)' % (u', '.join(
[u'%s=%s' % (n, repr(st)) for n, st in list(self.members.items())]), opt)
return 'StructOf(%s%s)' % (', '.join(
['%s=%s' % (n, repr(st)) for n, st in list(self.members.items())]), opt)
def __call__(self, value):
"""return the validated value or raise"""
@ -694,40 +686,40 @@ class StructOf(DataType):
# XXX: handle optional elements !!!
if len(list(value.keys())) != len(list(self.members.keys())):
raise BadValueError(
u'Illegal number of Arguments! Need %d arguments.' %
'Illegal number of Arguments! Need %d arguments.' %
len(list(self.members.keys())))
# validate elements and return as dict
return dict((unicode(k), self.members[k](v))
return dict((str(k), self.members[k](v))
for k, v in list(value.items()))
except Exception as exc:
raise BadValueError(u'Can not validate %s: %s' % (repr(value), unicode(exc)))
raise BadValueError('Can not validate %s: %s' % (repr(value), str(exc)))
def export_value(self, value):
"""returns a python object fit for serialisation"""
if len(list(value.keys())) != len(list(self.members.keys())):
raise BadValueError(
u'Illegal number of Arguments! Need %d arguments.' % len(
'Illegal number of Arguments! Need %d arguments.' % len(
list(self.members.keys())))
return dict((unicode(k), self.members[k].export_value(v))
return dict((str(k), self.members[k].export_value(v))
for k, v in list(value.items()))
def import_value(self, value):
"""returns a python object from serialisation"""
if len(list(value.keys())) != len(list(self.members.keys())):
raise BadValueError(
u'Illegal number of Arguments! Need %d arguments.' % len(
'Illegal number of Arguments! Need %d arguments.' % len(
list(self.members.keys())))
return dict((unicode(k), self.members[k].import_value(v))
return dict((str(k), self.members[k].import_value(v))
for k, v in list(value.items()))
def from_string(self, text):
value, rem = Parser.parse(text)
if rem:
raise ProtocolError(u'trailing garbage: %r' % rem)
raise ProtocolError('trailing garbage: %r' % rem)
return self(dict(value))
def format_value(self, value, unit=None):
return u'{%s}' % (', '.join(['%s=%s' % (k, self.members[k].format_value(v)) for k, v in sorted(value.items())]))
return '{%s}' % (', '.join(['%s=%s' % (k, self.members[k].format_value(v)) for k, v in sorted(value.items())]))
class CommandType(DataType):
@ -738,10 +730,10 @@ class CommandType(DataType):
def __init__(self, argument=None, result=None):
if argument is not None:
if not isinstance(argument, DataType):
raise BadValueError(u'CommandType: Argument type must be a DataType!')
raise BadValueError('CommandType: Argument type must be a DataType!')
if result is not None:
if not isinstance(result, DataType):
raise BadValueError(u'CommandType: Result type must be a DataType!')
raise BadValueError('CommandType: Result type must be a DataType!')
self.argument = argument
self.result = result
@ -757,23 +749,23 @@ class CommandType(DataType):
def __repr__(self):
argstr = repr(self.argument) if self.argument else ''
if self.result is None:
return u'CommandType(%s)' % argstr
return u'CommandType(%s)->%s' % (argstr, repr(self.result))
return 'CommandType(%s)' % argstr
return 'CommandType(%s)->%s' % (argstr, repr(self.result))
def __call__(self, value):
"""return the validated argument value or raise"""
return self.argument(value)
def export_value(self, value):
raise ProgrammingError(u'values of type command can not be transported!')
raise ProgrammingError('values of type command can not be transported!')
def import_value(self, value):
raise ProgrammingError(u'values of type command can not be transported!')
raise ProgrammingError('values of type command can not be transported!')
def from_string(self, text):
value, rem = Parser.parse(text)
if rem:
raise ProtocolError(u'trailing garbage: %r' % rem)
raise ProtocolError('trailing garbage: %r' % rem)
return self(value)
def format_value(self, value, unit=None):
@ -789,7 +781,7 @@ class DataTypeType(DataType):
returns the value or raises an appropriate exception"""
if isinstance(value, DataType):
return value
raise ProgrammingError(u'%r should be a DataType!' % value)
raise ProgrammingError('%r should be a DataType!' % value)
def export_value(self, value):
"""if needed, reformat value for transport"""
@ -872,7 +864,7 @@ class LimitsType(StructOf):
def __call__(self, value):
limits = StructOf.__call__(self, value)
if limits['max'] < limits['min']:
raise BadValueError(u'Maximum Value %s must be greater than minimum value %s!' % (limits['max'], limits['min']))
raise BadValueError('Maximum Value %s must be greater than minimum value %s!' % (limits['max'], limits['min']))
return limits
@ -925,4 +917,4 @@ def get_datatype(json):
try:
return DATATYPES[base](**args)
except (TypeError, AttributeError, KeyError):
raise BadValueError(u'invalid data descriptor: %r' % json)
raise BadValueError('invalid data descriptor: %r' % json)

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""Define (internal) SECoP Errors"""
from __future__ import division, print_function
class SECoPError(RuntimeError):

View File

@ -21,16 +21,14 @@
# *****************************************************************************
"""Define Mixin Features for real Modules implemented in the server"""
from __future__ import division, print_function
from secop.datatypes import ArrayOf, BoolType, EnumType, \
FloatRange, StringType, StructOf, TupleOf
from secop.metaclass import ModuleMeta, add_metaclass
from secop.metaclass import ModuleMeta
from secop.modules import Command, Parameter
@add_metaclass(ModuleMeta)
class Feature(object):
class Feature(object, metaclass=ModuleMeta):
"""all things belonging to a small, predefined functionality influencing the working of a module"""
pass

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
from __future__ import print_function
from os import path, listdir
import sys
import inspect

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
from __future__ import print_function
import os

View File

@ -21,7 +21,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
import sys

View File

@ -22,7 +22,6 @@
# *****************************************************************************
from __future__ import division, print_function
from os import path

View File

@ -22,7 +22,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
from secop.gui.params import ParameterView
from secop.gui.qt import QCheckBox, QDialog, QLabel, \
@ -30,20 +29,6 @@ from secop.gui.qt import QCheckBox, QDialog, QLabel, \
from secop.gui.util import loadUi
from secop.gui.valuewidgets import get_widget
try:
# py2
unicode(u'')
except NameError:
# py3
unicode = str # pylint: disable=redefined-builtin
#from secop.datatypes import ...
class CommandDialog(QDialog):
def __init__(self, cmdname, argument, parent=None):
@ -104,7 +89,7 @@ class ParameterGroup(QWidget):
self._row = 0
self._widgets = []
self.paramGroupBox.setTitle('Group: ' + unicode(groupname))
self.paramGroupBox.setTitle('Group: ' + str(groupname))
self.paramGroupBox.toggled.connect(self.on_toggle_clicked)
self.paramGroupBox.setChecked(False)
@ -293,7 +278,7 @@ class ModuleCtrl(QWidget):
label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Preferred)
# make 'display' label
view = QLabel(unicode(props[prop]))
view = QLabel(str(props[prop]))
view.setFont(self.font())
view.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Preferred)
view.setWordWrap(True)
@ -369,7 +354,7 @@ class ModuleCtrl(QWidget):
try:
self._node.setParameter(module, parameter, target)
except Exception as e:
QMessageBox.warning(self.parent(), 'Operation failed', unicode(e))
QMessageBox.warning(self.parent(), 'Operation failed', str(e))
def _updateValue(self, module, parameter, value):
if module != self._module:

View File

@ -21,7 +21,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
import json
import pprint
@ -33,15 +32,6 @@ from secop.gui.qt import QFont, QFontMetrics, QLabel, \
QMessageBox, QTextCursor, QWidget, pyqtSlot, toHtmlEscaped
from secop.gui.util import loadUi
try:
# py2
unicode(u'')
except NameError:
unicode = str # pylint: disable=redefined-builtin
class NodeCtrl(QWidget):
@ -334,6 +324,6 @@ class DrivableWidget(ReadableWidget):
def on_targetLineEdit_returnPressed(self):
self.target_go(self.targetLineEdit.text())
@pyqtSlot(unicode)
@pyqtSlot(str)
def on_targetComboBox_activated(self, selection):
self.target_go(selection)

View File

@ -21,7 +21,6 @@
#
# *****************************************************************************
from __future__ import print_function
from secop.datatypes import EnumType, FloatRange, IntRange
from secop.gui.qt import QPushButton as QButton
@ -30,14 +29,6 @@ from secop.gui.qt import QCheckBox, QLabel, QLineEdit, \
from secop.gui.util import loadUi
from secop.lib import formatExtendedStack
try:
# py2
unicode(u'')
except NameError:
unicode = str # pylint: disable=redefined-builtin
class ParameterWidget(QWidget):
setRequested = pyqtSignal(str, str, object) # module, parameter, target

View File

@ -21,19 +21,10 @@
#
# *****************************************************************************
from __future__ import division, print_function
from secop.gui.qt import QLabel, QSizePolicy, QWidget
from secop.gui.util import loadUi
try:
# py2
unicode(u'')
except NameError:
# py3
unicode = str # pylint: disable=redefined-builtin
class ParameterView(QWidget):

View File

@ -22,7 +22,6 @@
"""Import needed stuff from PyQt4/PyQt5"""
# pylint: disable=unused-import
from __future__ import division, print_function
import sys

View File

@ -21,7 +21,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
from os import path

View File

@ -21,7 +21,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
from secop.datatypes import ArrayOf, BLOBType, BoolType, EnumType, \
FloatRange, IntRange, StringType, StructOf, TupleOf, TextType

View File

@ -32,21 +32,20 @@ import subprocess
import sys
import threading
import traceback
import unicodedata
from os import path
repodir = path.abspath(path.join(path.dirname(__file__), u'..', u'..'))
repodir = path.abspath(path.join(path.dirname(__file__), '..', '..'))
CONFIG = {
u'piddir': os.path.join(repodir, u'pid'),
u'logdir': os.path.join(repodir, u'log'),
u'confdir': os.path.join(repodir, u'cfg'),
u'basedir': repodir,
} if os.path.exists(os.path.join(repodir, u'.git')) else {
u'piddir': u'/var/run/secop',
u'logdir': u'/var/log',
u'confdir': u'/etc/secop',
u'basedir': repodir,
'piddir': os.path.join(repodir, 'pid'),
'logdir': os.path.join(repodir, 'log'),
'confdir': os.path.join(repodir, 'etc'),
'basedir': repodir,
} if os.path.exists(os.path.join(repodir, '.git')) else {
'piddir': '/var/run/secop',
'logdir': '/var/log',
'confdir': '/etc/secop',
'basedir': repodir,
}

View File

@ -22,15 +22,9 @@
# *****************************************************************************
"""Enum class"""
from __future__ import division, print_function
__ALL__ = ['Enum']
try:
text_type = unicode # Py2
except NameError:
text_type = str # Py3
unicode = str # pylint: disable=redefined-builtin
class EnumMember(object):
"""represents one member of an Enum
@ -49,7 +43,7 @@ class EnumMember(object):
def __cmp__(self, other):
if isinstance(other, EnumMember):
other = other.value
if isinstance(other, (str, unicode)):
if isinstance(other, str):
if other in self.enum:
other = self.enum[other].value
try:
@ -73,7 +67,7 @@ class EnumMember(object):
if isinstance(other, int):
return other == self.value
# compare by name (for (in)equality only)
if isinstance(other, (str, unicode)):
if isinstance(other, str):
if other in self.enum:
return self.name == other
return False
@ -114,8 +108,6 @@ class EnumMember(object):
return self.value.__sub__(other.value if isinstance(other, EnumMember) else other)
def __mul__(self, other):
return self.value.__mul__(other.value if isinstance(other, EnumMember) else other)
def __div__(self, other):
return self.value.__div__(other.value if isinstance(other, EnumMember) else other)
def __truediv__(self, other):
return self.value.__truediv__(other.value if isinstance(other, EnumMember) else other)
def __floordiv__(self, other):
@ -137,8 +129,6 @@ class EnumMember(object):
return self.value.__rsub__(other.value if isinstance(other, EnumMember) else other)
def __rmul__(self, other):
return self.value.__rmul__(other.value if isinstance(other, EnumMember) else other)
def __rdiv__(self, other):
return self.value.__rdiv__(other.value if isinstance(other, EnumMember) else other)
def __rtruediv__(self, other):
return self.value.__rtruediv__(other.value if isinstance(other, EnumMember) else other)
def __rfloordiv__(self, other):
@ -181,10 +171,6 @@ class EnumMember(object):
def __float__(self):
return self.value.__float__()
#return NotImplemented # makes no sense
def __oct__(self):
return self.value.__oct__()
def __hex__(self):
return self.value.__hex__()
def __index__(self):
return self.value.__index__()
@ -234,7 +220,7 @@ class Enum(dict):
name=parent.name
# else:
# raise TypeError('Enum instances need a name or an Enum parent!')
if not isinstance(name, (str, text_type)):
if not isinstance(name, str):
raise TypeError('1st argument to Enum must be a name or an Enum!')
names = set()

View File

@ -1,44 +0,0 @@
# -*- coding: utf-8 -*-
# *****************************************************************************
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#
# Module authors:
# Enrico Faulhaber <enrico.faulhaber@frm2.tum.de>
#
# *****************************************************************************
"""Define metaclass helper"""
from __future__ import division, print_function
try:
# pylint: disable=unused-import
from six import add_metaclass # for py2/3 compat
except ImportError:
# copied from six v1.10.0
def add_metaclass(metaclass):
"""Class decorator for creating a class with a metaclass."""
def wrapper(cls):
orig_vars = cls.__dict__.copy()
slots = orig_vars.get('__slots__')
if slots is not None:
if isinstance(slots, str):
slots = [slots]
for slots_var in slots:
orig_vars.pop(slots_var)
orig_vars.pop('__dict__', None)
orig_vars.pop('__weakref__', None)
return metaclass(cls.__name__, cls.__bases__, orig_vars)
return wrapper

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""Define parsing helpers"""
from __future__ import division, print_function
import re
import time
@ -144,7 +143,7 @@ def format_args(args):
return ','.join(format_args(arg) for arg in args).join('[]')
if isinstance(args, tuple):
return ','.join(format_args(arg) for arg in args).join('()')
if isinstance(args, (str, unicode)):
if isinstance(args, str):
# XXX: check for 'easy' strings only and omit the ''
return repr(args)
return repr(args) # for floats/ints/...

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
"""Define pidfile helpers"""
from __future__ import division, print_function
import atexit
import os

View File

@ -23,7 +23,6 @@
"""Utilities for modules that require sequenced actions on value change."""
from __future__ import division, print_function
from time import sleep
@ -74,7 +73,7 @@ class SequencerMixin(object):
self._seq_fault_on_error = fault_on_error
self._seq_fault_on_stop = fault_on_stop
self._seq_stopflag = False
self._seq_phase = u''
self._seq_phase = ''
self._seq_error = None
self._seq_stopped = None
@ -116,7 +115,7 @@ class SequencerMixin(object):
the default is to only go into ALARM.
"""
if self.seq_is_alive():
raise IsBusyError(u'move sequence already in progress')
raise IsBusyError('move sequence already in progress')
self._seq_stopflag = False
self._seq_error = self._seq_stopped = None
@ -129,7 +128,7 @@ class SequencerMixin(object):
def read_status(self):
if self.seq_is_alive():
return self.Status.BUSY, u'moving: ' + self._seq_phase
return self.Status.BUSY, 'moving: ' + self._seq_phase
elif self._seq_error:
if self._seq_fault_on_error:
return self.Status.ERROR, self._seq_error
@ -138,9 +137,9 @@ class SequencerMixin(object):
if self._seq_fault_on_stop:
return self.Status.ERROR, self._seq_stopped
return self.Status.WARN, self._seq_stopped
if hasattr(self, u'read_hw_status'):
if hasattr(self, 'read_hw_status'):
return self.read_hw_status()
return self.Status.IDLE, u''
return self.Status.IDLE, ''
def do_stop(self):
if self.seq_is_alive():
@ -150,7 +149,7 @@ class SequencerMixin(object):
try:
self._seq_thread_inner(seq, store_init)
except Exception as e:
self.log.exception(u'unhandled error in sequence thread: %s', e)
self.log.exception('unhandled error in sequence thread: %s', e)
self._seq_error = str(e)
finally:
self._seq_thread = None
@ -159,11 +158,11 @@ class SequencerMixin(object):
def _seq_thread_inner(self, seq, store_init):
store = Namespace()
store.__dict__.update(store_init)
self.log.debug(u'sequence: starting, values %s', store_init)
self.log.debug('sequence: starting, values %s', store_init)
for step in seq:
self._seq_phase = step.desc
self.log.debug(u'sequence: entering phase: %s', step.desc)
self.log.debug('sequence: entering phase: %s', step.desc)
try:
i = 0
while True:
@ -171,10 +170,10 @@ class SequencerMixin(object):
result = step.func(store, *step.args)
if self._seq_stopflag:
if result:
self._seq_stopped = u'stopped while %s' % step.desc
self._seq_stopped = 'stopped while %s' % step.desc
else:
self._seq_stopped = u'stopped after %s' % step.desc
cleanup_func = step.kwds.get(u'cleanup', None)
self._seq_stopped = 'stopped after %s' % step.desc
cleanup_func = step.kwds.get('cleanup', None)
if callable(cleanup_func):
try:
cleanup_func(store, result, *step.args)
@ -188,6 +187,6 @@ class SequencerMixin(object):
i += 1
except Exception as e:
self.log.exception(
u'error in sequence step %r: %s', step.desc, e)
self._seq_error = u'during %s: %s' % (step.desc, e)
'error in sequence step %r: %s', step.desc, e)
self._seq_error = 'during %s: %s' % (step.desc, e)
break

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""Define Metaclass for Modules/Features"""
from __future__ import division, print_function
import time
from collections import OrderedDict

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""Define Baseclasses for real Modules implemented in the server"""
from __future__ import division, print_function
import sys
import time
@ -33,7 +32,6 @@ from secop.errors import ConfigError, ProgrammingError
from secop.lib import formatException, \
formatExtendedStack, mkthread, unset_value
from secop.lib.enum import Enum
from secop.lib.metaclass import add_metaclass
from secop.metaclass import ModuleMeta
from secop.params import PREDEFINED_ACCESSIBLES, Command, Override, Parameter, Parameters, Commands
from secop.properties import HasProperties, Property
@ -45,8 +43,7 @@ from secop.properties import HasProperties, Property
# from these base classes (how to do this?)
@add_metaclass(ModuleMeta)
class Module(HasProperties):
class Module(HasProperties, metaclass=ModuleMeta):
"""Basic Module
ALL secop Modules derive from this
@ -205,7 +202,7 @@ class Module(HasProperties):
# (self.name, k, e))
# note: this will call write_* methods which will
# write to the hardware, if possible!
if k != u'value':
if k != 'value':
setattr(self, k, v)
cfgdict.pop(k)

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""Define classes for Parameters/Commands and Overriding them"""
from __future__ import division, print_function
from collections import OrderedDict
@ -30,11 +29,6 @@ from secop.datatypes import CommandType, DataType, StringType, BoolType, EnumTyp
from secop.errors import ProgrammingError
from secop.properties import HasProperties, Property
try:
unicode
except NameError:
# pylint: disable=redefined-builtin
unicode = str # py3 compat
class CountedObj(object):
ctr = [0]
@ -54,8 +48,8 @@ class Accessible(HasProperties, CountedObj):
self.properties.update(kwds)
def __repr__(self):
return u'%s_%d(%s)' % (self.__class__.__name__, self.ctr, ',\n\t'.join(
[u'%s=%r' % (k, self.properties.get(k, v.default)) for k, v in sorted(self.__class__.properties.items())]))
return '%s_%d(%s)' % (self.__class__.__name__, self.ctr, ',\n\t'.join(
['%s=%r' % (k, self.properties.get(k, v.default)) for k, v in sorted(self.__class__.properties.items())]))
def copy(self):
# return a copy of ourselfs
@ -92,26 +86,26 @@ class Parameter(Accessible):
"""
properties = {
u'description': Property('Description of the Parameter', TextType(),
extname=u'description', mandatory=True),
u'datatype': Property('Datatype of the Parameter', DataTypeType(),
extname=u'datainfo', mandatory=True),
u'unit': Property('[legacy] unit of the parameter. This should now be on the datatype!', StringType(),
extname=u'unit', default=''), # goodie, should be on the datatype!
u'readonly': Property('Is the Parameter readonly? (vs. changeable via SECoP)', BoolType(),
extname=u'readonly', default=True),
u'group': Property('Optional parameter group this parameter belongs to', StringType(),
extname=u'group', default=''),
u'visibility': Property('Optional visibility hint', EnumType(u'visibility', user=1, advanced=2, expert=3),
extname=u'visibility', default=1),
u'constant': Property('Optional constant value for constant parameters', ValueType(),
extname=u'constant', default=None),
u'default': Property('Default (startup) value of this parameter if it can not be read from the hardware.',
'description': Property('Description of the Parameter', TextType(),
extname='description', mandatory=True),
'datatype': Property('Datatype of the Parameter', DataTypeType(),
extname='datainfo', mandatory=True),
'unit': Property('[legacy] unit of the parameter. This should now be on the datatype!', StringType(),
extname='unit', default=''), # goodie, should be on the datatype!
'readonly': Property('Is the Parameter readonly? (vs. changeable via SECoP)', BoolType(),
extname='readonly', default=True),
'group': Property('Optional parameter group this parameter belongs to', StringType(),
extname='group', default=''),
'visibility': Property('Optional visibility hint', EnumType('visibility', user=1, advanced=2, expert=3),
extname='visibility', default=1),
'constant': Property('Optional constant value for constant parameters', ValueType(),
extname='constant', default=None),
'default': Property('Default (startup) value of this parameter if it can not be read from the hardware.',
ValueType(), export=False, default=None, mandatory=False),
u'export': Property('Is this parameter accessible via SECoP? (vs. internal parameter)',
'export': Property('Is this parameter accessible via SECoP? (vs. internal parameter)',
OrType(BoolType(), StringType()), export=False, default=True),
u'poll': Property('Polling indicator', ValueType(), export=False, default=True), # check default value!
u'optional': Property('[Internal] is this parameter optional?', BoolType(), export=False, default=False),
'poll': Property('Polling indicator', ValueType(), export=False, default=True), # check default value!
'optional': Property('[Internal] is this parameter optional?', BoolType(), export=False, default=False),
}
value = None
@ -127,27 +121,27 @@ class Parameter(Accessible):
datatype = datatype()
else:
raise ValueError(
u'datatype MUST be derived from class DataType!')
'datatype MUST be derived from class DataType!')
kwds[u'description'] = description
kwds[u'datatype'] = datatype
kwds['description'] = description
kwds['datatype'] = datatype
super(Parameter, self).__init__(**kwds)
# note: auto-converts True/False to 1/0 which yield the expected
# behaviour...
self.properties[u'poll'] = int(self.poll)
self.properties['poll'] = int(self.poll)
if self.constant is not None:
self.properties[u'readonly'] = True
self.properties['readonly'] = True
# The value of the `constant` property should be the
# serialised version of the constant, or unset
constant = self.datatype(kwds[u'constant'])
self.properties[u'constant'] = self.datatype.export_value(constant)
constant = self.datatype(kwds['constant'])
self.properties['constant'] = self.datatype.export_value(constant)
# helper: unit should be set on the datatype, not on the parameter!
if self.unit:
self.datatype.unit = self.unit
self.properties[u'unit'] = ''
self.properties['unit'] = ''
# internal caching: value and timestamp of last change...
self.value = self.default
@ -161,7 +155,7 @@ class Parameter(Accessible):
return self.datatype.unit
def _set_unit_(self, unit):
print(u'DeprecationWarning: setting unit on the parameter is going to be removed')
print('DeprecationWarning: setting unit on the parameter is going to be removed')
self.datatype.unit = unit
unit = property(_get_unit_, _set_unit_)
@ -182,9 +176,9 @@ class Parameters(OrderedDict):
def __setitem__(self, key, value):
if value.export:
if isinstance(value, PREDEFINED_ACCESSIBLES.get(key, UnusedClass)):
value.properties[u'export'] = key
value.properties['export'] = key
else:
value.properties[u'export'] = '_' + key
value.properties['export'] = '_' + key
self.exported[value.export] = key
super(Parameters, self).__setitem__(key, value)
@ -216,22 +210,22 @@ class Override(CountedObj):
self.reorder = reorder
# allow to override description without keyword
if description:
self.kwds[u'description'] = description
self.kwds['description'] = description
# for now, do not use the Override ctr
# self.kwds['ctr'] = self.ctr
def __repr__(self):
return u'%s_%d(%s)' % (self.__class__.__name__, self.ctr, ', '.join(
[u'%s=%r' % (k, v) for k, v in sorted(self.kwds.items())]))
return '%s_%d(%s)' % (self.__class__.__name__, self.ctr, ', '.join(
['%s=%r' % (k, v) for k, v in sorted(self.kwds.items())]))
def apply(self, obj):
if isinstance(obj, Accessible):
props = obj.properties.copy()
if isinstance(obj, Parameter):
if u'constant' in self.kwds:
constant = obj.datatype(self.kwds.pop(u'constant'))
self.kwds[u'constant'] = obj.datatype.export_value(constant)
self.kwds[u'readonly'] = True
if 'constant' in self.kwds:
constant = obj.datatype(self.kwds.pop('constant'))
self.kwds['constant'] = obj.datatype.export_value(constant)
self.kwds['readonly'] = True
props.update(self.kwds)
if self.reorder:
@ -249,27 +243,27 @@ class Command(Accessible):
"""
# datatype is not listed (handled separately)
properties = {
u'description': Property('Description of the Command', TextType(),
extname=u'description', export=True, mandatory=True),
u'group': Property('Optional command group of the command.', StringType(),
extname=u'group', export=True, default=''),
u'visibility': Property('Optional visibility hint', EnumType(u'visibility', user=1, advanced=2, expert=3),
extname=u'visibility', export=True, default=1),
u'export': Property('[internal] Flag: is the command accessible via SECoP? (vs. pure internal use)',
'description': Property('Description of the Command', TextType(),
extname='description', export=True, mandatory=True),
'group': Property('Optional command group of the command.', StringType(),
extname='group', export=True, default=''),
'visibility': Property('Optional visibility hint', EnumType('visibility', user=1, advanced=2, expert=3),
extname='visibility', export=True, default=1),
'export': Property('[internal] Flag: is the command accessible via SECoP? (vs. pure internal use)',
OrType(BoolType(), StringType()), export=False, default=True),
u'optional': Property('[internal] is The comamnd optional to implement? (vs. mandatory',
'optional': Property('[internal] is The comamnd optional to implement? (vs. mandatory',
BoolType(), export=False, default=False, settable=False),
u'datatype': Property('[internal] datatype of the command, auto generated from \'argument\' and \'result\'',
DataTypeType(), extname=u'datainfo', mandatory=True),
u'argument': Property('Datatype of the argument to the command, or None.',
'datatype': Property('[internal] datatype of the command, auto generated from \'argument\' and \'result\'',
DataTypeType(), extname='datainfo', mandatory=True),
'argument': Property('Datatype of the argument to the command, or None.',
NoneOr(DataTypeType()), export=False, mandatory=True),
u'result': Property('Datatype of the result from the command, or None.',
'result': Property('Datatype of the result from the command, or None.',
NoneOr(DataTypeType()), export=False, mandatory=True),
}
def __init__(self, description, ctr=None, **kwds):
kwds[u'description'] = description
kwds[u'datatype'] = CommandType(kwds.get('argument', None), kwds.get('result', None))
kwds['description'] = description
kwds['datatype'] = CommandType(kwds.get('argument', None), kwds.get('result', None))
super(Command, self).__init__(**kwds)
if ctr is not None:
self.ctr = ctr
@ -289,10 +283,10 @@ class Command(Accessible):
# - readonly is mandatory for serialisation, but not for declaration in classes
r = self.exportProperties()
# if isinstance(self, Parameter):
# if u'readonly' not in r:
# r[u'readonly'] = self.__class__.properties[u'readonly'].default
# if u'datatype' in r:
# _d = r[u'datatype']
# if 'readonly' not in r:
# r['readonly'] = self.__class__.properties['readonly'].default
# if 'datatype' in r:
# _d = r['datatype']
# print(formatExtendedStack()) # for debug
return r

View File

@ -36,7 +36,6 @@ text -> string
further convertions are done by the validator of the datatype....
"""
from __future__ import division, print_function
from collections import OrderedDict
@ -55,7 +54,7 @@ class Parser(object):
length = l
l += 1
except ValueError:
if text[l - 1] in u'eE+-':
if text[l - 1] in 'eE+-':
l += 1
continue
if number is None:
@ -69,7 +68,7 @@ class Parser(object):
def parse_string(self, orgtext):
# handle quoted and unquoted strings correctly
text = orgtext.strip()
if text[0] in (u'"', u"'"):
if text[0] in ('"', u"'"):
# quoted string
quote = text[0]
idx = 0
@ -79,14 +78,14 @@ class Parser(object):
if idx == -1:
return None, orgtext
# check escapes!
if text[idx - 1] == u'\\':
if text[idx - 1] == '\\':
continue
return text[1:idx], text[idx + 1:]
# unquoted strings are terminated by comma or whitespace
idx = 0
while idx < len(text):
if text[idx] in u'\x09 ,.;:()[]{}<>-+*/\\!"§$%&=?#~+*\'´`^°|-':
if text[idx] in '\x09 ,.;:()[]{}<>-+*/\\!"§$%&=?#~+*\'´`^°|-':
break
idx += 1
return text[:idx] or None, text[idx:]
@ -94,10 +93,10 @@ class Parser(object):
def parse_tuple(self, orgtext):
text = orgtext.strip()
bra = text[0]
if bra not in u'([<':
if bra not in '([<':
return None, orgtext
# convert to closing bracket
bra = u')]>'[u'([<'.index(bra)]
bra = ')]>'['([<'.index(bra)]
reslist = []
# search for cosing bracket, collecting results
text = text[1:]
@ -111,7 +110,7 @@ class Parser(object):
if rem[0] == bra:
return tuple(reslist), rem[1:]
# eat separator
if rem[0] in u',;':
if rem[0] in ',;':
text = rem[1:]
else:
return None, rem
@ -119,19 +118,19 @@ class Parser(object):
def parse_dict(self, orgtext):
text = orgtext.strip()
if text[0] != u'{':
if text[0] != '{':
return None, orgtext
# keep ordering
result = OrderedDict()
# search for cosing bracket, collecting results
# watch for key=value or key:value pairs, separated by ,
text = text[1:]
while u'}' in text:
while '}' in text:
# first part is always a string
key, rem = self.parse_string(text)
if not key:
return None, orgtext
if rem[0] not in u':=':
if rem[0] not in ':=':
return None, rem
# eat separator
text = rem[1:]
@ -139,10 +138,10 @@ class Parser(object):
if not value:
return None, orgtext
result[key] = value
if rem[0] == u'}':
if rem[0] == '}':
return result, rem[1:]
if rem[0] not in u',;':
if rem[0] not in ',;':
return None, rem
# eat separator
text = rem[1:]
@ -152,17 +151,17 @@ class Parser(object):
text = orgtext.strip()
if not text:
return None, orgtext
if text[0] in u'+-.0123456789':
if text[0] in '+-.0123456789':
return self.parse_number(orgtext)
elif text[0] == u'{':
elif text[0] == '{':
return self.parse_dict(orgtext)
elif text[0] in u'([<':
elif text[0] in '([<':
return self.parse_tuple(orgtext)
return self.parse_string(orgtext)
def parse(self, orgtext):
print("parsing %r" % orgtext)
res, rem = self.parse_sub(orgtext)
if rem and rem[0] in u',;':
return self.parse_sub(u'[%s]' % orgtext)
if rem and rem[0] in ',;':
return self.parse_sub('[%s]' % orgtext)
return res, rem

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""Pathes. how to find what and where..."""
from __future__ import division, print_function
import sys
from os import path

View File

@ -21,14 +21,11 @@
# *****************************************************************************
"""Define validated data types."""
from __future__ import division, print_function
from collections import OrderedDict
from secop.datatypes import ValueType, DataType
from secop.errors import ProgrammingError, ConfigError
from secop.lib.metaclass import add_metaclass
# storage for 'properties of a property'
@ -44,7 +41,7 @@ class Property(object):
# the VALUES of the properties are on the instances!
def __init__(self, description, datatype, default=None, extname='', export=False, mandatory=False, settable=True):
if not callable(datatype):
raise ValueError(u'datatype MUST be a valid DataType or a basic_validator')
raise ValueError('datatype MUST be a valid DataType or a basic_validator')
self.description = description
self.default = datatype.default if default is None else datatype(default)
self.datatype = datatype
@ -54,7 +51,7 @@ class Property(object):
self.settable = settable or mandatory # settable means settable from the cfg file
def __repr__(self):
return u'Property(%s, %s, default=%r, extname=%r, export=%r, mandatory=%r)' % (
return 'Property(%s, %s, default=%r, extname=%r, export=%r, mandatory=%r)' % (
self.description, self.datatype, self.default, self.extname, self.export, self.mandatory)
@ -67,16 +64,16 @@ class Properties(OrderedDict):
"""
def __setitem__(self, key, value):
if not isinstance(value, Property):
raise ProgrammingError(u'setting property %r on classes is not supported!' % key)
raise ProgrammingError('setting property %r on classes is not supported!' % key)
# make sure, extname is valid if export is True
if not value.extname and value.export:
value.extname = u'_%s' % key # generate custom kex
value.extname = '_%s' % key # generate custom kex
elif value.extname and not value.export:
value.export = True
OrderedDict.__setitem__(self, key, value)
def __delitem__(self, key):
raise ProgrammingError(u'deleting Properties is not supported!')
raise ProgrammingError('deleting Properties is not supported!')
class PropertyMeta(type):
@ -112,13 +109,12 @@ class PropertyMeta(type):
return self.properties.get(pname, val)
if k in attrs:
if not isinstance(attrs[k], property):
raise ProgrammingError(u'Name collision with property %r' % k)
raise ProgrammingError('Name collision with property %r' % k)
setattr(newtype, k, property(getter))
return newtype
@add_metaclass(PropertyMeta)
class HasProperties(object):
class HasProperties(object, metaclass=PropertyMeta):
properties = {}
def __init__(self, supercall_init=True):

View File

@ -36,7 +36,6 @@ Interface to the modules:
- remove_module(modulename_or_obj): removes the module (during shutdown)
"""
from __future__ import division, print_function
import threading
from collections import OrderedDict
@ -50,12 +49,6 @@ from secop.protocol.messages import COMMANDREPLY, DESCRIPTIONREPLY, \
DISABLEEVENTSREPLY, ENABLEEVENTSREPLY, ERRORPREFIX, EVENTREPLY, \
HEARTBEATREPLY, IDENTREPLY, IDENTREQUEST, READREPLY, WRITEREPLY
try:
unicode
except NameError:
# no unicode on py3
unicode = str # pylint: disable=redefined-builtin
class Dispatcher(object):
@ -101,7 +94,7 @@ class Dispatcher(object):
"""called by modules param setters to notify subscribers of new values
"""
# argument pname is no longer used here - should we remove it?
msg = (EVENTREPLY, u'%s:%s' % (moduleobj.name, pobj.export),
msg = (EVENTREPLY, '%s:%s' % (moduleobj.name, pobj.export),
[pobj.export_value(), dict(t=pobj.timestamp)])
self.broadcast_event(msg)
@ -113,7 +106,7 @@ class Dispatcher(object):
# argument pname is no longer used here - should we remove it?
if not isinstance(err, SECoPError):
err = InternalError(err)
msg = (ERRORPREFIX + EVENTREPLY, u'%s:%s' % (moduleobj.name, pobj.export),
msg = (ERRORPREFIX + EVENTREPLY, '%s:%s' % (moduleobj.name, pobj.export),
# error-report !
[err.name, repr(err), dict(t=currenttime())])
self.broadcast_event(msg)
@ -125,7 +118,7 @@ class Dispatcher(object):
if not ':' in eventname:
# also remove 'more specific' subscriptions
for k, v in self._subscriptions.items():
if k.startswith(u'%s:' % eventname):
if k.startswith('%s:' % eventname):
v.discard(conn)
if eventname in self._subscriptions:
self._subscriptions[eventname].discard(conn)
@ -143,7 +136,7 @@ class Dispatcher(object):
self._active_connections.discard(conn)
def register_module(self, moduleobj, modulename, export=True):
self.log.debug(u'registering module %r as %s (export=%r)' %
self.log.debug('registering module %r as %s (export=%r)' %
(moduleobj, modulename, export))
self._modules[modulename] = moduleobj
if export:
@ -154,7 +147,7 @@ class Dispatcher(object):
return self._modules[modulename]
elif modulename in list(self._modules.values()):
return modulename
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
def remove_module(self, modulename_or_obj):
moduleobj = self.get_module(modulename_or_obj)
@ -163,7 +156,7 @@ class Dispatcher(object):
self._export.remove(modulename)
self._modules.pop(modulename)
self._subscriptions.pop(modulename, None)
for k in [k for k in self._subscriptions if k.startswith(u'%s:' % modulename)]:
for k in [kk for kk in self._subscriptions if kk.startswith('%s:' % modulename)]:
self._subscriptions.pop(k, None)
def list_module_names(self):
@ -171,52 +164,52 @@ class Dispatcher(object):
return self._export[:]
def export_accessibles(self, modulename):
self.log.debug(u'export_accessibles(%r)' % modulename)
self.log.debug('export_accessibles(%r)' % modulename)
if modulename in self._export:
# omit export=False params!
res = OrderedDict()
for aobj in self.get_module(modulename).accessibles.values():
if aobj.export:
res[aobj.export] = aobj.for_export()
self.log.debug(u'list accessibles for module %s -> %r' %
self.log.debug('list accessibles for module %s -> %r' %
(modulename, res))
return res
self.log.debug(u'-> module is not to be exported!')
self.log.debug('-> module is not to be exported!')
return OrderedDict()
def get_descriptive_data(self):
"""returns a python object which upon serialisation results in the descriptive data"""
# XXX: be lazy and cache this?
result = {u'modules': OrderedDict()}
result = {'modules': OrderedDict()}
for modulename in self._export:
module = self.get_module(modulename)
if not module.properties.get('export', False):
continue
# some of these need rework !
mod_desc = {u'accessibles': self.export_accessibles(modulename)}
mod_desc = {'accessibles': self.export_accessibles(modulename)}
mod_desc.update(module.exportProperties())
mod_desc.pop('export', False)
result[u'modules'][modulename] = mod_desc
result[u'equipment_id'] = self.equipment_id
result[u'firmware'] = u'FRAPPY - The Python Framework for SECoP'
result[u'version'] = u'2019.08'
result['modules'][modulename] = mod_desc
result['equipment_id'] = self.equipment_id
result['firmware'] = 'FRAPPY - The Python Framework for SECoP'
result['version'] = '2019.08'
result.update(self.nodeprops)
return result
def _execute_command(self, modulename, exportedname, argument=None):
moduleobj = self.get_module(modulename)
if moduleobj is None:
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
cmdname = moduleobj.commands.exported.get(exportedname, None)
if cmdname is None:
raise NoSuchCommandError(u'Module has no command %r on this SEC-Node!' % exportedname)
raise NoSuchCommandError('Module has no command %r on this SEC-Node!' % exportedname)
cmdspec = moduleobj.commands[cmdname]
if argument is None and cmdspec.datatype.argument is not None:
raise BadValueError(u'Command needs an argument!')
raise BadValueError('Command needs an argument!')
if argument is not None and cmdspec.datatype.argument is None:
raise BadValueError(u'Command takes no argument!')
raise BadValueError('Command takes no argument!')
if cmdspec.datatype.argument:
# validate!
@ -224,7 +217,7 @@ class Dispatcher(object):
# now call func
# note: exceptions are handled in handle_request, not here!
func = getattr(moduleobj, u'do_' + cmdname)
func = getattr(moduleobj, 'do_' + cmdname)
res = func(argument) if argument else func()
# pipe through cmdspec.datatype.result
@ -236,20 +229,20 @@ class Dispatcher(object):
def _setParameterValue(self, modulename, exportedname, value):
moduleobj = self.get_module(modulename)
if moduleobj is None:
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
pname = moduleobj.parameters.exported.get(exportedname, None)
if pname is None:
raise NoSuchParameterError(u'Module has no parameter %r on this SEC-Node!' % exportedname)
raise NoSuchParameterError('Module has no parameter %r on this SEC-Node!' % exportedname)
pobj = moduleobj.parameters[pname]
if pobj.constant is not None:
raise ReadOnlyError(u'This parameter is constant and can not be accessed remotely.')
raise ReadOnlyError('This parameter is constant and can not be accessed remotely.')
if pobj.readonly:
raise ReadOnlyError(u'This parameter can not be changed remotely.')
raise ReadOnlyError('This parameter can not be changed remotely.')
# validate!
value = pobj.datatype(value)
writefunc = getattr(moduleobj, u'write_%s' % pname, None)
writefunc = getattr(moduleobj, 'write_%s' % pname, None)
# note: exceptions are handled in handle_request, not here!
if writefunc:
# return value is ignored here, as it is automatically set on the pobj and broadcast
@ -261,18 +254,18 @@ class Dispatcher(object):
def _getParameterValue(self, modulename, exportedname):
moduleobj = self.get_module(modulename)
if moduleobj is None:
raise NoSuchModuleError(u'Module does not exist on this SEC-Node!')
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
pname = moduleobj.parameters.exported.get(exportedname, None)
if pname is None:
raise NoSuchParameterError(u'Module has no parameter %r on this SEC-Node!' % exportedname)
raise NoSuchParameterError('Module has no parameter %r on this SEC-Node!' % exportedname)
pobj = moduleobj.parameters[pname]
if pobj.constant is not None:
# really needed? we could just construct a readreply instead....
#raise ReadOnlyError(u'This parameter is constant and can not be accessed remotely.')
#raise ReadOnlyError('This parameter is constant and can not be accessed remotely.')
return pobj.datatype.export_value(pobj.constant)
readfunc = getattr(moduleobj, u'read_%s' % pname, None)
readfunc = getattr(moduleobj, 'read_%s' % pname, None)
if readfunc:
# should also update the pobj (via the setter from the metaclass)
# note: exceptions are handled in handle_request, not here!
@ -288,7 +281,7 @@ class Dispatcher(object):
will call 'queue_async_reply(data)' on conn or return reply
"""
self.log.debug(u'Dispatcher: handling msg: %s' % repr(msg))
self.log.debug('Dispatcher: handling msg: %s' % repr(msg))
# play thread safe !
# XXX: ONLY ONE REQUEST (per dispatcher) AT A TIME
@ -298,8 +291,8 @@ class Dispatcher(object):
if action == IDENTREQUEST:
action, specifier, data = '_ident', None, None
self.log.debug(u'Looking for handle_%s' % action)
handler = getattr(self, u'handle_%s' % action, None)
self.log.debug('Looking for handle_%s' % action)
handler = getattr(self, 'handle_%s' % action, None)
if handler:
return handler(conn, specifier, data)
@ -319,28 +312,28 @@ class Dispatcher(object):
def handle_read(self, conn, specifier, data):
if data:
raise ProtocolError('read requests don\'t take data!')
modulename, pname = specifier, u'value'
modulename, pname = specifier, 'value'
if ':' in specifier:
modulename, pname = specifier.split(':', 1)
# XXX: trigger polling and force sending event ???
return (READREPLY, specifier, list(self._getParameterValue(modulename, pname)))
def handle_change(self, conn, specifier, data):
modulename, pname = specifier, u'value'
modulename, pname = specifier, 'value'
if ':' in specifier:
modulename, pname = specifier.split(u':', 1)
modulename, pname = specifier.split(':', 1)
return (WRITEREPLY, specifier, list(self._setParameterValue(modulename, pname, data)))
def handle_do(self, conn, specifier, data):
# XXX: should this be done asyncron? we could just return the reply in
# that case
modulename, cmd = specifier.split(u':', 1)
modulename, cmd = specifier.split(':', 1)
return (COMMANDREPLY, specifier, list(self._execute_command(modulename, cmd, data)))
def handle_ping(self, conn, specifier, data):
if data:
raise ProtocolError('ping requests don\'t take data!')
return (HEARTBEATREPLY, specifier, [None, {u't':currenttime()}])
return (HEARTBEATREPLY, specifier, [None, {'t':currenttime()}])
def handle_activate(self, conn, specifier, data):
if data:
@ -348,7 +341,7 @@ class Dispatcher(object):
if specifier:
modulename, exportedname = specifier, None
if ':' in specifier:
modulename, exportedname = specifier.split(u':', 1)
modulename, exportedname = specifier.split(':', 1)
if modulename not in self._export:
raise NoSuchModuleError('Module does not exist on this SEC-Node!')
moduleobj = self.get_module(modulename)
@ -373,7 +366,7 @@ class Dispatcher(object):
moduleobj = self._modules.get(modulename, None)
if pname:
pobj = moduleobj.accessibles[pname]
updmsg = (EVENTREPLY, u'%s:%s' % (modulename, pobj.export),
updmsg = (EVENTREPLY, '%s:%s' % (modulename, pobj.export),
[pobj.export_value(), dict(t=pobj.timestamp)])
conn.queue_async_reply(updmsg)
continue
@ -383,7 +376,7 @@ class Dispatcher(object):
if not pobj.export:
continue
# can not use announce_update here, as this will send to all clients
updmsg = (EVENTREPLY, u'%s:%s' % (modulename, pobj.export),
updmsg = (EVENTREPLY, '%s:%s' % (modulename, pobj.export),
[pobj.export_value(), dict(t=pobj.timestamp)])
conn.queue_async_reply(updmsg)
return (ENABLEEVENTSREPLY, specifier, None) if specifier else (ENABLEEVENTSREPLY, None, None)

View File

@ -28,7 +28,7 @@ SPACE = b' '
def encode_msg_frame(action, specifier=None, data=None):
""" encode a msg_tripel into an msg_frame, ready to be sent
action (and optional specifier) are unicode strings,
action (and optional specifier) are str strings,
data may be an json-yfied python object"""
action = action.encode('utf-8')
if specifier is None:
@ -54,7 +54,7 @@ def get_msg(_bytes):
def decode_msg(msg):
"""decode the (binary) msg into a (unicode) msg_tripel"""
"""decode the (binary) msg into a (str) msg_tripel"""
# check for leading/trailing CR and remove it
res = msg.split(b' ', 2)
action = res[0].decode('utf-8')

View File

@ -19,11 +19,11 @@
#
# *****************************************************************************
"""provides tcp interface to the SECoP Server"""
from __future__ import division, print_function
import collections
import socket
import sys
import socket
import collections
import socketserver
from secop.datatypes import StringType, IntRange, BoolType
from secop.errors import SECoPError
@ -34,17 +34,10 @@ from secop.protocol.interface import decode_msg, encode_msg_frame, get_msg
from secop.protocol.messages import ERRORPREFIX, \
HELPREPLY, HELPREQUEST, HelpMessage
try:
import socketserver # py3
except ImportError:
import SocketServer as socketserver # py2
DEF_PORT = 10767
MESSAGE_READ_SIZE = 1024
CR = b'\r'
SPACE = b' '

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""provide a zmq server"""
from __future__ import division, print_function
# tbd.

View File

@ -20,50 +20,49 @@
#
# *****************************************************************************
"""Define SECoP Messages"""
from __future__ import division, print_function
# allowed actions:
IDENTREQUEST = u'*IDN?' # literal
IDENTREQUEST = '*IDN?' # literal
# literal! first part is fixed!
IDENTREPLY = u'SINE2020&ISSE,SECoP,V2019-08-20,v1.0 RC2'
IDENTREPLY = 'SINE2020&ISSE,SECoP,V2019-08-20,v1.0 RC2'
DESCRIPTIONREQUEST = u'describe' # literal
DESCRIPTIONREPLY = u'describing' # +<id> +json
DESCRIPTIONREQUEST = 'describe' # literal
DESCRIPTIONREPLY = 'describing' # +<id> +json
ENABLEEVENTSREQUEST = u'activate' # literal + optional spec
ENABLEEVENTSREPLY = u'active' # literal + optional spec, is end-of-initial-data-transfer
ENABLEEVENTSREQUEST = 'activate' # literal + optional spec
ENABLEEVENTSREPLY = 'active' # literal + optional spec, is end-of-initial-data-transfer
DISABLEEVENTSREQUEST = u'deactivate' # literal + optional spec
DISABLEEVENTSREPLY = u'inactive' # literal + optional spec
DISABLEEVENTSREQUEST = 'deactivate' # literal + optional spec
DISABLEEVENTSREPLY = 'inactive' # literal + optional spec
COMMANDREQUEST = u'do' # +module:command +json args (if needed)
COMMANDREQUEST = 'do' # +module:command +json args (if needed)
# +module:command +json args (if needed) # send after the command finished !
COMMANDREPLY = u'done'
COMMANDREPLY = 'done'
# +module[:parameter] +json_value
WRITEREQUEST = u'change'
WRITEREQUEST = 'change'
# +module[:parameter] +json_value # send with the read back value
WRITEREPLY = u'changed'
WRITEREPLY = 'changed'
# +module[:parameter] +json_value
BUFFERREQUEST = u'buffer'
BUFFERREQUEST = 'buffer'
# +module[:parameter] +json_value # send with the read back value
BUFFERREPLY = u'buffered'
BUFFERREPLY = 'buffered'
# +module[:parameter] -> NO direct reply, calls POLL internally!
READREQUEST = u'read'
READREPLY = u'reply' # See Issue 54
READREQUEST = 'read'
READREPLY = 'reply' # See Issue 54
EVENTREPLY = u'update' # +module[:parameter] +json_value (value, qualifiers_as_dict)
EVENTREPLY = 'update' # +module[:parameter] +json_value (value, qualifiers_as_dict)
HEARTBEATREQUEST = u'ping' # +nonce_without_space
HEARTBEATREPLY = u'pong' # +nonce_without_space
HEARTBEATREQUEST = 'ping' # +nonce_without_space
HEARTBEATREPLY = 'pong' # +nonce_without_space
ERRORPREFIX = u'error_' # + specifier + json_extended_info(error_report)
ERRORPREFIX = 'error_' # + specifier + json_extended_info(error_report)
HELPREQUEST = u'help' # literal
HELPREPLY = u'helping' # +line number +json_text
HELPREQUEST = 'help' # literal
HELPREPLY = 'helping' # +line number +json_text
# helper mapping to find the REPLY for a REQUEST
REQUEST2REPLY = {

View File

@ -21,12 +21,12 @@
#
# *****************************************************************************
"""Define helpers"""
from __future__ import division, print_function
import ast
import os
import threading
import ast
import time
import threading
import configparser
from collections import OrderedDict
from daemon import DaemonContext
@ -34,19 +34,12 @@ from daemon import DaemonContext
from secop.errors import ConfigError
from secop.lib import formatException, get_class, getGeneralConfig
try:
import configparser # py3
except ImportError:
import ConfigParser as configparser # py2
try:
import daemon.pidlockfile as pidlockfile
except ImportError:
import daemon.pidfile as pidlockfile
class Server(object):
# list allowed section prefixes
# if mapped dict does not exist -> section need a 'class' option
@ -66,12 +59,12 @@ class Server(object):
if os.path.abspath(name) == name and os.path.exists(name) and \
name.endswith('.cfg'):
self._cfgfile = name
self._pidfile = os.path.join(cfg[u'piddir'],
name[:-4].replace(os.path.sep, u'_') + u'.pid')
self._pidfile = os.path.join(cfg['piddir'],
name[:-4].replace(os.path.sep, '_') + '.pid')
name = os.path.basename(name[:-4])
else:
self._cfgfile = os.path.join(cfg[u'confdir'], name + u'.cfg')
self._pidfile = os.path.join(cfg[u'piddir'], name + u'.pid')
self._cfgfile = os.path.join(cfg['confdir'], name + '.cfg')
self._pidfile = os.path.join(cfg['piddir'], name + '.pid')
self._name = name
@ -87,7 +80,7 @@ class Server(object):
pidfile = pidlockfile.TimeoutPIDLockFile(self._pidfile)
if pidfile.is_locked():
self.log.error(u'Pidfile already exists. Exiting')
self.log.error('Pidfile already exists. Exiting')
with DaemonContext(
pidfile=pidfile,
@ -101,10 +94,10 @@ class Server(object):
print(formatException(verbose=True))
raise
self.log.info(u'startup done, handling transport messages')
self.log.info('startup done, handling transport messages')
self._threads = set()
for ifname, ifobj in self.interfaces.items():
self.log.debug(u'starting thread for interface %r' % ifname)
self.log.debug('starting thread for interface %r' % ifname)
t = threading.Thread(target=ifobj.serve_forever)
t.daemon = True
t.start()
@ -113,78 +106,78 @@ class Server(object):
time.sleep(1)
for t in self._threads:
if not t.is_alive():
self.log.debug(u'thread %r died (%d still running)' %
self.log.debug('thread %r died (%d still running)' %
(t, len(self._threads)))
t.join()
self._threads.discard(t)
def _processCfg(self):
self.log.debug(u'Parse config file %s ...' % self._cfgfile)
self.log.debug('Parse config file %s ...' % self._cfgfile)
parser = configparser.SafeConfigParser()
parser.optionxform = str
if not parser.read([self._cfgfile]):
self.log.error(u'Couldn\'t read cfg file !')
raise ConfigError(u'Couldn\'t read cfg file %r' % self._cfgfile)
self.log.error('Couldn\'t read cfg file !')
raise ConfigError('Couldn\'t read cfg file %r' % self._cfgfile)
for kind, devtype, classmapping in self.CFGSECTIONS:
kinds = u'%ss' % kind
kinds = '%ss' % kind
objs = OrderedDict()
self.__dict__[kinds] = objs
for section in parser.sections():
prefix = u'%s ' % kind
prefix = '%s ' % kind
if section.lower().startswith(prefix):
name = section[len(prefix):]
opts = dict(item for item in parser.items(section))
if u'class' in opts:
cls = opts.pop(u'class')
if 'class' in opts:
cls = opts.pop('class')
else:
if not classmapping:
self.log.error(u'%s %s needs a class option!' % (kind.title(), name))
raise ConfigError(u'cfgfile %r: %s %s needs a class option!' %
self.log.error('%s %s needs a class option!' % (kind.title(), name))
raise ConfigError('cfgfile %r: %s %s needs a class option!' %
(self._cfgfile, kind.title(), name))
type_ = opts.pop(u'type', devtype)
type_ = opts.pop('type', devtype)
cls = classmapping.get(type_, None)
if not cls:
self.log.error(u'%s %s needs a type option (select one of %s)!' %
self.log.error('%s %s needs a type option (select one of %s)!' %
(kind.title(), name, ', '.join(repr(r) for r in classmapping)))
raise ConfigError(u'cfgfile %r: %s %s needs a type option (select one of %s)!' %
raise ConfigError('cfgfile %r: %s %s needs a type option (select one of %s)!' %
(self._cfgfile, kind.title(), name, ', '.join(repr(r) for r in classmapping)))
# MAGIC: transform \n.\n into \n\n which are normally stripped
# by the ini parser
for k in opts:
v = opts[k]
while u'\n.\n' in v:
v = v.replace(u'\n.\n', u'\n\n')
while '\n.\n' in v:
v = v.replace('\n.\n', '\n\n')
try:
opts[k] = ast.literal_eval(v)
except Exception:
opts[k] = v
# try to import the class, raise if this fails
self.log.debug(u'Creating %s %s ...' % (kind.title(), name))
self.log.debug('Creating %s %s ...' % (kind.title(), name))
# cls.__init__ should pop all used args from options!
logname = u'dispatcher' if kind == u'node' else u'%s_%s' % (kind, name.lower())
logname = 'dispatcher' if kind == 'node' else '%s_%s' % (kind, name.lower())
obj = get_class(cls)(name, self.log.getChild(logname), opts, self)
if opts:
raise ConfigError(u'%s %s: class %s: don\'t know how to handle option(s): %s' %
(kind, name, cls, u', '.join(opts)))
raise ConfigError('%s %s: class %s: don\'t know how to handle option(s): %s' %
(kind, name, cls, ', '.join(opts)))
# all went well so far
objs[name] = obj
# following line is the reason for 'node' beeing the first entry in CFGSECTIONS
if len(self.nodes) != 1:
raise ConfigError(u'cfgfile %r: needs exactly one node section!' % self._cfgfile)
raise ConfigError('cfgfile %r: needs exactly one node section!' % self._cfgfile)
self.dispatcher, = tuple(self.nodes.values())
pollTable = dict()
# all objs created, now start them up and interconnect
for modname, modobj in self.modules.items():
self.log.info(u'registering module %r' % modname)
self.log.info('registering module %r' % modname)
self.dispatcher.register_module(modobj, modname, modobj.properties['export'])
try:
modobj.pollerClass.add_to_table(pollTable, modobj)
@ -208,8 +201,8 @@ class Server(object):
# poller.start must return either a timeout value or None (default 30 sec)
timeout = poller.start(started_callback=event.set) or 30
start_events.append((time.time() + timeout, repr(poller), event))
self.log.info(u'waiting for modules and pollers being started')
self.log.info('waiting for modules and pollers being started')
for deadline, name, event in sorted(start_events):
if not event.wait(timeout=max(0, deadline - time.time())):
self.log.info('WARNING: timeout when starting %s' % name)
self.log.info(u'all modules and pollers started')
self.log.info('all modules and pollers started')

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""Define Simulation classes"""
from __future__ import division, print_function
import random
from time import sleep

View File

@ -23,7 +23,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
import os.path
from subprocess import PIPE, Popen

View File

@ -20,7 +20,6 @@
# *****************************************************************************
"""playing implementation of a (simple) simulated cryostat"""
from __future__ import division, print_function
import random
import time

View File

@ -20,7 +20,6 @@
# *****************************************************************************
"""testing devices"""
from __future__ import division, print_function
import random
import threading

View File

@ -20,7 +20,6 @@
# *****************************************************************************
"""testing devices"""
from __future__ import division, print_function
import random
@ -28,15 +27,6 @@ from secop.datatypes import FloatRange, StringType
from secop.modules import Communicator, Drivable, Parameter, Readable, Override
from secop.params import Command
try:
# py2
unicode
except NameError:
# py3
unicode = str # pylint: disable=redefined-builtin
class LN2(Readable):
"""Just a readable.
@ -104,4 +94,4 @@ class Lower(Communicator):
'communicate': Command('lowercase a string', argument=StringType(), result=StringType(), export='communicate'),
}
def do_communicate(self, request):
return unicode(request).lower()
return str(request).lower()

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
from __future__ import absolute_import, division, print_function
from secop.datatypes import EnumType, FloatRange, StringType
from secop.modules import Drivable, Parameter, Readable

View File

@ -25,7 +25,6 @@
# partially borrowed from nicos
from __future__ import division, print_function
import math

View File

@ -27,7 +27,6 @@
Here we support devices which fulfill the official
MLZ TANGO interface for the respective device classes.
"""
from __future__ import division, print_function
import re
import threading

View File

@ -22,7 +22,6 @@
#
# *****************************************************************************
from __future__ import division, print_function
from glob import glob
from os import listdir, path

View File

@ -1,5 +1,4 @@
# content of conftest.py
from __future__ import division, print_function
import pytest

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
"""test basic validators."""
from __future__ import division, print_function
# no fixtures needed
import pytest
@ -42,9 +41,9 @@ class unprintable(object):
[PositiveIntProperty, ['x', 1.9, '-9', '1e-4'], [1, '1']],
[NonNegativeIntProperty, ['x', 1.9, '-9', '1e-6'], [0, '1']],
[BoolProperty, ['x', 3], ['on', 'off', True, False]],
[StringProperty, [unprintable()], [u'1', 1.2, [{}]]],
[UnitProperty, [unprintable(), '3', 9], [u'mm', 'Gbarn', 'acre']],
[FmtStrProperty, [1, None, 'a', '%f'], [u'%.0e', u'%.3f','%.1g']],
[StringProperty, [unprintable()], ['1', 1.2, [{}]]],
[UnitProperty, [unprintable(), '3', 9], ['mm', 'Gbarn', 'acre']],
[FmtStrProperty, [1, None, 'a', '%f'], ['%.0e', '%.3f','%.1g']],
])
def test_validators(validators_args):
v, fails, oks = validators_args
@ -72,7 +71,7 @@ def test_checker_fails(checker_inits):
@pytest.mark.parametrize('checker_args', [
[OneOfProperty(1,2,3), ['x', None, 4], [1, 2, 3]],
[NoneOr(IntProperty), ['a', 1.2, '1.2'], [None, 1, '-1', '999999999999999']],
[EnumProperty(a=1, b=2), ['x', None, 3], [u'a', 'b', 1, 2]],
[EnumProperty(a=1, b=2), ['x', None, 3], ['a', 'b', 1, 2]],
[TupleProperty(IntProperty, StringProperty), [1, 'a', ('x', 2)], [(1,'x')]],
])
def test_checkers(checker_args):

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
"""test base client."""
from __future__ import division, print_function
from collections import OrderedDict

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""test data types."""
from __future__ import division, print_function
# no fixtures needed
import pytest
@ -56,34 +55,34 @@ def test_FloatRange():
with pytest.raises(ValueError):
dt(-9)
with pytest.raises(ValueError):
dt(u'XX')
dt('XX')
with pytest.raises(ValueError):
dt([19, u'X'])
dt([19, 'X'])
dt(1)
dt(0)
dt(13.14 - 10) # raises an error, if resolution is not handled correctly
assert dt.export_value(-2.718) == -2.718
assert dt.import_value(-2.718) == -2.718
with pytest.raises(ValueError):
FloatRange(u'x', u'Y')
FloatRange('x', 'Y')
# check that unit can be changed
dt.unit = u'K'
assert dt.export_datatype() == {'type': 'double', 'min':-3.14, 'max':3.14, 'unit': u'K'}
dt.unit = 'K'
assert dt.export_datatype() == {'type': 'double', 'min':-3.14, 'max':3.14, 'unit': 'K'}
dt = FloatRange()
copytest(dt)
assert dt.export_datatype() == {'type': 'double'}
dt = FloatRange(unit=u'X', fmtstr=u'%.2f', absolute_resolution=1,
dt = FloatRange(unit='X', fmtstr='%.2f', absolute_resolution=1,
relative_resolution=0.1)
copytest(dt)
assert dt.export_datatype() == {'type': 'double', 'unit':'X', 'fmtstr':'%.2f',
'absolute_resolution':1.0,
'relative_resolution':0.1}
assert dt(4) == 4
assert dt.format_value(3.14) == u'3.14 X'
assert dt.format_value(3.14, u'') == u'3.14'
assert dt.format_value(3.14, u'#') == u'3.14 #'
assert dt.format_value(3.14) == '3.14 X'
assert dt.format_value(3.14, '') == '3.14'
assert dt.format_value(3.14, '#') == '3.14 #'
def test_IntRange():
@ -96,20 +95,20 @@ def test_IntRange():
with pytest.raises(ValueError):
dt(-9)
with pytest.raises(ValueError):
dt(u'XX')
dt('XX')
with pytest.raises(ValueError):
dt([19, u'X'])
dt([19, 'X'])
dt(1)
dt(0)
with pytest.raises(ValueError):
IntRange(u'xc', u'Yx')
IntRange('xc', 'Yx')
dt = IntRange()
copytest(dt)
assert dt.export_datatype()['type'] == 'int'
assert dt.export_datatype()['min'] < 0 < dt.export_datatype()['max']
assert dt.export_datatype() == {'type': 'int', 'max': 16777216,u'min': -16777216}
assert dt.format_value(42) == u'42'
assert dt.export_datatype() == {'type': 'int', 'max': 16777216,'min': -16777216}
assert dt.format_value(42) == '42'
def test_ScaledInteger():
dt = ScaledInteger(0.01, -3, 3)
@ -122,36 +121,36 @@ def test_ScaledInteger():
with pytest.raises(ValueError):
dt(-9)
with pytest.raises(ValueError):
dt(u'XX')
dt('XX')
with pytest.raises(ValueError):
dt([19, u'X'])
dt([19, 'X'])
dt(1)
dt(0)
with pytest.raises(ValueError):
ScaledInteger(u'xc', u'Yx')
ScaledInteger('xc', 'Yx')
with pytest.raises(ValueError):
ScaledInteger(scale=0, minval=1, maxval=2)
with pytest.raises(ValueError):
ScaledInteger(scale=-10, minval=1, maxval=2)
# check that unit can be changed
dt.unit = u'A'
dt.unit = 'A'
assert dt.export_datatype() == {'type': 'scaled', 'scale':0.01, 'min':-300, 'max':300, 'unit': 'A'}
assert dt.export_value(0.0001) == int(0)
assert dt.export_value(2.71819) == int(272)
assert dt.import_value(272) == 2.72
dt = ScaledInteger(0.003, 0, 1, unit=u'X', fmtstr=u'%.1f',
dt = ScaledInteger(0.003, 0, 1, unit='X', fmtstr='%.1f',
absolute_resolution=0.001, relative_resolution=1e-5)
copytest(dt)
assert dt.export_datatype() == {'type': 'scaled', 'scale':0.003, 'min':0, 'max':333,
u'unit':u'X', u'fmtstr':u'%.1f',
u'absolute_resolution':0.001,
u'relative_resolution':1e-5}
'unit':'X', 'fmtstr':'%.1f',
'absolute_resolution':0.001,
'relative_resolution':1e-5}
assert dt(0.4) == 0.399
assert dt.format_value(0.4) == u'0.4 X'
assert dt.format_value(0.4, u'') == u'0.4'
assert dt.format_value(0.4, u'Z') == u'0.4 Z'
assert dt.format_value(0.4) == '0.4 X'
assert dt.format_value(0.4, '') == '0.4'
assert dt.format_value(0.4, 'Z') == '0.4 Z'
assert dt(1.0029) == 0.999
with pytest.raises(ValueError):
dt(1.004)
@ -162,9 +161,9 @@ def test_EnumType():
with pytest.raises(TypeError):
EnumType(1)
with pytest.raises(TypeError):
EnumType([u'b', 0])
EnumType(['b', 0])
dt = EnumType(u'dt', a=3, c=7, stuff=1)
dt = EnumType('dt', a=3, c=7, stuff=1)
copytest(dt)
assert dt.export_datatype() == {'type': 'enum', 'members': dict(a=3, c=7, stuff=1)}
@ -173,28 +172,28 @@ def test_EnumType():
with pytest.raises(ValueError):
dt(-9)
with pytest.raises(ValueError):
dt(u'XX')
dt('XX')
with pytest.raises(ValueError):
dt([19, u'X'])
dt([19, 'X'])
assert dt(u'a') == 3
assert dt(u'stuff') == 1
assert dt('a') == 3
assert dt('stuff') == 1
assert dt(1) == 1
with pytest.raises(ValueError):
dt(2)
assert dt.export_value(u'c') == 7
assert dt.export_value(u'stuff') == 1
assert dt.export_value('c') == 7
assert dt.export_value('stuff') == 1
assert dt.export_value(1) == 1
assert dt.import_value(u'c') == 7
assert dt.import_value(u'a') == 3
assert dt.import_value(u'stuff') == 1
assert dt.import_value('c') == 7
assert dt.import_value('a') == 3
assert dt.import_value('stuff') == 1
with pytest.raises(ValueError):
dt.export_value(2)
with pytest.raises(ValueError):
dt.import_value(u'A')
dt.import_value('A')
assert dt.format_value(3) == u'a<3>'
assert dt.format_value(3) == 'a<3>'
def test_BLOBType():
@ -217,13 +216,13 @@ def test_BLOBType():
with pytest.raises(ValueError):
dt(b'abcdefghijklmno')
with pytest.raises(ValueError):
dt(u'abcd')
dt('abcd')
assert dt(b'abcd') == b'abcd'
assert dt.export_value(b'abcd') == u'YWJjZA=='
assert dt.export_value(b'abcd') == u'YWJjZA=='
# assert dt.export_value(u'abcd') == u'YWJjZA=='
assert dt.import_value(u'YWJjZA==') == b'abcd'
assert dt.export_value(b'abcd') == 'YWJjZA=='
assert dt.export_value(b'abcd') == 'YWJjZA=='
# assert dt.export_value('abcd') == 'YWJjZA=='
assert dt.import_value('YWJjZA==') == b'abcd'
# XXX: right? or different format?
# to be added after migration to py3
@ -246,9 +245,9 @@ def test_StringType():
with pytest.raises(ValueError):
dt(9)
with pytest.raises(ValueError):
dt(u'av')
dt('av')
with pytest.raises(ValueError):
dt(u'abcdefghijklmno')
dt('abcdefghijklmno')
with pytest.raises(ValueError):
dt('abcdefg\0')
assert dt('abcd') == 'abcd'
@ -271,7 +270,7 @@ def test_TextType():
with pytest.raises(ValueError):
dt(9)
with pytest.raises(ValueError):
dt(u'abcdefghijklmno')
dt('abcdefghijklmno')
with pytest.raises(ValueError):
dt('abcdefg\0')
assert dt('ab\n\ncd\n') == 'ab\n\ncd\n'
@ -292,20 +291,20 @@ def test_BoolType():
with pytest.raises(ValueError):
dt(9)
with pytest.raises(ValueError):
dt(u'av')
dt('av')
assert dt(u'true') is True
assert dt(u'off') is False
assert dt('true') is True
assert dt('off') is False
assert dt(1) is True
assert dt.export_value(u'false') is False
assert dt.export_value('false') is False
assert dt.export_value(0) is False
assert dt.export_value(u'on') is True
assert dt.export_value('on') is True
assert dt.import_value(False) is False
assert dt.import_value(True) is True
with pytest.raises(ValueError):
dt.import_value(u'av')
dt.import_value('av')
assert dt.format_value(0) == u"False"
assert dt.format_value(True) == u"True"
@ -323,7 +322,7 @@ def test_ArrayOf():
'members': {'type': 'int', 'min':-10,
'max':10}}
dt = ArrayOf(FloatRange(-10, 10, unit=u'Z'), 1, 3)
dt = ArrayOf(FloatRange(-10, 10, unit='Z'), 1, 3)
copytest(dt)
assert dt.export_datatype() == {'type': 'array', 'minlen':1, 'maxlen':3,
'members':{'type': 'double', 'min':-10,
@ -331,16 +330,16 @@ def test_ArrayOf():
with pytest.raises(ValueError):
dt(9)
with pytest.raises(ValueError):
dt(u'av')
dt('av')
assert dt([1, 2, 3]) == [1, 2, 3]
assert dt.export_value([1, 2, 3]) == [1, 2, 3]
assert dt.import_value([1, 2, 3]) == [1, 2, 3]
assert dt.format_value([1,2,3]) == u'[1, 2, 3] Z'
assert dt.format_value([1,2,3], u'') == u'[1, 2, 3]'
assert dt.format_value([1,2,3], u'Q') == u'[1, 2, 3] Q'
assert dt.format_value([1,2,3]) == '[1, 2, 3] Z'
assert dt.format_value([1,2,3], '') == '[1, 2, 3]'
assert dt.format_value([1,2,3], 'Q') == '[1, 2, 3] Q'
def test_TupleOf():
@ -373,7 +372,7 @@ def test_StructOf():
StructOf(IntRange=1)
dt = StructOf(a_string=StringType(0, 55), an_int=IntRange(0, 999),
optional=[u'an_int'])
optional=['an_int'])
copytest(dt)
assert dt.export_datatype() == {'type': 'struct',
'members':{'a_string': {'type': 'string', 'maxchars':55},
@ -383,18 +382,18 @@ def test_StructOf():
with pytest.raises(ValueError):
dt(9)
with pytest.raises(ValueError):
dt([99, u'X'])
dt([99, 'X'])
with pytest.raises(ValueError):
dt(dict(a_string=u'XXX', an_int=1811))
dt(dict(a_string='XXX', an_int=1811))
assert dt(dict(a_string=u'XXX', an_int=8)) == {u'a_string': u'XXX',
u'an_int': 8}
assert dt.export_value({u'an_int': 13, u'a_string': u'WFEC'}) == {
u'a_string': u'WFEC', u'an_int': 13}
assert dt.import_value({u'an_int': 13, u'a_string': u'WFEC'}) == {
u'a_string': u'WFEC', u'an_int': 13}
assert dt(dict(a_string='XXX', an_int=8)) == {'a_string': 'XXX',
'an_int': 8}
assert dt.export_value({'an_int': 13, 'a_string': 'WFEC'}) == {
'a_string': 'WFEC', 'an_int': 13}
assert dt.import_value({'an_int': 13, 'a_string': 'WFEC'}) == {
'a_string': 'WFEC', 'an_int': 13}
assert dt.format_value({'an_int':2, u'a_string':'Z'}) == u"{a_string='Z', an_int=2}"
assert dt.format_value({'an_int':2, 'a_string':'Z'}) == u"{a_string='Z', an_int=2}"
def test_Command():
@ -418,11 +417,11 @@ def test_get_datatype():
with pytest.raises(ValueError):
get_datatype(str)
with pytest.raises(ValueError):
get_datatype({u'undefined': {}})
get_datatype({'undefined': {}})
assert isinstance(get_datatype({'type': 'bool'}), BoolType)
with pytest.raises(ValueError):
get_datatype([u'bool'])
get_datatype(['bool'])
with pytest.raises(ValueError):
get_datatype({'type': 'int', 'min':-10}) # missing max
@ -444,7 +443,7 @@ def test_get_datatype():
FloatRange)
with pytest.raises(ValueError):
get_datatype([u'double'])
get_datatype(['double'])
with pytest.raises(ValueError):
get_datatype({'type': 'double', 'min':10, 'max':-10})
with pytest.raises(ValueError):
@ -462,7 +461,7 @@ def test_get_datatype():
assert get_datatype(dt.export_datatype()).export_datatype() == dt.export_datatype()
with pytest.raises(ValueError):
get_datatype([u'scaled']) # dict missing
get_datatype(['scaled']) # dict missing
with pytest.raises(ValueError):
get_datatype({'type': 'scaled', 'min':-10, 'max':10}) # no scale
with pytest.raises(ValueError):
@ -471,7 +470,7 @@ def test_get_datatype():
get_datatype(['scaled', {'min':10, 'max':-10, 'scale': 1}, 2])
with pytest.raises(ValueError):
get_datatype([u'enum'])
get_datatype(['enum'])
with pytest.raises(ValueError):
get_datatype({'type': 'enum', 'a': -2})
assert isinstance(get_datatype({'type': 'enum', 'members':dict(a=-2)}), EnumType)
@ -498,13 +497,13 @@ def test_get_datatype():
get_datatype(['string', {'maxchars':-0}, 'x'])
with pytest.raises(ValueError):
get_datatype([u'array'])
get_datatype(['array'])
with pytest.raises(ValueError):
get_datatype({'type': 'array', 'members': [1]})
assert isinstance(get_datatype({'type': 'array', 'minlen':1, 'maxlen':1,
'members':{'type': 'blob', 'maxbytes':1}}
), ArrayOf)
assert isinstance(get_datatype({'type': 'array', 'minlen':1, u'maxlen':1,
assert isinstance(get_datatype({'type': 'array', 'minlen':1, 'maxlen':1,
'members':{'type': 'blob', 'maxbytes':1}}
).members, BLOBType)
@ -528,7 +527,7 @@ def test_get_datatype():
with pytest.raises(ValueError):
get_datatype({'type': 'tuple', 'members': {}})
with pytest.raises(ValueError):
get_datatype([u'tuple', 10, -10])
get_datatype(['tuple', 10, -10])
assert isinstance(get_datatype({'type': 'tuple', 'members':[{'type': 'blob', 'maxbytes':1},
{'type': 'bool'}]}), TupleOf)
@ -538,9 +537,9 @@ def test_get_datatype():
with pytest.raises(ValueError):
get_datatype(['struct', [1], 2, 3])
assert isinstance(get_datatype({'type': 'struct', 'members':
{u'name': {'type': 'blob', 'maxbytes':1}}}), StructOf)
{'name': {'type': 'blob', 'maxbytes':1}}}), StructOf)
assert isinstance(get_datatype({'type': 'struct', 'members':
{u'name': {'type': 'blob', 'maxbytes':1}}}).members[u'name'], BLOBType)
{'name': {'type': 'blob', 'maxbytes':1}}}).members['name'], BLOBType)
with pytest.raises(ValueError):
get_datatype({'type': 'struct', 'members': {}})

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""test Enum type."""
from __future__ import division, print_function
# no fixtures needed
import pytest

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
"""test data types."""
from __future__ import division, print_function
# no fixtures needed
#import pytest

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""test data types."""
from __future__ import division, print_function
# no fixtures needed
import pytest
@ -31,24 +30,24 @@ from secop.params import Command, Override, Parameter, Parameters
def test_Command():
cmd = Command(u'do_something')
assert cmd.description == u'do_something'
cmd = Command('do_something')
assert cmd.description == 'do_something'
assert cmd.ctr
assert cmd.argument is None
assert cmd.result is None
assert cmd.for_export() == {u'datainfo': {'type': 'command'},
u'description': u'do_something'}
assert cmd.for_export() == {'datainfo': {'type': 'command'},
'description': 'do_something'}
cmd = Command(u'do_something', argument=IntRange(-9,9), result=IntRange(-1,1))
cmd = Command('do_something', argument=IntRange(-9,9), result=IntRange(-1,1))
assert cmd.description
assert isinstance(cmd.argument, IntRange)
assert isinstance(cmd.result, IntRange)
assert cmd.for_export() == {u'datainfo': {'type': 'command', 'argument': {'type': 'int', 'min':-9, 'max':9},
u'result': {'type': 'int', 'min':-1, 'max':1}},
u'description': u'do_something'}
assert cmd.exportProperties() == {u'datainfo': {'type': 'command', 'argument': {'type': 'int', 'max': 9, 'min': -9},
assert cmd.for_export() == {'datainfo': {'type': 'command', 'argument': {'type': 'int', 'min':-9, 'max':9},
'result': {'type': 'int', 'min':-1, 'max':1}},
'description': 'do_something'}
assert cmd.exportProperties() == {'datainfo': {'type': 'command', 'argument': {'type': 'int', 'max': 9, 'min': -9},
'result': {'type': 'int', 'max': 1, 'min': -1}},
u'description': u'do_something'}
'description': 'do_something'}
def test_Parameter():

View File

@ -21,7 +21,6 @@
# *****************************************************************************
"""test data types."""
from __future__ import division, print_function
from collections import OrderedDict

View File

@ -20,7 +20,6 @@
#
# *****************************************************************************
"""test data types."""
from __future__ import division, print_function
import pytest
@ -31,13 +30,13 @@ from secop.properties import Property, Properties, HasProperties
V_test_Property = [
[(StringType(), 'default', 'extname', False, False),
dict(default=u'default', extname=u'extname', export=True, mandatory=False)],
dict(default='default', extname='extname', export=True, mandatory=False)],
[(IntRange(), '42', '_extname', False, True),
dict(default=42, extname=u'_extname', export=True, mandatory=True)],
dict(default=42, extname='_extname', export=True, mandatory=True)],
[(IntRange(), '42', '_extname', True, False),
dict(default=42, extname=u'_extname', export=True, mandatory=False)],
dict(default=42, extname='_extname', export=True, mandatory=False)],
[(IntRange(), 42, '_extname', True, True),
dict(default=42, extname=u'_extname', export=True, mandatory=True)],
dict(default=42, extname='_extname', export=True, mandatory=True)],
[(IntRange(), 0, '', True, True),
dict(default=0, extname='', export=True, mandatory=True)],
[(IntRange(), 0, '', True, False),
@ -75,7 +74,7 @@ def test_Properties():
p['a'] = Property('', IntRange(), '42', export=True)
assert p['a'].default == 42
assert p['a'].export is True
assert p['a'].extname == u'_a'
assert p['a'].extname == '_a'
with pytest.raises(ProgrammingError):
p['a'] = 137
with pytest.raises(ProgrammingError):

View File

@ -1,4 +1,3 @@
from __future__ import division, print_function
def test_assert():