summaryrefslogtreecommitdiff
path: root/lib/taurus/core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/taurus/core')
-rw-r--r--lib/taurus/core/epics/__init__.py4
-rw-r--r--lib/taurus/core/epics/epicsattribute.py8
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/epics/test/test_epicsattribute.py0
-rw-r--r--lib/taurus/core/evaluation/evalattribute.py6
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/evaluation/evalfactory.py0
-rw-r--r--lib/taurus/core/evaluation/test/res/dev_example.py2
-rw-r--r--lib/taurus/core/evaluation/test/res/ipap_example.py2
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/evaluation/test/test_evalattribute.py0
-rw-r--r--lib/taurus/core/init_bkcomp.py1
-rw-r--r--lib/taurus/core/release.py2
-rw-r--r--lib/taurus/core/resource/resvalidator.py4
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/resource/test/res/__init__.py0
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/resource/test/res/attr_resources_file.py0
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/resource/test/test_resfactory.py0
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/resource/test/test_resvalidator.py0
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/tango/tangoattribute.py17
-rw-r--r--lib/taurus/core/tango/tangodatabase.py31
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/tango/tangodevice.py2
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/tango/test/test_tangofactory.py0
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/tango/util/formatter.py0
-rw-r--r--lib/taurus/core/taurusattribute.py14
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/taurusdevice.py0
-rw-r--r--lib/taurus/core/taurusfactory.py11
-rw-r--r--lib/taurus/core/taurushelper.py20
-rw-r--r--[-rwxr-xr-x]lib/taurus/core/taurusmanager.py0
-rw-r--r--lib/taurus/core/test/test_taurushelper.py14
-rw-r--r--lib/taurus/core/units.py1
-rw-r--r--lib/taurus/core/util/argparse/taurusargparse.py6
-rw-r--r--lib/taurus/core/util/codecs.py90
-rw-r--r--lib/taurus/core/util/console.py3
-rw-r--r--lib/taurus/core/util/constant.py6
-rw-r--r--lib/taurus/core/util/containers.py2
-rw-r--r--lib/taurus/core/util/decorator/__init__.py28
-rw-r--r--lib/taurus/core/util/decorator/decorator.py38
-rw-r--r--lib/taurus/core/util/decorator/typecheck.py35
-rw-r--r--lib/taurus/core/util/event.py3
-rw-r--r--lib/taurus/core/util/parse_args.py6
-rw-r--r--lib/taurus/core/util/property_parser.py2
-rw-r--r--lib/taurus/core/util/propertyfile.py3
-rw-r--r--lib/taurus/core/util/remotelogmonitor.py58
-rw-r--r--lib/taurus/core/util/tablepprint.py35
-rw-r--r--lib/taurus/core/util/test/test_codecs.py2
-rw-r--r--lib/taurus/core/util/whichexecutable.py2
43 files changed, 267 insertions, 191 deletions
diff --git a/lib/taurus/core/epics/__init__.py b/lib/taurus/core/epics/__init__.py
index b39cf4a2..1f8123a8 100644
--- a/lib/taurus/core/epics/__init__.py
+++ b/lib/taurus/core/epics/__init__.py
@@ -54,11 +54,11 @@ Epics attributes (should) work just as other Taurus attributes and can be
referred by their model name wherever a Taurus Attribute model is expected. For
example, you can launch a `TaurusForm` with an epics attribute::
- $> taurusform ca:my:example
+ $> taurus form ca:my:example
Similarly, you can combine epics attributes with attributes from other schemes::
- $> taurusform 'ca:my:example' 'tango:sys/tg_test/1/float_scalar'\
+ $> taurus form 'ca:my:example' 'tango:sys/tg_test/1/float_scalar'\
'eval:{ca:my:example}*{tango:sys/tg_test/1/float_scalar}'
Currently, the taurus epics scheme just supports epics PVs, implementing them as
diff --git a/lib/taurus/core/epics/epicsattribute.py b/lib/taurus/core/epics/epicsattribute.py
index bba58f84..11680af2 100644
--- a/lib/taurus/core/epics/epicsattribute.py
+++ b/lib/taurus/core/epics/epicsattribute.py
@@ -226,14 +226,6 @@ class EpicsAttribute(TaurusAttribute):
def isUsingEvents(self):
return True # TODO: implement this
-
- def _subscribeEvents(self):
- raise NotImplementedError("Not allowed to call AbstractClass" +
- " TaurusAttribute._subscribeEvents")
-
- def _unsubscribeEvents(self):
- raise NotImplementedError("Not allowed to call AbstractClass" +
- " TaurusAttribute._unsubscribeEvents")
# ------------------------------------------------------------------------------
def factory(self):
diff --git a/lib/taurus/core/epics/test/test_epicsattribute.py b/lib/taurus/core/epics/test/test_epicsattribute.py
index 3a32c91f..3a32c91f 100755..100644
--- a/lib/taurus/core/epics/test/test_epicsattribute.py
+++ b/lib/taurus/core/epics/test/test_epicsattribute.py
diff --git a/lib/taurus/core/evaluation/evalattribute.py b/lib/taurus/core/evaluation/evalattribute.py
index f7277f2e..1e414519 100644
--- a/lib/taurus/core/evaluation/evalattribute.py
+++ b/lib/taurus/core/evaluation/evalattribute.py
@@ -445,12 +445,6 @@ class EvaluationAttribute(TaurusAttribute):
v = self.read(cache=False)
self.fireEvent(TaurusEventType.Periodic, v)
- def _subscribeEvents(self):
- pass
-
- def _unsubscribeEvents(self):
- pass
-
def isUsingEvents(self):
# if this attributes depends from others, then we consider it uses
# events
diff --git a/lib/taurus/core/evaluation/evalfactory.py b/lib/taurus/core/evaluation/evalfactory.py
index f7bd6c5c..f7bd6c5c 100755..100644
--- a/lib/taurus/core/evaluation/evalfactory.py
+++ b/lib/taurus/core/evaluation/evalfactory.py
diff --git a/lib/taurus/core/evaluation/test/res/dev_example.py b/lib/taurus/core/evaluation/test/res/dev_example.py
index cc093eb5..21ef55c7 100644
--- a/lib/taurus/core/evaluation/test/res/dev_example.py
+++ b/lib/taurus/core/evaluation/test/res/dev_example.py
@@ -81,7 +81,7 @@ def test2():
import sys
from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.panel import TaurusForm
- app = TaurusApplication()
+ app = TaurusApplication(cmd_line_parser=None)
w = TaurusForm()
attrname = 'eval:@taurus.core.evaluation.test.res.dev_example.FreeSpaceDevice/getFreeSpace("/")'
diff --git a/lib/taurus/core/evaluation/test/res/ipap_example.py b/lib/taurus/core/evaluation/test/res/ipap_example.py
index de47bbad..2e391459 100644
--- a/lib/taurus/core/evaluation/test/res/ipap_example.py
+++ b/lib/taurus/core/evaluation/test/res/ipap_example.py
@@ -44,7 +44,7 @@ def _test2():
import sys
from taurus.qt.qtgui.application import TaurusApplication
from taurus.qt.qtgui.display import TaurusLabel
- app = TaurusApplication()
+ app = TaurusApplication(cmd_line_parser=None)
tl = TaurusLabel()
tl.setModel(ATTR_IPAP_POS)
diff --git a/lib/taurus/core/evaluation/test/test_evalattribute.py b/lib/taurus/core/evaluation/test/test_evalattribute.py
index 6e9a7388..6e9a7388 100755..100644
--- a/lib/taurus/core/evaluation/test/test_evalattribute.py
+++ b/lib/taurus/core/evaluation/test/test_evalattribute.py
diff --git a/lib/taurus/core/init_bkcomp.py b/lib/taurus/core/init_bkcomp.py
index 26f64052..3a480733 100644
--- a/lib/taurus/core/init_bkcomp.py
+++ b/lib/taurus/core/init_bkcomp.py
@@ -42,6 +42,7 @@ from .taurusmanager import *
from .taurusoperation import *
from .tauruspollingtimer import *
from .taurusvalidator import *
+from .units import *
# enable compatibility code with tau V1 if tauv1 package is present
try:
diff --git a/lib/taurus/core/release.py b/lib/taurus/core/release.py
index 00dda8f6..820800f5 100644
--- a/lib/taurus/core/release.py
+++ b/lib/taurus/core/release.py
@@ -47,7 +47,7 @@ name = 'taurus'
# we use semantic versioning (http://semver.org/) and we update it using the
# bumpversion script (https://github.com/peritus/bumpversion)
-version = '4.5.0'
+version = '4.6.1'
# generate version_info and revision (**deprecated** since version 4.0.2-dev).
if '-' in version:
diff --git a/lib/taurus/core/resource/resvalidator.py b/lib/taurus/core/resource/resvalidator.py
index 6e3e99a6..581ededd 100644
--- a/lib/taurus/core/resource/resvalidator.py
+++ b/lib/taurus/core/resource/resvalidator.py
@@ -29,8 +29,8 @@ from taurus.core.taurusvalidator import (TaurusAttributeNameValidator,
TaurusAuthorityNameValidator)
from taurus.core.taurushelper import getSchemeFromName, Factory
-__all__ = ['ResDeviceNameValidator',
- 'ResAttributeNameValidator']
+__all__ = ['ResourceAuthorityNameValidator', 'ResourceDeviceNameValidator',
+ 'ResourceAttributeNameValidator']
# Pattern for python variables
PY_VAR = r'(?<![\.a-zA-Z0-9_])[a-zA-Z_][a-zA-Z0-9_]*'
diff --git a/lib/taurus/core/resource/test/res/__init__.py b/lib/taurus/core/resource/test/res/__init__.py
index e69de29b..e69de29b 100755..100644
--- a/lib/taurus/core/resource/test/res/__init__.py
+++ b/lib/taurus/core/resource/test/res/__init__.py
diff --git a/lib/taurus/core/resource/test/res/attr_resources_file.py b/lib/taurus/core/resource/test/res/attr_resources_file.py
index 0db7a6e0..0db7a6e0 100755..100644
--- a/lib/taurus/core/resource/test/res/attr_resources_file.py
+++ b/lib/taurus/core/resource/test/res/attr_resources_file.py
diff --git a/lib/taurus/core/resource/test/test_resfactory.py b/lib/taurus/core/resource/test/test_resfactory.py
index e80714a4..e80714a4 100755..100644
--- a/lib/taurus/core/resource/test/test_resfactory.py
+++ b/lib/taurus/core/resource/test/test_resfactory.py
diff --git a/lib/taurus/core/resource/test/test_resvalidator.py b/lib/taurus/core/resource/test/test_resvalidator.py
index 4384e97b..4384e97b 100755..100644
--- a/lib/taurus/core/resource/test/test_resvalidator.py
+++ b/lib/taurus/core/resource/test/test_resvalidator.py
diff --git a/lib/taurus/core/tango/tangoattribute.py b/lib/taurus/core/tango/tangoattribute.py
index 9bd9af00..b0620881 100755..100644
--- a/lib/taurus/core/tango/tangoattribute.py
+++ b/lib/taurus/core/tango/tangoattribute.py
@@ -119,8 +119,10 @@ class TangoAttrValue(TaurusAttrValue):
for _ in range(len(shape) - 1):
p.value = [p.value]
- rvalue = p.value
- wvalue = p.w_value
+ # Protect against DeviceAttribute not providing .value in some cases,
+ # seen e.g. in PyTango 9.3.0
+ rvalue = getattr(p, 'value', None)
+ wvalue = getattr(p, 'w_value', None)
if numerical:
units = self._attrRef._units
if rvalue is not None:
@@ -324,6 +326,7 @@ class TangoAttribute(TaurusAttribute):
def cleanUp(self):
self.trace("[TangoAttribute] cleanUp")
self._unsubscribeConfEvents()
+ self._unsubscribeChangeEvents()
TaurusAttribute.cleanUp(self)
self.__dev_hw_obj = None
self._pytango_attrinfoex = None
@@ -417,7 +420,7 @@ class TangoAttribute(TaurusAttribute):
elif fmt in (DataFormat._1D, DataFormat._2D):
if PyTango.is_int_type(tgtype):
# cast to integer because the magnitude conversion gives floats
- attrvalue = magnitude.astype('int64')
+ attrvalue = numpy.array(magnitude, copy=False, dtype='int64')
elif tgtype == PyTango.CmdArgType.DevUChar:
attrvalue = magnitude.view('uint8')
else:
@@ -600,7 +603,7 @@ class TangoAttribute(TaurusAttribute):
assert len(listeners) >= 1
if self.__subscription_state == SubscriptionState.Unsubscribed and len(listeners) == 1:
- self._subscribeEvents()
+ self._subscribeChangeEvents()
# if initial_subscription_state == SubscriptionState.Subscribed:
if (len(listeners) > 1
@@ -630,7 +633,7 @@ class TangoAttribute(TaurusAttribute):
return ret
if self.__subscription_state != SubscriptionState.Unsubscribed:
- self._unsubscribeEvents()
+ self._unsubscribeChangeEvents()
return ret
@@ -654,7 +657,7 @@ class TangoAttribute(TaurusAttribute):
def _process_event_exception(self, ex):
pass
- def _subscribeEvents(self):
+ def _subscribeChangeEvents(self):
""" Enable subscription to the attribute events. If change events are
not supported polling is activated """
@@ -705,7 +708,7 @@ class TangoAttribute(TaurusAttribute):
return self.__chg_evt_id
- def _unsubscribeEvents(self):
+ def _unsubscribeChangeEvents(self):
# Careful in this method: This is intended to be executed in the cleanUp
# so we should not access external objects from the factory, like the
# parent object
diff --git a/lib/taurus/core/tango/tangodatabase.py b/lib/taurus/core/tango/tangodatabase.py
index 0d29365b..cb138566 100644
--- a/lib/taurus/core/tango/tangodatabase.py
+++ b/lib/taurus/core/tango/tangodatabase.py
@@ -643,21 +643,22 @@ def get_env_var(env_var_name):
if not os.path.exists(fname):
return None
- for line in file(fname):
- strippedline = line.split('#', 1)[0].strip()
-
- if not strippedline:
- # empty line
- continue
-
- tup = strippedline.split('=', 1)
- if len(tup) != 2:
- # illegal line!
- continue
-
- key, val = list(map(str.strip, tup))
- if key == env_var_name:
- return val
+ with open(fname) as f:
+ for line in f:
+ strippedline = line.split('#', 1)[0].strip()
+
+ if not strippedline:
+ # empty line
+ continue
+
+ tup = strippedline.split('=', 1)
+ if len(tup) != 2:
+ # illegal line!
+ continue
+
+ key, val = list(map(str.strip, tup))
+ if key == env_var_name:
+ return val
class TangoAuthority(TaurusAuthority):
diff --git a/lib/taurus/core/tango/tangodevice.py b/lib/taurus/core/tango/tangodevice.py
index 562faa66..60e979c8 100755..100644
--- a/lib/taurus/core/tango/tangodevice.py
+++ b/lib/taurus/core/tango/tangodevice.py
@@ -75,7 +75,7 @@ class TangoDevice(TaurusDevice):
# This way we can call for example read_attribute on an object of this
# class
def __getattr__(self, name):
- if self._deviceObj is not None:
+ if name != "_deviceObj" and self._deviceObj is not None:
return getattr(self._deviceObj, name)
cls_name = self.__class__.__name__
raise AttributeError("'%s' has no attribute '%s'" % (cls_name, name))
diff --git a/lib/taurus/core/tango/test/test_tangofactory.py b/lib/taurus/core/tango/test/test_tangofactory.py
index 7c7c3a8a..7c7c3a8a 100755..100644
--- a/lib/taurus/core/tango/test/test_tangofactory.py
+++ b/lib/taurus/core/tango/test/test_tangofactory.py
diff --git a/lib/taurus/core/tango/util/formatter.py b/lib/taurus/core/tango/util/formatter.py
index ce5ebd0d..ce5ebd0d 100755..100644
--- a/lib/taurus/core/tango/util/formatter.py
+++ b/lib/taurus/core/tango/util/formatter.py
diff --git a/lib/taurus/core/taurusattribute.py b/lib/taurus/core/taurusattribute.py
index 9f61d5e1..eba0365a 100644
--- a/lib/taurus/core/taurusattribute.py
+++ b/lib/taurus/core/taurusattribute.py
@@ -79,7 +79,11 @@ class TaurusAttribute(TaurusModel):
def cleanUp(self):
self.trace("[TaurusAttribute] cleanUp")
- self._unsubscribeEvents()
+ if hasattr(self, '_unsuscribeEvents'):
+ self.deprecated(
+ dep='TaurusAttribute._unsuscribeEvents API',
+ alt='If you need it called in cleanUp, re-implement cleanUp')
+ self._unsuscribeEvents()
TaurusModel.cleanUp(self)
#-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-
@@ -146,14 +150,6 @@ class TaurusAttribute(TaurusModel):
raise NotImplementedError("Not allowed to call AbstractClass" +
" TaurusAttribute.poll")
- def _subscribeEvents(self):
- raise NotImplementedError("Not allowed to call AbstractClass" +
- " TaurusAttribute._subscribeEvents")
-
- def _unsubscribeEvents(self):
- raise NotImplementedError("Not allowed to call AbstractClass" +
- " TaurusAttribute._unsubscribeEvents")
-
def isUsingEvents(self):
raise NotImplementedError("Not allowed to call AbstractClass" +
" TaurusAttribute.isUsingEvents")
diff --git a/lib/taurus/core/taurusdevice.py b/lib/taurus/core/taurusdevice.py
index ae605e1f..ae605e1f 100755..100644
--- a/lib/taurus/core/taurusdevice.py
+++ b/lib/taurus/core/taurusdevice.py
diff --git a/lib/taurus/core/taurusfactory.py b/lib/taurus/core/taurusfactory.py
index 01a48148..230c2151 100644
--- a/lib/taurus/core/taurusfactory.py
+++ b/lib/taurus/core/taurusfactory.py
@@ -396,6 +396,17 @@ class TaurusFactory(object):
ret.append(TaurusElementType.Authority)
return ret
+ def getValidatorFromName(self, name):
+ """
+ Obtain the validator object corresponding to the given model
+ name. If the model name is not valid for any TaurusModel class,
+ it returns None
+ """
+ modeltypes = self.getValidTypesForName(name)
+ if not modeltypes:
+ return None
+ return self.elementTypesMap[modeltypes[0]].getNameValidator()
+
def findObjectClass(self, absolute_name):
"""
Obtain the class object corresponding to the given name.
diff --git a/lib/taurus/core/taurushelper.py b/lib/taurus/core/taurushelper.py
index a6de167b..07fb7d32 100644
--- a/lib/taurus/core/taurushelper.py
+++ b/lib/taurus/core/taurushelper.py
@@ -42,7 +42,8 @@ __all__ = ['check_dependencies', 'log_dependencies', 'getSchemeFromName',
'resetLogLevel', 'resetLogFormat',
'enableLogOutput', 'disableLogOutput',
'log', 'trace', 'debug', 'info', 'warning', 'error', 'fatal',
- 'critical', 'deprecated', 'changeDefaultPollingPeriod']
+ 'critical', 'deprecated', 'changeDefaultPollingPeriod',
+ 'getValidatorFromName']
__docformat__ = "restructuredtext"
@@ -134,6 +135,21 @@ def getSchemeFromName(name, implicit=True):
return None
+def getValidatorFromName(name):
+ """Helper for obtaining the validator object corresponding to the
+ given name.
+
+ :return: model name validator or None if name is not a supported model name
+ """
+
+ try:
+ factory = Factory(scheme=getSchemeFromName(name))
+ except:
+ return None
+ return factory.getValidatorFromName(name)
+
+
+
def makeSchemeExplicit(name, default=None):
"""return the name guaranteeing that the scheme is present. If name already
contains the scheme, it is returned unchanged.
@@ -200,7 +216,7 @@ def isValidName(name, etypes=None, strict=None):
for e in etypes:
if e in validtypes:
return True
- return False
+ return False
def Manager():
diff --git a/lib/taurus/core/taurusmanager.py b/lib/taurus/core/taurusmanager.py
index 5ef57107..5ef57107 100755..100644
--- a/lib/taurus/core/taurusmanager.py
+++ b/lib/taurus/core/taurusmanager.py
diff --git a/lib/taurus/core/test/test_taurushelper.py b/lib/taurus/core/test/test_taurushelper.py
index 252471ba..5febe0a7 100644
--- a/lib/taurus/core/test/test_taurushelper.py
+++ b/lib/taurus/core/test/test_taurushelper.py
@@ -466,5 +466,19 @@ class AttributeTestCase(unittest.TestCase):
self.assertTrue(chk, msg)
+class ValidatorFromName(unittest.TestCase):
+ """TestCase for the taurus.getValidatorFromName helper"""
+
+ def test_getValidatorFromName(self):
+ """check that getValidatorFromName returns the expected values"""
+
+ self.assertIsInstance(
+ taurus.getValidatorFromName('eval:@foo'),
+ taurus.core.evaluation.evalvalidator.EvaluationDeviceNameValidator
+ )
+ self.assertIsNone(taurus.getValidatorFromName('eval:@/'))
+ self.assertIsNone(taurus.getValidatorFromName('unsupported:scheme'))
+
+
if __name__ == '__main__':
pass
diff --git a/lib/taurus/core/units.py b/lib/taurus/core/units.py
index 0d6ad349..64a1250e 100644
--- a/lib/taurus/core/units.py
+++ b/lib/taurus/core/units.py
@@ -27,6 +27,7 @@ This module provides a pint unit registry instance (`UR`) to be used by all
taurus objects. It also provides the `Quantity` factory from that registry
(also aliased as `Q_`).
"""
+__all__ = ['UR', 'Quantity', 'Q_']
from pint import UnitRegistry
diff --git a/lib/taurus/core/util/argparse/taurusargparse.py b/lib/taurus/core/util/argparse/taurusargparse.py
index b21e717a..4555f019 100644
--- a/lib/taurus/core/util/argparse/taurusargparse.py
+++ b/lib/taurus/core/util/argparse/taurusargparse.py
@@ -84,6 +84,12 @@ __all__ = ["get_taurus_parser", "init_taurus_args", "parse_taurus_args",
__docformat__ = "restructuredtext"
+from taurus.core.util import log as __log
+
+__log.deprecated(dep='taurus.core.util.argparse', rel='4.5.4',
+ alt='argparse or (better) click')
+
+
def get_taurus_parser(parser=None):
""" Returns a :class:`optparse.OptionParser` initialized with a
:class:`optparse.OptionGroup` containning some taurus options.
diff --git a/lib/taurus/core/util/codecs.py b/lib/taurus/core/util/codecs.py
index 0b91df54..15cdd0ee 100644
--- a/lib/taurus/core/util/codecs.py
+++ b/lib/taurus/core/util/codecs.py
@@ -63,7 +63,7 @@ A Taurus related example::
>>> f, d = codec.decode((v.format, v.value))
"""
from __future__ import absolute_import
-from builtins import str
+from builtins import str, bytes
import copy
@@ -79,7 +79,8 @@ from .log import Logger
from .containers import CaselessDict
__all__ = ["Codec", "NullCodec", "ZIPCodec", "BZ2Codec", "JSONCodec",
- "FunctionCodec", "PlotCodec", "CodecPipeline", "CodecFactory"]
+ "Utf8Codec", "FunctionCodec", "PlotCodec", "CodecPipeline",
+ "CodecFactory"]
__docformat__ = "restructuredtext"
@@ -171,7 +172,7 @@ class ZIPCodec(Codec):
'Hello world\\nHello wo'"""
def encode(self, data, *args, **kwargs):
- """encodes the given data to a gzip string. The given data **must** be a string
+ """encodes the given data to gzip bytes. The given data **must** be bytes
:param data: (sequence[str, obj]) a sequence of two elements where the first item is the encoding format of the second item object
@@ -183,7 +184,7 @@ class ZIPCodec(Codec):
return format, zlib.compress(data[1])
def decode(self, data, *args, **kwargs):
- """decodes the given data from a gzip string.
+ """decodes the given data from a gzip bytes.
:param data: (sequence[str, obj]) a sequence of two elements where the first item is the encoding format of the second item object
@@ -214,7 +215,7 @@ class BZ2Codec(Codec):
'Hello world\\nHello wo'"""
def encode(self, data, *args, **kwargs):
- """encodes the given data to a bz2 string. The given data **must** be a string
+ """encodes the given data to bz2 bytes. The given data **must** be bytes
:param data: (sequence[str, obj]) a sequence of two elements where the first item is the encoding format of the second item object
@@ -226,7 +227,7 @@ class BZ2Codec(Codec):
return format, bz2.compress(data[1])
def decode(self, data, *args, **kwargs):
- """decodes the given data from a bz2 string.
+ """decodes the given data from bz2 bytes.
:param data: (sequence[str, obj]) a sequence of two elements where the first item is the encoding format of the second item object
@@ -259,7 +260,7 @@ class PickleCodec(Codec):
{'hello': 'world', 'goodbye': 1000}"""
def encode(self, data, *args, **kwargs):
- """encodes the given data to a pickle string. The given data **must** be
+ """encodes the given data to pickle bytes. The given data **must** be
a python object that :mod:`pickle` is able to convert.
:param data: (sequence[str, obj]) a sequence of two elements where the
@@ -331,7 +332,7 @@ class JSONCodec(Codec):
format += '_%s' % data[0]
# make it compact by default
kwargs['separators'] = kwargs.get('separators', (',', ':'))
- return format, json.dumps(data[1], *args, **kwargs).encode('utf-8')
+ return format, json.dumps(data[1], *args, **kwargs)
def decode(self, data, *args, **kwargs):
"""decodes the given data from a json string.
@@ -350,8 +351,6 @@ class JSONCodec(Codec):
if isinstance(data[1], buffer_types):
data = data[0], str(data[1])
- elif isinstance(data[1], bytes):
- data = data[0], data[1].decode('utf-8')
data = json.loads(data[1])
if ensure_ascii:
@@ -380,6 +379,56 @@ class JSONCodec(Codec):
return newdict
+class Utf8Codec(Codec):
+ """A codec able to encode/decode utf8 strings to/from bytes.
+ Useful to adapt i/o encodings in a codec pipe.
+
+ Example::
+
+ >>> from taurus.core.util.codecs import CodecFactory
+
+ >>> cf = CodecFactory()
+ >>> codec = cf.getCodec('zip_utf8_json')
+ >>>
+ >>> # first encode something
+ >>> data = { 'hello' : 'world', 'goodbye' : 1000 }
+ >>> format, encoded_data = codec.encode(("", data))
+ >>>
+ >>> # now decode it
+ >>> _, decoded_data = codec.decode((format, encoded_data))
+ >>> print decoded_data
+ """
+
+ def encode(self, data, *args, **kwargs):
+ """
+ Encodes the given utf8 string to bytes.
+
+ :param data: (sequence[str, obj]) a sequence of two elements where the
+ first item is the encoding format of the second item object
+
+ :return: (sequence[str, obj]) a sequence of two elements where the
+ first item is the encoding format of the second item object
+ """
+ format = 'utf8'
+ fmt, data = data
+ if len(fmt):
+ format += '_%s' % fmt
+ return format, str(data).encode()
+
+ def decode(self, data, *args, **kwargs):
+ """decodes the given data from a bytes.
+
+ :param data: (sequence[str, obj]) a sequence of two elements where the
+ first item is the encoding format of the second item object
+
+ :return: (sequence[str, obj]) a sequence of two elements where the
+ first item is the encoding format of the second item object
+ """
+ fmt, data = data
+ fmt = fmt.partition('_')[2]
+ return fmt, bytes(data).decode()
+
+
class BSONCodec(Codec):
"""A codec able to encode/decode to/from bson format. It uses the
:mod:`bson` module.
@@ -550,7 +599,19 @@ class VideoImageCodec(Codec):
imgBuffer = data[1][struct.calcsize(self.VIDEO_HEADER_FORMAT):]
dtype = self.__getDtypeId(header['imageMode'])
- if header['imageMode'] == 7:
+
+ if header['imageMode'] == 6:
+ # RGB24, 3 bytes per pixel
+ rgba = numpy.fromstring(imgBuffer, dtype)
+ bbuf = rgba[0::3]
+ gbuf = rgba[1::3]
+ rbuf = rgba[2::3]
+ r = rbuf.reshape(header['height'], header['width'])
+ g = gbuf.reshape(header['height'], header['width'])
+ b = bbuf.reshape(header['height'], header['width'])
+ img2D = numpy.dstack((r, g, b))
+
+ elif header['imageMode'] == 7:
# RGBA 4 bytes per pixel
rgba = numpy.fromstring(imgBuffer, dtype)
bbuf = rgba[0::4]
@@ -698,7 +759,7 @@ class VideoImageCodec(Codec):
# TODO: other modes
#'RGB555' : 4,#Core.RGB555,
#'RGB565' : 5,#Core.RGB565,
- #'RGB24' : 6,#Core.RGB24,
+ 'RGB24': 6, # Core.RGB24,
'RGB32': 7, # Core.RGB32,
#'BGR24' : 8,#Core.BGR24,
#'BGR32' : 9,#Core.BGR32,
@@ -719,7 +780,7 @@ class VideoImageCodec(Codec):
3: 'L',
#'RGB555' : Core.RGB555,
#'RGB565' : Core.RGB565,
- #'RGB24' : Core.RGB24,
+ 6: 'RGB24', # Core.RGB24,
7: 'RGB32', # Core.RGB32,
# 8 : 'BGR24',#Core.BGR24,
#'BGR32' : Core.BGR32,
@@ -740,7 +801,7 @@ class VideoImageCodec(Codec):
3: 'uint64',
#'RGB555' : Core.RGB555,
#'RGB565' : Core.RGB565,
- # 6 : 'uint8', # Core.RGB24,
+ 6: 'uint8', # Core.RGB24,
7: 'uint8', # Core.RGB32,
#'BGR24' : Core.BGR24,
#'BGR32' : Core.BGR32,
@@ -854,6 +915,7 @@ class CodecFactory(Singleton, Logger):
#: Default minimum map of registered codecs
CODEC_MAP = CaselessDict({
'json': JSONCodec,
+ 'utf8': Utf8Codec,
'bson': BSONCodec,
'bz2': BZ2Codec,
'zip': ZIPCodec,
diff --git a/lib/taurus/core/util/console.py b/lib/taurus/core/util/console.py
index 051f721d..7ffe55c5 100644
--- a/lib/taurus/core/util/console.py
+++ b/lib/taurus/core/util/console.py
@@ -34,8 +34,7 @@ __docformat__ = "restructuredtext"
def make_color_table(in_class, use_name=False, fake=False):
"""Build a set of color attributes in a class.
-
- Helper function for building the *TermColors classes."""
+ Helper function for building the TermColors classes."""
color_templates = (
("Black", "0;30"),
("Red", "0;31"),
diff --git a/lib/taurus/core/util/constant.py b/lib/taurus/core/util/constant.py
index c793322e..ae217333 100644
--- a/lib/taurus/core/util/constant.py
+++ b/lib/taurus/core/util/constant.py
@@ -69,5 +69,7 @@ class _consttype(object):
def __del__(self):
self.__dict__.clear()
-import sys
-sys.modules[__name__] = _consttype()
+
+if __name__ == '__main__':
+ import sys
+ sys.modules[__name__] = _consttype()
diff --git a/lib/taurus/core/util/containers.py b/lib/taurus/core/util/containers.py
index bbc8d762..8fbd5ce6 100644
--- a/lib/taurus/core/util/containers.py
+++ b/lib/taurus/core/util/containers.py
@@ -498,6 +498,8 @@ class LoopList(object):
self._index += 1
return self.current()
+ next = __next__
+
def previous(self):
'''goes one item back in the list and returns it'''
self._index -= 1
diff --git a/lib/taurus/core/util/decorator/__init__.py b/lib/taurus/core/util/decorator/__init__.py
index e69de29b..2ff6c9a0 100644
--- a/lib/taurus/core/util/decorator/__init__.py
+++ b/lib/taurus/core/util/decorator/__init__.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+
+#############################################################################
+##
+# This file is part of Taurus
+##
+# http://taurus-scada.org
+##
+# Copyright 2011 CELLS / ALBA Synchrotron, Bellaterra, Spain
+##
+# Taurus is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+##
+# Taurus 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 Lesser General Public License for more details.
+##
+# You should have received a copy of the GNU Lesser General Public License
+# along with Taurus. If not, see <http://www.gnu.org/licenses/>.
+##
+#############################################################################
+
+"""
+This module provides a few convenience decorators
+""" \ No newline at end of file
diff --git a/lib/taurus/core/util/decorator/decorator.py b/lib/taurus/core/util/decorator/decorator.py
index e26227f1..a3fef8af 100644
--- a/lib/taurus/core/util/decorator/decorator.py
+++ b/lib/taurus/core/util/decorator/decorator.py
@@ -23,36 +23,10 @@
##
#############################################################################
-"""\
-Allow to use decorator either with arguments or not. Example::
-
- @decorator
- def apply(func, *args, **kw):
- return func(*args, **kw)
-
- @decorator
- class apply:
- def __init__(self, *args, **kw):
- self.args = args
- self.kw = kw
-
- def __call__(self, func):
- return func(*self.args, **self.kw)
-
- #
- # Usage in both cases:
- #
- @apply
- def test():
- return 'test'
-
- assert test == 'test'
-
- @apply(2, 3)
- def test(a, b):
- return a + b
-
- assert test == 5"""
+"""
+Provides a decorator to decorate decorators so that they can be used both
+with and without args
+"""
__all__ = ["decorator"]
@@ -63,7 +37,8 @@ import inspect
def decorator(func):
- """Allow to use decorator either with arguments or not. Example::
+ """
+ Allow to use decorator either with arguments or not. Example::
@decorator
def apply(func, *args, **kw):
@@ -92,6 +67,7 @@ def decorator(func):
return a + b
assert test == 5
+
"""
def isFuncArg(*args, **kw):
diff --git a/lib/taurus/core/util/decorator/typecheck.py b/lib/taurus/core/util/decorator/typecheck.py
index 88ec269e..1b015e35 100644
--- a/lib/taurus/core/util/decorator/typecheck.py
+++ b/lib/taurus/core/util/decorator/typecheck.py
@@ -26,12 +26,15 @@
"""
One of three degrees of enforcement may be specified by passing
the 'debug' keyword argument to the decorator:
- 0 -- NONE: No type-checking. Decorators disabled.
- 1 -- MEDIUM: Print warning message to stderr. (Default)
- 2 -- STRONG: Raise TypeError with message.
+
+ - 0 -- NONE: No type-checking. Decorators disabled.
+ - 1 -- MEDIUM: Print warning message to stderr. (Default)
+ - 2 -- STRONG: Raise TypeError with message.
+
If 'debug' is not passed to the decorator, the default level is used.
-Example usage:
+Example usage::
+
>>> NONE, MEDIUM, STRONG = 0, 1, 2
>>>
>>> @accepts(int, int, int)
@@ -47,7 +50,7 @@ Example usage:
TypeWarning: 'average' method returns (float), but result is (int)
15
-Needed to cast params as floats in function def (or simply divide by 2.0).
+Needed to cast params as floats in function def (or simply divide by 2.0)::
>>> TYPE_CHECK = STRONG
>>> @accepts(int, debug=TYPE_CHECK)
@@ -71,15 +74,12 @@ __all__ = ["accepts", "returns"]
__docformat__ = "restructuredtext"
def accepts(*types, **kw):
- """ Function decorator. Checks that inputs given to decorated function
+ """
+ Function decorator. Checks that inputs given to decorated function
are of the expected type.
- Parameters:
- types -- The expected types of the inputs to the decorated function.
- Must specify type for each parameter.
- kw -- Optional specification of 'debug' level (this is the only valid
- keyword argument, no other should be given).
- debug = ( 0 | 1 | 2 )
+ :param types: The expected type of the decorated function's return value
+ :param debug: Optional specification of 'debug' level (0 | 1 | 2)
"""
if not kw:
@@ -111,15 +111,12 @@ def accepts(*types, **kw):
def returns(ret_type, **kw):
- """ Function decorator. Checks that return value of decorated function
+ """
+ Function decorator. Checks that return value of decorated function
is of the expected type.
- Parameters:
- ret_type -- The expected type of the decorated function's return value.
- Must specify type for each parameter.
- kw -- Optional specification of 'debug' level (this is the only valid
- keyword argument, no other should be given).
- debug=(0 | 1 | 2)
+ :param ret_type: The expected type of the decorated function's return value.
+ :param debug: Optional specification of 'debug' level (0 | 1 | 2)
"""
try:
diff --git a/lib/taurus/core/util/event.py b/lib/taurus/core/util/event.py
index d2e67449..e77f6f20 100644
--- a/lib/taurus/core/util/event.py
+++ b/lib/taurus/core/util/event.py
@@ -106,7 +106,8 @@ def CallableRef(object, del_cb=None):
:type del_cb: callable object or None
:return: a weak reference for the given callable
- :rtype: BoundMethodWeakref or weakref.ref"""
+ :rtype: taurus.core.util.BoundMethodWeakref or weakref.ref
+ """
im_self = None
if hasattr(object, '__self__'):
im_self = object.__self__
diff --git a/lib/taurus/core/util/parse_args.py b/lib/taurus/core/util/parse_args.py
index 3da75c67..034c4abb 100644
--- a/lib/taurus/core/util/parse_args.py
+++ b/lib/taurus/core/util/parse_args.py
@@ -33,10 +33,10 @@ def parse_args(s, strip_pars=False):
corresponding args and kwargs.
:param s: string representing arguments to a method
- :type strip_pars: (bool) If True, expect s to include surrounding
- parenthesis
+ :param strip_pars: (bool) If True, expect s to include surrounding
+ parenthesis
:return: args, kwargs (a list of positional arguments and a dict of keyword
- arguments)
+ arguments)
"""
s = s.strip()
if strip_pars:
diff --git a/lib/taurus/core/util/property_parser.py b/lib/taurus/core/util/property_parser.py
index 784055c2..4b981b21 100644
--- a/lib/taurus/core/util/property_parser.py
+++ b/lib/taurus/core/util/property_parser.py
@@ -101,7 +101,7 @@ def t_STRING(t):
def t_KEY(t):
- r'[a-zA-Z0-9_\.\/]+'
+ r'[a-zA-Z0-9/_\.\/]+'
t.type = reserved.get(t.value, 'KEY') # Check for reserved words
return t
diff --git a/lib/taurus/core/util/propertyfile.py b/lib/taurus/core/util/propertyfile.py
index a608b884..91182aaf 100644
--- a/lib/taurus/core/util/propertyfile.py
+++ b/lib/taurus/core/util/propertyfile.py
@@ -246,9 +246,6 @@ class Properties(object):
def load(self, stream):
""" Load properties from an open file stream """
- # For the time being only accept file input streams
- if type(stream) is not file:
- raise TypeError('Argument should be a file object!')
# Check for the opened mode
if stream.mode != 'r':
raise ValueError('Stream should be opened in read-only mode!')
diff --git a/lib/taurus/core/util/remotelogmonitor.py b/lib/taurus/core/util/remotelogmonitor.py
index 9b7988be..9fbf673f 100644
--- a/lib/taurus/core/util/remotelogmonitor.py
+++ b/lib/taurus/core/util/remotelogmonitor.py
@@ -38,6 +38,7 @@ import logging
import logging.handlers
import struct
import weakref
+import click
import socketserver
@@ -181,47 +182,26 @@ def log(host, port, name=None, level=None):
print("\nCancelled", msg)
-def main(argv=None):
- import optparse
- import socket
-
- import taurus.core.util.log
-
- taurus.setLogLevel(taurus.Trace)
-
- dft_port = logging.handlers.DEFAULT_TCP_LOGGING_PORT
-
+@click.command('logmon')
+@click.option('--port', 'port', type=int,
+ default=logging.handlers.DEFAULT_TCP_LOGGING_PORT,
+ show_default=True,
+ help='port where log server is running')
+@click.option('--log-name', 'log_name', default=None,
+ help='filter specific log object')
+@click.option('--log-level', 'log_level',
+ type=click.Choice(['critical', 'error', 'warning', 'info',
+ 'debug', 'trace']),
+ default='debug', show_default=True,
+ help='filter specific log level')
+def logmon_cmd(port, log_name, log_level):
+ """Show the console-based Taurus Remote Log Monitor"""
+ import taurus
host = socket.gethostname()
+ level = getattr(taurus, log_level.capitalize(), taurus.Trace)
- help_port = "port where log server is running [default: %d]" % dft_port
- help_name = "filter specific log object [default: None, meaning don't " \
- "filter]"
- help_level = "filter specific log level." \
- "Allowed values are (case insensitive): critical, "\
- "error, warning/warn, info, debug, trace [default: debug]."
-
- parser = optparse.OptionParser()
- parser.add_option("--log-port", dest="log_port", default=dft_port,
- type="int", help=help_port)
- parser.add_option("--log-name", dest="log_name", default=None,
- type="string", help=help_name)
- parser.add_option("--log-level", dest="log_level", default="debug",
- type="string", help=help_level)
-
- if argv is None:
- import sys
- argv = sys.argv
-
- options, args = parser.parse_args(args=argv)
-
- port, name = options.log_port, options.log_name
- level_str = options.log_level.capitalize()
-
- level = None
- if hasattr(taurus, level_str):
- level = getattr(taurus, level_str)
+ log(host=host, port=port, name=log_name, level=level)
- log(host, port, name=name, level=level)
if __name__ == '__main__':
- main()
+ logmon_cmd()
diff --git a/lib/taurus/core/util/tablepprint.py b/lib/taurus/core/util/tablepprint.py
index cab4c13e..70552cfe 100644
--- a/lib/taurus/core/util/tablepprint.py
+++ b/lib/taurus/core/util/tablepprint.py
@@ -41,23 +41,21 @@ __docformat__ = "restructuredtext"
def indent(rows, hasHeader=False, headerChar='-', delim=' | ', justify='left',
separateRows=False, prefix='', postfix='', wrapfunc=lambda x: x):
"""Indents a table by column.
- - rows: A sequence of sequences of items, one sequence per row.
- - hasHeader: True if the first row consists of the columns' names.
- - headerChar: Character to be used for the row separator line
- (if hasHeader==True or separateRows==True).
- - delim: The column delimiter.
- - justify: Determines how are data justified in their column.
- Valid values are 'left','right' and 'center'.
- - separateRows: True if rows are to be separated by a line
- of 'headerChar's.
- - prefix: A string prepended to each printed row.
- - postfix: A string appended to each printed row.
- - wrapfunc: A function f(text) for wrapping text; each element in
- the table is first wrapped by this function.
-
- Returns a list of strings. One for each row of the table
+ :param rows: A sequence of sequences of items, one sequence per row.
+ :param hasHeader: True if the first row consists of the columns' names.
+ :param headerChar: Character to be used for the row separator line
+ (if hasHeader==True or separateRows==True).
+ :param delim: The column delimiter.
+ :param justify: Determines how are data justified in their column.
+ Valid values are 'left','right' and 'center'.
+ :param separateRows: True if rows are to be separated by a line of
+ 'headerChar's.
+ :param prefix: A string prepended to each printed row.
+ :param postfix: A string appended to each printed row.
+ :param wrapfunc: A function f(text) for wrapping text;
+ each element in the table is first wrapped by this function.
+ :return: a list of strings. One for each row of the table
"""
-
# closure for breaking logical rows to physical, using wrapfunc
def rowWrapper(row):
newRows = [wrapfunc(item).split('\n') for item in row]
@@ -102,10 +100,9 @@ def indent(rows, hasHeader=False, headerChar='-', delim=' | ', justify='left',
def wrap_onspace(text, width):
- """
- A word-wrap function that preserves existing line breaks
+ """A word-wrap function that preserves existing line breaks
and most spaces in the text. Expects that existing line
- breaks are posix newlines (\n).
+ breaks are posix newlines (\\\\n).
"""
return reduce(lambda line, word, width=width: '%s%s%s' %
(line,
diff --git a/lib/taurus/core/util/test/test_codecs.py b/lib/taurus/core/util/test/test_codecs.py
index 0543ca87..0746a5d8 100644
--- a/lib/taurus/core/util/test/test_codecs.py
+++ b/lib/taurus/core/util/test/test_codecs.py
@@ -38,7 +38,7 @@ import numpy
@insertTest(helper_name='encDec', cname='json', data=[1, 2, 3])
@insertTest(helper_name='encDec', cname='zip', data=b'foobar')
-@insertTest(helper_name='encDec', cname='zip_json', data=[1, 2, 3])
+@insertTest(helper_name='encDec', cname='zip_utf8_json', data=[1, 2, 3])
@insertTest(helper_name='encDec', cname='videoimage',
data=numpy.ones((2, 2), dtype='uint8'))
@insertTest(helper_name='encDec', cname='zip_null_zip_videoimage',
diff --git a/lib/taurus/core/util/whichexecutable.py b/lib/taurus/core/util/whichexecutable.py
index 29ce10e6..926e0980 100644
--- a/lib/taurus/core/util/whichexecutable.py
+++ b/lib/taurus/core/util/whichexecutable.py
@@ -42,7 +42,7 @@ def whichfile(filename, exts=None):
Example::
# on a debian machine with taurus installed in the default path:
- whichfile('taurusform') --> '/usr/bin/taurusform'
+ whichfile('taurus') --> '/usr/bin/taurus'
# or, on a winXP machine:
whichfile('command') --> 'C:\\WINDOWS\\system32\\command.COM'