diff --git a/Makefile b/Makefile index c519c82..15186ce 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/bin/make_doc.py b/bin/make_doc.py index 5630775..a412fb7 100755 --- a/bin/make_doc.py +++ b/bin/make_doc.py @@ -21,7 +21,6 @@ # # ***************************************************************************** -from __future__ import division, print_function import os from os import path diff --git a/bin/secop-console b/bin/secop-console index dc7ec7d..1acf828 100755 --- a/bin/secop-console +++ b/bin/secop-console @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ***************************************************************************** # diff --git a/bin/secop-gui b/bin/secop-gui index 568bfd8..7d76bde 100755 --- a/bin/secop-gui +++ b/bin/secop-gui @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # pylint: disable=invalid-name # -*- coding: utf-8 -*- # ***************************************************************************** diff --git a/bin/secop-server b/bin/secop-server index 0997f92..acbffc4 100755 --- a/bin/secop-server +++ b/bin/secop-server @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # -*- coding: utf-8 -*- # ***************************************************************************** # diff --git a/secop/basic_validators.py b/secop/basic_validators.py index cf471a4..ff055f9 100644 --- a/secop/basic_validators.py +++ b/secop/basic_validators.py @@ -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 diff --git a/secop/client/__init__.py b/secop/client/__init__.py index 9c1e857..69bcd82 100644 --- a/secop/client/__init__.py +++ b/secop/client/__init__.py @@ -23,7 +23,6 @@ # nothing here yet. -from __future__ import print_function import code import socket diff --git a/secop/client/baseclient.py b/secop/client/baseclient.py index f30cc5d..87d4d0d 100644 --- a/secop/client/baseclient.py +++ b/secop/client/baseclient.py @@ -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 diff --git a/secop/datatypes.py b/secop/datatypes.py index fb3afcc..b986132 100644 --- a/secop/datatypes.py +++ b/secop/datatypes.py @@ -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) diff --git a/secop/errors.py b/secop/errors.py index fd30d36..30ad77b 100644 --- a/secop/errors.py +++ b/secop/errors.py @@ -21,7 +21,6 @@ # ***************************************************************************** """Define (internal) SECoP Errors""" -from __future__ import division, print_function class SECoPError(RuntimeError): diff --git a/secop/features.py b/secop/features.py index 8c7fed8..f9b4e51 100644 --- a/secop/features.py +++ b/secop/features.py @@ -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 diff --git a/secop/gui/cfg_editor/utils.py b/secop/gui/cfg_editor/utils.py index 08f7270..1aa4b42 100644 --- a/secop/gui/cfg_editor/utils.py +++ b/secop/gui/cfg_editor/utils.py @@ -20,7 +20,6 @@ # # ***************************************************************************** -from __future__ import print_function from os import path, listdir import sys import inspect diff --git a/secop/gui/cfg_editor/widgets.py b/secop/gui/cfg_editor/widgets.py index d86e47a..ac562f8 100644 --- a/secop/gui/cfg_editor/widgets.py +++ b/secop/gui/cfg_editor/widgets.py @@ -20,7 +20,6 @@ # # ***************************************************************************** -from __future__ import print_function import os diff --git a/secop/gui/mainwindow.py b/secop/gui/mainwindow.py index ee9736f..3b62b5c 100644 --- a/secop/gui/mainwindow.py +++ b/secop/gui/mainwindow.py @@ -21,7 +21,6 @@ # # ***************************************************************************** -from __future__ import division, print_function import sys diff --git a/secop/gui/miniplot.py b/secop/gui/miniplot.py index 8914dfd..998e677 100644 --- a/secop/gui/miniplot.py +++ b/secop/gui/miniplot.py @@ -22,7 +22,6 @@ # ***************************************************************************** -from __future__ import division, print_function from os import path diff --git a/secop/gui/modulectrl.py b/secop/gui/modulectrl.py index ce63001..3e2d9f0 100644 --- a/secop/gui/modulectrl.py +++ b/secop/gui/modulectrl.py @@ -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: diff --git a/secop/gui/nodectrl.py b/secop/gui/nodectrl.py index 92c6095..fa847d6 100644 --- a/secop/gui/nodectrl.py +++ b/secop/gui/nodectrl.py @@ -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) diff --git a/secop/gui/params/__init__.py b/secop/gui/params/__init__.py index b087e7d..a461dff 100644 --- a/secop/gui/params/__init__.py +++ b/secop/gui/params/__init__.py @@ -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 diff --git a/secop/gui/paramview.py b/secop/gui/paramview.py index 7a6aa87..afa3356 100644 --- a/secop/gui/paramview.py +++ b/secop/gui/paramview.py @@ -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): diff --git a/secop/gui/qt.py b/secop/gui/qt.py index 1f1cb2a..2f743bd 100644 --- a/secop/gui/qt.py +++ b/secop/gui/qt.py @@ -22,7 +22,6 @@ """Import needed stuff from PyQt4/PyQt5""" # pylint: disable=unused-import -from __future__ import division, print_function import sys diff --git a/secop/gui/util.py b/secop/gui/util.py index 97fb9eb..377bf41 100644 --- a/secop/gui/util.py +++ b/secop/gui/util.py @@ -21,7 +21,6 @@ # # ***************************************************************************** -from __future__ import division, print_function from os import path diff --git a/secop/gui/valuewidgets.py b/secop/gui/valuewidgets.py index 88636d7..59a5fbd 100644 --- a/secop/gui/valuewidgets.py +++ b/secop/gui/valuewidgets.py @@ -21,7 +21,6 @@ # # ***************************************************************************** -from __future__ import division, print_function from secop.datatypes import ArrayOf, BLOBType, BoolType, EnumType, \ FloatRange, IntRange, StringType, StructOf, TupleOf, TextType diff --git a/secop/lib/__init__.py b/secop/lib/__init__.py index 9969723..f424756 100644 --- a/secop/lib/__init__.py +++ b/secop/lib/__init__.py @@ -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, } diff --git a/secop/lib/enum.py b/secop/lib/enum.py index ffc011e..f459584 100755 --- a/secop/lib/enum.py +++ b/secop/lib/enum.py @@ -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() diff --git a/secop/lib/metaclass.py b/secop/lib/metaclass.py deleted file mode 100644 index 3fccd05..0000000 --- a/secop/lib/metaclass.py +++ /dev/null @@ -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 -# -# ***************************************************************************** -"""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 diff --git a/secop/lib/parsing.py b/secop/lib/parsing.py index 78ee6c4..c085f06 100644 --- a/secop/lib/parsing.py +++ b/secop/lib/parsing.py @@ -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/... diff --git a/secop/lib/pidfile.py b/secop/lib/pidfile.py index 532ba38..76382d1 100644 --- a/secop/lib/pidfile.py +++ b/secop/lib/pidfile.py @@ -20,7 +20,6 @@ # # ***************************************************************************** """Define pidfile helpers""" -from __future__ import division, print_function import atexit import os diff --git a/secop/lib/sequence.py b/secop/lib/sequence.py index b126f7c..b17a58e 100644 --- a/secop/lib/sequence.py +++ b/secop/lib/sequence.py @@ -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 diff --git a/secop/metaclass.py b/secop/metaclass.py index e0f7456..dee49c8 100644 --- a/secop/metaclass.py +++ b/secop/metaclass.py @@ -21,7 +21,6 @@ # ***************************************************************************** """Define Metaclass for Modules/Features""" -from __future__ import division, print_function import time from collections import OrderedDict diff --git a/secop/modules.py b/secop/modules.py index 821bada..265631e 100644 --- a/secop/modules.py +++ b/secop/modules.py @@ -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) diff --git a/secop/params.py b/secop/params.py index 59424b7..d0d3ae1 100644 --- a/secop/params.py +++ b/secop/params.py @@ -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 diff --git a/secop/parse.py b/secop/parse.py index 3e2921c..374a483 100644 --- a/secop/parse.py +++ b/secop/parse.py @@ -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 diff --git a/secop/paths.py b/secop/paths.py index 3460d2b..d43cd69 100644 --- a/secop/paths.py +++ b/secop/paths.py @@ -21,7 +21,6 @@ # ***************************************************************************** """Pathes. how to find what and where...""" -from __future__ import division, print_function import sys from os import path diff --git a/secop/properties.py b/secop/properties.py index 101476f..0ad8bd2 100644 --- a/secop/properties.py +++ b/secop/properties.py @@ -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): diff --git a/secop/protocol/dispatcher.py b/secop/protocol/dispatcher.py index e1638cf..9654e64 100644 --- a/secop/protocol/dispatcher.py +++ b/secop/protocol/dispatcher.py @@ -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) diff --git a/secop/protocol/interface/__init__.py b/secop/protocol/interface/__init__.py index 067ef46..8e4d6e6 100644 --- a/secop/protocol/interface/__init__.py +++ b/secop/protocol/interface/__init__.py @@ -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') diff --git a/secop/protocol/interface/tcp.py b/secop/protocol/interface/tcp.py index 8857a9d..3f2343c 100644 --- a/secop/protocol/interface/tcp.py +++ b/secop/protocol/interface/tcp.py @@ -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' ' diff --git a/secop/protocol/interface/zmq.py b/secop/protocol/interface/zmq.py index 8623819..8bff683 100644 --- a/secop/protocol/interface/zmq.py +++ b/secop/protocol/interface/zmq.py @@ -21,7 +21,6 @@ # ***************************************************************************** """provide a zmq server""" -from __future__ import division, print_function # tbd. diff --git a/secop/protocol/messages.py b/secop/protocol/messages.py index a9d41fe..ed42a06 100644 --- a/secop/protocol/messages.py +++ b/secop/protocol/messages.py @@ -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' # + +json +DESCRIPTIONREQUEST = 'describe' # literal +DESCRIPTIONREPLY = 'describing' # + +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 = { diff --git a/secop/server.py b/secop/server.py index fef3292..7c5c3f4 100644 --- a/secop/server.py +++ b/secop/server.py @@ -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') diff --git a/secop/simulation.py b/secop/simulation.py index da9df5d..8e4653a 100644 --- a/secop/simulation.py +++ b/secop/simulation.py @@ -21,7 +21,6 @@ # ***************************************************************************** """Define Simulation classes""" -from __future__ import division, print_function import random from time import sleep diff --git a/secop/version.py b/secop/version.py index 19991d7..670337c 100644 --- a/secop/version.py +++ b/secop/version.py @@ -23,7 +23,6 @@ # # ***************************************************************************** -from __future__ import division, print_function import os.path from subprocess import PIPE, Popen diff --git a/secop_demo/cryo.py b/secop_demo/cryo.py index 83be2f8..3ba74c2 100644 --- a/secop_demo/cryo.py +++ b/secop_demo/cryo.py @@ -20,7 +20,6 @@ # ***************************************************************************** """playing implementation of a (simple) simulated cryostat""" -from __future__ import division, print_function import random import time diff --git a/secop_demo/modules.py b/secop_demo/modules.py index d3a0056..f16a854 100644 --- a/secop_demo/modules.py +++ b/secop_demo/modules.py @@ -20,7 +20,6 @@ # ***************************************************************************** """testing devices""" -from __future__ import division, print_function import random import threading diff --git a/secop_demo/test.py b/secop_demo/test.py index fcc73ef..31686a5 100644 --- a/secop_demo/test.py +++ b/secop_demo/test.py @@ -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() diff --git a/secop_ess/epics.py b/secop_ess/epics.py index 3bd115f..4d762f5 100644 --- a/secop_ess/epics.py +++ b/secop_ess/epics.py @@ -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 diff --git a/secop_mlz/amagnet.py b/secop_mlz/amagnet.py index e8ae64b..5ebfc7e 100644 --- a/secop_mlz/amagnet.py +++ b/secop_mlz/amagnet.py @@ -25,7 +25,6 @@ # partially borrowed from nicos -from __future__ import division, print_function import math diff --git a/secop_mlz/entangle.py b/secop_mlz/entangle.py index a9cc4b3..983186b 100644 --- a/secop_mlz/entangle.py +++ b/secop_mlz/entangle.py @@ -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 diff --git a/setup.py b/setup.py index 19fe831..0bf3530 100644 --- a/setup.py +++ b/setup.py @@ -22,7 +22,6 @@ # # ***************************************************************************** -from __future__ import division, print_function from glob import glob from os import listdir, path diff --git a/test/conftest.py b/test/conftest.py index 7119cb5..244a171 100644 --- a/test/conftest.py +++ b/test/conftest.py @@ -1,5 +1,4 @@ # content of conftest.py -from __future__ import division, print_function import pytest diff --git a/test/test_basic_validators.py b/test/test_basic_validators.py index 2caaa0b..dfdfaba 100644 --- a/test/test_basic_validators.py +++ b/test/test_basic_validators.py @@ -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): diff --git a/test/test_client_baseclient.py b/test/test_client_baseclient.py index 95872a2..fe0fa0b 100644 --- a/test/test_client_baseclient.py +++ b/test/test_client_baseclient.py @@ -20,7 +20,6 @@ # # ***************************************************************************** """test base client.""" -from __future__ import division, print_function from collections import OrderedDict diff --git a/test/test_datatypes.py b/test/test_datatypes.py index 2c111bf..0fd9c2a 100644 --- a/test/test_datatypes.py +++ b/test/test_datatypes.py @@ -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': {}}) diff --git a/test/test_lib_enum.py b/test/test_lib_enum.py index 78ab40a..78016fa 100644 --- a/test/test_lib_enum.py +++ b/test/test_lib_enum.py @@ -21,7 +21,6 @@ # ***************************************************************************** """test Enum type.""" -from __future__ import division, print_function # no fixtures needed import pytest diff --git a/test/test_modules.py b/test/test_modules.py index a6d0eaf..ef1e9d0 100644 --- a/test/test_modules.py +++ b/test/test_modules.py @@ -20,7 +20,6 @@ # # ***************************************************************************** """test data types.""" -from __future__ import division, print_function # no fixtures needed #import pytest diff --git a/test/test_params.py b/test/test_params.py index 93a8347..555a2c8 100644 --- a/test/test_params.py +++ b/test/test_params.py @@ -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(): diff --git a/test/test_parse.py b/test/test_parse.py index 273c0f0..ebe9544 100644 --- a/test/test_parse.py +++ b/test/test_parse.py @@ -21,7 +21,6 @@ # ***************************************************************************** """test data types.""" -from __future__ import division, print_function from collections import OrderedDict diff --git a/test/test_properties.py b/test/test_properties.py index 6ef0d9c..7012c9b 100644 --- a/test/test_properties.py +++ b/test/test_properties.py @@ -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): diff --git a/test/test_test.py b/test/test_test.py index 972a6a1..3df69fb 100644 --- a/test/test_test.py +++ b/test/test_test.py @@ -1,4 +1,3 @@ -from __future__ import division, print_function def test_assert():