Hello community, here is the log from the commit of package python3-veusz for openSUSE:Factory checked in at 2016-01-05 09:41:24 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python3-veusz (Old) and /work/SRC/openSUSE:Factory/.python3-veusz.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-veusz" Changes: -------- --- /work/SRC/openSUSE:Factory/python3-veusz/python3-veusz.changes 2015-06-23 11:59:14.000000000 +0200 +++ /work/SRC/openSUSE:Factory/.python3-veusz.new/python3-veusz.changes 2016-01-05 09:41:52.000000000 +0100 @@ -1,0 +2,14 @@ +Thu Dec 31 20:10:07 UTC 2015 - [email protected] + +- Update to version 1.23.2: + * Add data clipping dataset plugin + * Fix boxplot with manual settings + * Fix plugin normalize and divide by maximum for new numpy versions + * Avoid error in 2d data creation + * Fix problems with unicode characters in plugins in Python 2.x + * Clip axis to sensible range -1e100->1e100 + * Handle unicode errors from operating system in Veusz scripts + * Handle unicode errors in error reports + * Fix crash in \color + +------------------------------------------------------------------- Old: ---- veusz-1.23.1.tar.gz New: ---- veusz-1.23.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python3-veusz.spec ++++++ --- /var/tmp/diff_new_pack.1WNYT0/_old 2016-01-05 09:41:53.000000000 +0100 +++ /var/tmp/diff_new_pack.1WNYT0/_new 2016-01-05 09:41:53.000000000 +0100 @@ -19,7 +19,7 @@ %define appname veusz3 Name: python3-veusz -Version: 1.23.1 +Version: 1.23.2 Release: 0 Summary: Scientific plotting library for Python License: GPL-2.0+ and Python-2.0 ++++++ veusz-1.23.1.tar.gz -> veusz-1.23.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/ChangeLog new/veusz-1.23.2/ChangeLog --- old/veusz-1.23.1/ChangeLog 2015-06-14 12:28:08.000000000 +0200 +++ new/veusz-1.23.2/ChangeLog 2015-12-23 12:37:33.000000000 +0100 @@ -1,3 +1,14 @@ +Changes in 1.23.2: + * Add data clipping dataset plugin + * Fix boxplot with manual settings + * Fix plugin normalize and divide by maximum for new numpy versions + * Avoid error in 2d data creation + * Fix problems with unicode characters in plugins in Python 2.x + * Clip axis to sensible range -1e100->1e100 + * Handle unicode errors from operating system in Veusz scripts + * Handle unicode errors in error reports + * Fix crash in \color + Changes in 1.23.1: * Enable compression in exported files (Benjamin K. Stuhl) * Fix saving histogram datasets diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/INSTALL new/veusz-1.23.2/INSTALL --- old/veusz-1.23.1/INSTALL 2015-06-13 10:22:03.000000000 +0200 +++ new/veusz-1.23.2/INSTALL 2015-12-23 12:37:30.000000000 +0100 @@ -36,7 +36,7 @@ To install on linux to the standard location on the hard disk -# cd veusz-1.23.1 +# cd veusz-1.23.2 # python setup.py build # su [enter root password] @@ -94,8 +94,8 @@ If you don't want to install veusz fully or are doing development, it can currently be run from its own directory. Do -# tar xzf veusz-1.23.1.tar.gz [change version here] -# cd veusz-1.23.1 +# tar xzf veusz-1.23.2.tar.gz [change version here] +# cd veusz-1.23.2 # ./run_veusz_inplace Certain features will be disabled if you do this. You will not be able @@ -117,8 +117,8 @@ incompatibilities. Simply unpack the tar file and run the main executable: -# tar xzf veusz-linux-i386-1.23.1.tar.gz [change version here] -# cd veusz-linux-i386-1.23.1 +# tar xzf veusz-linux-i386-1.23.2.tar.gz [change version here] +# cd veusz-linux-i386-1.23.2 # ./veusz 2.2 Installing in Windows diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/PKG-INFO new/veusz-1.23.2/PKG-INFO --- old/veusz-1.23.1/PKG-INFO 2015-06-14 12:37:53.000000000 +0200 +++ new/veusz-1.23.2/PKG-INFO 2015-12-23 13:55:21.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: veusz -Version: 1.23.1 +Version: 1.23.2 Summary: A scientific plotting package Home-page: http://home.gna.org/veusz/ Author: Jeremy Sanders diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/README new/veusz-1.23.2/README --- old/veusz-1.23.1/README 2015-06-14 12:28:11.000000000 +0200 +++ new/veusz-1.23.2/README 2015-12-23 12:37:16.000000000 +0100 @@ -1,4 +1,4 @@ -Veusz 1.23.1 +Veusz 1.23.2 ------------ http://home.gna.org/veusz/ @@ -12,6 +12,17 @@ manipulation and editing of datasets. Data can be captured from external sources such as Internet sockets or other programs. +Changes in 1.23.2: + * Add data clipping dataset plugin + * Fix boxplot with manual settings + * Fix plugin normalize and divide by maximum for new numpy versions + * Avoid error in 2d data creation + * Fix problems with unicode characters in plugins in Python 2.x + * Clip axis to sensible range -1e100->1e100 + * Handle unicode errors from operating system in Veusz scripts + * Handle unicode errors in error reports + * Fix crash in \color + Changes in 1.23.1: * Enable compression in exported files (Benjamin K. Stuhl) * Fix saving histogram datasets diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/VERSION new/veusz-1.23.2/VERSION --- old/veusz-1.23.1/VERSION 2015-06-13 10:20:39.000000000 +0200 +++ new/veusz-1.23.2/VERSION 2015-12-23 12:36:35.000000000 +0100 @@ -1 +1 @@ -1.23.1 +1.23.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/ui/exceptionlist.ui new/veusz-1.23.2/ui/exceptionlist.ui --- old/veusz-1.23.1/ui/exceptionlist.ui 2014-12-22 13:42:32.000000000 +0100 +++ new/veusz-1.23.2/ui/exceptionlist.ui 2015-08-30 10:44:35.000000000 +0200 @@ -82,6 +82,13 @@ </widget> </item> <item> + <widget class="QPushButton" name="saveButton"> + <property name="text"> + <string>Save report</string> + </property> + </widget> + </item> + <item> <widget class="QPushButton" name="cancelButton"> <property name="text"> <string>&Ignore this time</string> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/compat.py new/veusz-1.23.2/veusz/compat.py --- old/veusz-1.23.1/veusz/compat.py 2015-04-05 14:38:55.000000000 +0200 +++ new/veusz-1.23.2/veusz/compat.py 2015-11-22 12:56:22.000000000 +0100 @@ -80,6 +80,12 @@ # exec function cexec = getattr(cbuiltins, 'exec') + # execfile + def cexecfile(filename, globaldict): + with open(filename) as f: + code = compile(f.read(), filename, 'exec') + cexec(code, globaldict) + # convert strerror exception to string def cstrerror(ex): return ex.strerror @@ -90,6 +96,10 @@ return 'u' + repr(v) return repr(v) + # convert exception to a user string + def cexceptionuser(ex): + return str(ex) + else: # py2 @@ -152,15 +162,28 @@ code = 'exec text in globdict' exec(code) + # execfile + def cexecfile(filename, globaldict): + execfile(filename, globaldict) + # convert strerror exception to string def cstrerror(ex): if isinstance(ex.strerror, str): - deflocale = locale.getdefaultlocale()[1] - if deflocale is None: - deflocale = 'ascii' + deflocale = locale.getdefaultlocale()[1] or 'ascii' return ex.strerror.decode(deflocale) else: return ex.strerror + # sometimes exceptions come as unicode, sometimes as strings + # encoded in ascii, so we have to decode + def cexceptionuser(ex): + if hasattr(ex, 'strerror') and isinstance(ex.strerror, str): + # comes from operating system as encoded + deflocale = locale.getdefaultlocale()[1] or 'ascii' + return str(ex).decode(deflocale) + else: + # let's hope this works + return unicode(ex) + # py2/3 repr crepr = repr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/dialogs/datacreate2d.py new/veusz-1.23.2/veusz/dialogs/datacreate2d.py --- old/veusz-1.23.1/veusz/dialogs/datacreate2d.py 2015-04-22 19:41:20.000000000 +0200 +++ new/veusz-1.23.2/veusz/dialogs/datacreate2d.py 2015-11-22 11:20:19.000000000 +0100 @@ -19,7 +19,7 @@ """Dataset creation dialog for 2d data.""" from __future__ import division -from ..compat import crange, citems +from ..compat import crange, citems, cstr from .. import qtall as qt4 from .. import utils from .. import document @@ -95,7 +95,7 @@ if ds.datatype == 'numeric': datasets[ds.dimensions-1].append(name) datasets[0].sort() - datasets[1].sort() + datasets[1].sort() # make sure names are escaped if they have funny characters self.escapeDatasets(datasets[0]) @@ -163,7 +163,7 @@ disable = False # need name and zexpr disable = disable or not text['name'] or not text['zexpr'] - + if self.mode == 'xyzexpr': # need x and yexpr disable = disable or not text['xexpr'] or not text['yexpr'] @@ -171,7 +171,7 @@ elif self.mode == '2dexpr': # nothing else pass - + elif self.mode == 'xyfunc': # need x and yexpr in special step format min:max:step disable = disable or ( checkGetStep(text['xexpr']) is None or @@ -179,7 +179,7 @@ # finally check button self.createbutton.setDisabled(disable) - + def createButtonClickedSlot(self): """Create button pressed.""" @@ -188,29 +188,30 @@ text[name] = getattr(self, name+'combo').currentText().strip() link = self.linkcheckbox.checkState() == qt4.Qt.Checked - if self.mode == 'xyzexpr': - # build operation - op = document.OperationDataset2DCreateExpressionXYZ( - text['name'], - text['xexpr'], text['yexpr'], text['zexpr'], - link) - - elif self.mode == '2dexpr': - op = document.OperationDataset2DCreateExpression( - text['name'], text['zexpr'], link) - - elif self.mode == 'xyfunc': - xstep = checkGetStep(text['xexpr']) - ystep = checkGetStep(text['yexpr']) - # build operation - op = document.OperationDataset2DXYFunc( - text['name'], - xstep, ystep, - text['zexpr'], link) - - # apply operation, catching evaluation errors + # create and apply operation, catching evaluation errors try: + if self.mode == 'xyzexpr': + # build operation + op = document.OperationDataset2DCreateExpressionXYZ( + text['name'], + text['xexpr'], text['yexpr'], text['zexpr'], + link) + + elif self.mode == '2dexpr': + op = document.OperationDataset2DCreateExpression( + text['name'], text['zexpr'], link) + + elif self.mode == 'xyfunc': + xstep = checkGetStep(text['xexpr']) + ystep = checkGetStep(text['yexpr']) + + # build operation + op = document.OperationDataset2DXYFunc( + text['name'], + xstep, ystep, + text['zexpr'], link) + # check expression is okay op.validateExpression(self.document) @@ -218,15 +219,20 @@ self.document.applyOperation(op) # forces an evaluation self.document.data[text['name']].data + except (document.CreateDatasetException, - document.DatasetException): + document.DatasetException) as e: + msg = _("Failed to create dataset '%s'") % text['name'] + s = cstr(e) + if s: + msg += ' (%s)' % s else: msg = _("Created dataset '%s'") % text['name'] self.notifylabel.setText(msg) qt4.QTimer.singleShot(4000, self.notifylabel.clear) - + def recreateDataset(mainwindow, document, dataset, datasetname): """Open dialog to recreate a DatasetExpression / DatasetRange.""" dialog = DataCreate2DDialog(mainwindow, document) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/dialogs/exceptiondialog.py new/veusz-1.23.2/veusz/dialogs/exceptiondialog.py --- old/veusz-1.23.1/veusz/dialogs/exceptiondialog.py 2015-04-05 14:38:55.000000000 +0200 +++ new/veusz-1.23.2/veusz/dialogs/exceptiondialog.py 2015-11-22 14:05:29.000000000 +0100 @@ -15,7 +15,7 @@ # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. ############################################################################## - + '''Dialog to pop up if an exception occurs in Veusz. This allows the user to send a bug report in via email.''' @@ -29,7 +29,7 @@ import numpy import sip -from ..compat import citems, curlrequest +from ..compat import citems, curlrequest, cexceptionuser from .. import qtall as qt4 from .. import utils from .veuszdialog import VeuszDialog @@ -38,6 +38,8 @@ """Translate text.""" return qt4.QCoreApplication.translate(context, text, disambiguation) +_emailUrl ='http://barmag.net/veusz-mail.php' + _reportformat = \ '''Veusz version: %s Python version: %s @@ -63,25 +65,28 @@ %s ''' +def createReportText(exception): + return _reportformat % ( + utils.version(), + sys.version, + sys.platform, + numpy.__version__, + qt4.qVersion(), + qt4.PYQT_VERSION_STR, + sip.SIP_VERSION_STR, + time.strftime('%a, %d %b %Y %H:%M:%S +0000', time.gmtime()), + cexceptionuser(exception), + ) + class ExceptionSendDialog(VeuszDialog): """Dialog to send debugging report.""" - + def __init__(self, exception, parent): VeuszDialog.__init__(self, parent, 'exceptionsend.ui') # debugging report text - self.text = _reportformat % ( - utils.version(), - sys.version, - sys.platform, - numpy.__version__, - qt4.qVersion(), - qt4.PYQT_VERSION_STR, - sip.SIP_VERSION_STR, - time.strftime('%a, %d %b %Y %H:%M:%S +0000', time.gmtime()), - exception - ) + self.text = createReportText(exception) self.detailstosend.setPlainText(self.text) def accept(self): @@ -98,9 +103,8 @@ try: # send the message - curlrequest.urlopen('http://barmag.net/veusz-mail.php', + curlrequest.urlopen(_emailUrl, 'message=%s' % text) - except: # something went wrong... qt4.QMessageBox.critical(None, _("Veusz"), @@ -170,7 +174,7 @@ class ExceptionDialog(VeuszDialog): """Choose an exception to send to developers.""" - + ignore_exceptions = set() def __init__(self, exception, parent): @@ -189,9 +193,13 @@ self.erroriconlabel.setPixmap(icon.pixmap(32)) self.ignoreSessionButton.clicked.connect(self.ignoreSessionSlot) - + self.saveButton.clicked.connect(self.saveButtonSlot) + self.checkVeuszVersion() + if not _emailUrl: + self.okButton.hide() + def checkVeuszVersion(self): """See whether there is a later version of veusz and inform the user.""" @@ -225,12 +233,21 @@ d = ExceptionSendDialog(self.backtrace, self) if d.exec_() == qt4.QDialog.Accepted: VeuszDialog.accept(self) - + def ignoreSessionSlot(self): """Ignore exception for session.""" ExceptionDialog.ignore_exceptions.add(self.fmtexcept) self.reject() + def saveButtonSlot(self): + filename = qt4.QFileDialog.getSaveFileName(self, 'Save File') + if filename: + f = open(filename, 'w') + f.write(createReportText(self.backtrace)) + f.close() + + self.close() + def exec_(self): """Exec dialog if exception is not ignored.""" if self.fmtexcept not in ExceptionDialog.ignore_exceptions: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/document/datasets.py new/veusz-1.23.2/veusz/document/datasets.py --- old/veusz-1.23.1/veusz/document/datasets.py 2015-06-14 12:15:17.000000000 +0200 +++ new/veusz-1.23.2/veusz/document/datasets.py 2015-11-22 11:15:10.000000000 +0100 @@ -1692,14 +1692,19 @@ Dataset2DBase.__init__(self) + if xstep is None or ystep is None: + raise DatasetException('Steps are not set') + self.xstep = xstep self.ystep = ystep self.expr = expr - self.xrange = (self.xstep[0] - self.xstep[2]*0.5, - self.xstep[1] + self.xstep[2]*0.5) - self.yrange = (self.ystep[0] - self.ystep[2]*0.5, - self.ystep[1] + self.ystep[2]*0.5) + self.xrange = ( + self.xstep[0] - self.xstep[2]*0.5, + self.xstep[1] + self.xstep[2]*0.5) + self.yrange = ( + self.ystep[0] - self.ystep[2]*0.5, + self.ystep[1] + self.ystep[2]*0.5) self.xedge = self.yedge = self.xcent = self.ycent = None self.cacheddata = None diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/document/doc.py new/veusz-1.23.2/veusz/document/doc.py --- old/veusz-1.23.1/veusz/document/doc.py 2015-06-08 19:39:31.000000000 +0200 +++ new/veusz-1.23.2/veusz/document/doc.py 2015-11-22 11:35:07.000000000 +0100 @@ -36,7 +36,7 @@ except ImportError: h5py = None -from ..compat import crange, citems, cvalues, cstr, cexec, CStringIO +from ..compat import crange, citems, cvalues, cstr, cexec, CStringIO, cexecfile from .. import qtall as qt4 from . import widgetfactory @@ -415,7 +415,7 @@ for plugin in pluginlist: try: - cexec(compile(open(plugin).read(), plugin, 'exec'), dict()) + cexecfile(plugin, {}) except Exception: err = _('Error loading plugin %s\n\n%s') % ( plugin, traceback.format_exc()) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/document/loader.py new/veusz-1.23.2/veusz/document/loader.py --- old/veusz-1.23.1/veusz/document/loader.py 2015-04-22 19:41:20.000000000 +0200 +++ new/veusz-1.23.2/veusz/document/loader.py 2015-11-22 13:02:21.000000000 +0100 @@ -28,7 +28,7 @@ from .. import setting from .. import utils -from ..compat import cexec, cstr, cstrerror, cbytes +from ..compat import cexec, cstr, cstrerror, cbytes, cexceptionuser from .commandinterface import CommandInterface from . import datasets @@ -69,7 +69,7 @@ def genexception(exc): info = sys.exc_info() backtrace = ''.join(traceback.format_exception(*info)) - return LoadError(cstr(exc), backtrace=backtrace) + return LoadError(cexceptionuser(exc), backtrace=backtrace) # compile script and check for security (if reqd) unsafe = [setting.transient_settings['unsafe_mode']] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/plugins/datasetplugin.py new/veusz-1.23.2/veusz/plugins/datasetplugin.py --- old/veusz-1.23.1/veusz/plugins/datasetplugin.py 2015-06-12 20:18:17.000000000 +0200 +++ new/veusz-1.23.2/veusz/plugins/datasetplugin.py 2015-11-22 10:53:56.000000000 +0100 @@ -20,7 +20,7 @@ """Plugins for creating datasets.""" -from __future__ import division +from __future__ import division, print_function import numpy as N from . import field @@ -212,7 +212,7 @@ # class to pass to plugin to give parameters class DatasetPluginHelper(object): """Helpers to get existing datasets for plugins.""" - + def __init__(self, doc): """Construct helper object to pass to DatasetPlugins.""" self._doc = doc @@ -287,7 +287,7 @@ if isinstance(ds, document.DatasetDateTime): return DatasetDateTime(name, data=ds.data) elif ds.dimensions == 1: - return Dataset1D(name, data=ds.data, serr=ds.serr, + return Dataset1D(name, data=ds.data, serr=ds.serr, perr=ds.perr, nerr=ds.nerr) elif ds.dimensions == 2: return Dataset2D(name, ds.data, @@ -327,7 +327,7 @@ doc - document instance fields - fields to pass to plugin """ - + self.plugin = plugin self.document = doc self.helper = DatasetPluginHelper(doc) @@ -487,7 +487,7 @@ f = N.isfinite(d.data) if errortype == 'symmetric' and d.serr is not None: - serr[f] += d.serr[f]**2 + serr[f] += d.serr[f]**2 elif errortype == 'asymmetric': if d.serr is not None: v = (d.serr[f])**2 @@ -521,7 +521,7 @@ f = f[:length] if errortype == 'symmetric' and d.serr is not None: - serr[f] += (d.serr[f]/d.data[f])**2 + serr[f] += (d.serr[f]/d.data[f])**2 elif errortype == 'asymmetric': if d.serr is not None: v = (d.serr[f]/d.data[f])**2 @@ -548,7 +548,7 @@ description_short = _('Multiply dataset by a constant') description_full = _('Multiply a dataset by a factor. ' 'Error bars are also scaled.') - + def __init__(self): """Define fields.""" self.fields = [ @@ -579,7 +579,7 @@ description_short = _('Add a constant to a dataset') description_full = _('Add a dataset by adding a value. ' 'Error bars remain the same.') - + def __init__(self): """Define fields.""" self.fields = [ @@ -948,7 +948,7 @@ description_short = _('Subtract two datasets') description_full = _('Subtract two datasets. ' 'Combined error bars are also calculated.') - + def __init__(self): """Define fields.""" self.fields = [ @@ -1063,7 +1063,7 @@ description_short = _('Multiply two or more datasets') description_full = _('Multiply two or more datasets. ' 'Combined error bars are also calculated.') - + def __init__(self): """Define fields.""" self.fields = [ @@ -1103,7 +1103,7 @@ ' between two datasets') description_full = _('Divide or compute fractional difference' ' between two datasets') - + def __init__(self): """Define fields.""" self.fields = [ @@ -1162,9 +1162,9 @@ data = data / maxval # divide error bars serr = perr = nerr = None - if inds.serr: serr = inds.serr / maxval - if inds.perr: perr = inds.perr / maxval - if inds.nerr: nerr = inds.nerr / maxval + if inds.serr is not None: serr = inds.serr / maxval + if inds.perr is not None: perr = inds.perr / maxval + if inds.nerr is not None: nerr = inds.nerr / maxval self.dsout.update(data=data, serr=serr, perr=perr, nerr=nerr) @@ -1198,9 +1198,9 @@ data = data / tot # divide error bars serr = perr = nerr = None - if inds.serr: serr = inds.serr / tot - if inds.perr: perr = inds.perr / tot - if inds.nerr: nerr = inds.nerr / tot + if inds.serr is not None: serr = inds.serr / tot + if inds.perr is not None: perr = inds.perr / tot + if inds.nerr is not None: nerr = inds.nerr / tot self.dsout.update(data=data, serr=serr, perr=perr, nerr=nerr) @@ -1427,7 +1427,7 @@ description_short = _('Filter a dataset using an expression') description_full = _('Filter a dataset using an expression, ' 'e.g. "x>10" or "(x>1) & (y<2)"') - + def __init__(self): """Define fields.""" self.fields = [ @@ -1482,7 +1482,7 @@ description_full = _('Compute moving average for regularly spaced data.' 'Average is computed either\nside of each data point ' 'by number of points given.') - + def __init__(self): """Define fields.""" self.fields = [ @@ -1493,7 +1493,7 @@ default=True), field.FieldDataset('ds_out', _('Output dataset')), ] - + def updateDatasets(self, fields, helper): """Do shifting of dataset.""" ds_in = helper.getDataset(fields['ds_in']) @@ -1873,6 +1873,68 @@ self.dsout.update(data=data) +class ClipPlugin(_OneOutputDatasetPlugin): + """Compute moving average for dataset.""" + + menu = (_('Compute'), _('Clipped dataset'),) + name = 'Clip' + description_short = _('Clip data between a minimum and maximum') + description_full = _('Clip data points to minimum and/or maximum values') + + def __init__(self): + """Define fields.""" + self.fields = [ + field.FieldDataset('ds_in', _('Input dataset')), + field.FieldFloat('minimum', _('Minimum'), default=0.), + field.FieldBool('disablemin', _('Disable minimum')), + field.FieldFloat('maximum', _('Maximum'), default=1.), + field.FieldBool('disablemax', _('Disable maximum')), + field.FieldBool('cliperrs', _('Clip error bars'), default=True), + field.FieldDataset('ds_out', _('Output dataset')), + ] + + def updateDatasets(self, fields, helper): + """Do shifting of dataset.""" + ds_in = helper.getDataset(fields['ds_in']) + data = N.array(ds_in.data) + perr = getattr(ds_in, 'perr') + nerr = getattr(ds_in, 'nerr') + serr = getattr(ds_in, 'serr') + + cliperrs = fields['cliperrs'] + # force asymmetric errors if clipping error bars + if cliperrs and serr is not None and (nerr is None or perr is None): + perr = serr + nerr = -serr + serr = None + + # we have to clip the ranges, so calculate these first + upper = (data+perr) if (cliperrs and perr is not None) else None + lower = (data+nerr) if (cliperrs and nerr is not None) else None + + # note: this preserves nan values + if not fields['disablemin']: + minv = fields['minimum'] + data[data<minv] = minv + if upper is not None: + upper[upper<minv] = minv + if lower is not None: + lower[lower<minv] = minv + if not fields['disablemax']: + maxv = fields['maximum'] + data[data>maxv] = maxv + if upper is not None: + upper[upper>maxv] = maxv + if lower is not None: + lower[lower>maxv] = maxv + + if upper is not None: + perr = upper-data + if lower is not None: + nerr = lower-data + + self.dsout.update(data=data, serr=serr, perr=perr, nerr=nerr) + datasetpluginregistry += [ AddDatasetPlugin, AddDatasetsPlugin, @@ -1887,6 +1949,7 @@ MeanDatasetPlugin, ExtremesDatasetPlugin, CumulativePlugin, + ClipPlugin, ConcatenateDatasetPlugin, InterleaveDatasetPlugin, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/utils/textrender.py new/veusz-1.23.2/veusz/utils/textrender.py --- old/veusz-1.23.1/veusz/utils/textrender.py 2015-04-05 14:38:55.000000000 +0200 +++ new/veusz-1.23.2/veusz/utils/textrender.py 2015-11-28 16:32:26.000000000 +0100 @@ -1004,7 +1004,7 @@ def __init__(self, children): try: self.colorname = children[0].text - except AttributeError: + except (AttributeError, IndexError): self.colorname = '' self.children = children[1:] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/utils/version.py new/veusz-1.23.2/veusz/utils/version.py --- old/veusz-1.23.1/veusz/utils/version.py 2015-04-05 14:38:55.000000000 +0200 +++ new/veusz-1.23.2/veusz/utils/version.py 2015-07-09 20:01:34.000000000 +0200 @@ -29,21 +29,22 @@ from . import utilfuncs -def version(): - """Return the version number as a string.""" - - try: - f = open( os.path.join(utilfuncs.resourceDirectory, 'VERSION') ) - except EnvironmentError: - sys.stderr.write(''' -Failed to find VERSION file. +_errmsg = """Failed to find VERSION file. This is probably because the resource files are not installed in the python module directory. You may need to set the environment variable VEUSZ_RESOURCE_DIR or add a "resources" symlink in the main veusz module directory pointing to the directory where resources are located. See INSTALL for details. -'''.lstrip()) - sys.exit(1) +""" - return f.readline().strip() +def version(): + """Return the version number as a string.""" + + filename = os.path.join(utilfuncs.resourceDirectory, "VERSION") + try: + with open(filename) as f: + return f.readline().strip() + except EnvironmentError: + sys.stderr.write(_errmsg) + sys.exit(1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/widgets/axisfunction.py new/veusz-1.23.2/veusz/widgets/axisfunction.py --- old/veusz-1.23.1/veusz/widgets/axisfunction.py 2015-04-05 14:38:55.000000000 +0200 +++ new/veusz-1.23.2/veusz/widgets/axisfunction.py 2015-08-11 16:11:44.000000000 +0200 @@ -508,7 +508,7 @@ def _linearInterpolWarning(self, vals, xcoords, ycoords): '''Linear interpolation, giving out of bounds warning.''' - if any(vals < xcoords[0]) or any(vals > xcoords[-1]): + if N.any(vals < xcoords[0]) or N.any(vals > xcoords[-1]): self.document.log( _('Warning: values exceed bounds in axis-function')) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/widgets/axisticks.py new/veusz-1.23.2/veusz/widgets/axisticks.py --- old/veusz-1.23.1/veusz/widgets/axisticks.py 2015-04-05 14:38:55.000000000 +0200 +++ new/veusz-1.23.2/veusz/widgets/axisticks.py 2015-11-22 12:30:21.000000000 +0100 @@ -54,8 +54,11 @@ is tuple as returned in self.interval after calling getTicks() """ - self.minval = minval - self.maxval = maxval + # clip to sensible range + self.minval = max(min(minval, 1e100), -1e100) + self.maxval = max(min(maxval, 1e100), -1e100) + + # tick parameters self.numticks = numticks self.numminorticks = numminorticks self.logaxis = logaxis diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/widgets/boxplot.py new/veusz-1.23.2/veusz/widgets/boxplot.py --- old/veusz-1.23.1/veusz/widgets/boxplot.py 2015-04-22 19:41:20.000000000 +0200 +++ new/veusz-1.23.2/veusz/widgets/boxplot.py 2015-11-14 14:08:33.000000000 +0100 @@ -405,7 +405,7 @@ datasets = [ s.get(x).getData(doc) for x in ('whiskermin', 'whiskermax', 'boxmin', 'boxmax', 'mean', 'median') ] - if N.any((d is None for d in datasets)): + if any((d is None for d in datasets)): return # get axes widgets diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/veusz-1.23.1/veusz/windows/plotwindow.py new/veusz-1.23.2/veusz/windows/plotwindow.py --- old/veusz-1.23.1/veusz/windows/plotwindow.py 2015-04-22 19:41:20.000000000 +0200 +++ new/veusz-1.23.2/veusz/windows/plotwindow.py 2015-10-27 19:35:12.000000000 +0100 @@ -1,6 +1,6 @@ # plotwindow.py # the main window for showing plots - + # Copyright (C) 2004 Jeremy S. Sanders # Email: Jeremy Sanders <[email protected]> # @@ -527,7 +527,7 @@ pt1.x(), pt1.y(), widgets.Graph) if widget is None: return - + # convert points on plotter to points on axis for each axis # we also add a neighbouring pixel for the rounding calculation xpts = N.array( [pt1.x(), pt2.x(), pt1.x()+1, pt2.x()-1] ) @@ -535,7 +535,7 @@ # build up operation list to do zoom operations = [] - + axes = {} # iterate over children, to look for plotters for c in [i for i in widget.children if @@ -853,7 +853,7 @@ def locateClickWidget(self, x, y): """Work out which widget was clicked, and if necessary send a sigWidgetClicked(widget) signal.""" - + if self.document.getNumberPages() == 0: return @@ -907,7 +907,7 @@ # print >>sys.stderr, "updating" self.pickeritem.hide() - + self.pagenumber = min( self.document.getNumberPages() - 1, self.pagenumber ) self.oldpagenumber = self.pagenumber @@ -1077,10 +1077,10 @@ if aspectwin > aspectplot: # take account of scroll bar width -= self.verticalScrollBar().width() - + mult = width / r.width() self.setZoomFactor(self.zoomfactor * mult) - + def slotViewZoomHeight(self): """Make the zoom factor so that the plot fills the whole width.""" @@ -1094,7 +1094,7 @@ if aspectwin < aspectplot: # take account of scroll bar height -= self.horizontalScrollBar().height() - + mult = height / r.height() self.setZoomFactor(self.zoomfactor * mult) @@ -1115,7 +1115,7 @@ def slotViewPreviousPage(self): """View the previous page.""" self.setPageNumber( self.pagenumber - 1 ) - + def slotViewNextPage(self): """View the next page.""" self.setPageNumber( self.pagenumber + 1 ) @@ -1135,7 +1135,7 @@ modecnvt = { self.vzactions['view.select'] : 'select', self.vzactions['view.pick'] : 'pick', self.vzactions['view.zoomgraph'] : 'graphzoom' } - + # close the current picker self.pickeritem.hide() self.sigPickerEnabled.emit(False) @@ -1145,14 +1145,12 @@ if self.clickmode == 'select': self.pixmapitem.unsetCursor() - #self.label.setCursor(qt4.Qt.ArrowCursor) elif self.clickmode == 'graphzoom': - self.pixmapitem.unsetCursor() - #self.label.setCursor(qt4.Qt.CrossCursor) + self.pixmapitem.setCursor(qt4.Qt.CrossCursor) elif self.clickmode == 'pick': self.pixmapitem.setCursor(qt4.Qt.CrossCursor) self.sigPickerEnabled.emit(True) - + def getClick(self): """Return a click point from the graph.""" @@ -1173,7 +1171,7 @@ pt.x(), pt.y(), widgets.Graph) if widget is None: return [] - + # convert points on plotter to points on axis for each axis xpts = N.array( [pt.x()] ) ypts = N.array( [pt.y()] )
