Hello community, here is the log from the commit of package python-param for openSUSE:Factory checked in at 2019-03-14 14:59:49 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-param (Old) and /work/SRC/openSUSE:Factory/.python-param.new.28833 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-param" Thu Mar 14 14:59:49 2019 rev:7 rq:684696 version:1.8.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-param/python-param.changes 2019-01-08 12:30:33.800135778 +0100 +++ /work/SRC/openSUSE:Factory/.python-param.new.28833/python-param.changes 2019-03-14 15:01:01.823699307 +0100 @@ -1,0 +2,6 @@ +Wed Mar 13 13:43:12 UTC 2019 - Tomáš Chvátal <tchva...@suse.com> + +- Update to 1.8.2: + * Added output decorator and outputs lookup method (#299, #312) + +------------------------------------------------------------------- Old: ---- v1.8.1.tar.gz New: ---- v1.8.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-param.spec ++++++ --- /var/tmp/diff_new_pack.4Owr4S/_old 2019-03-14 15:01:04.031698872 +0100 +++ /var/tmp/diff_new_pack.4Owr4S/_new 2019-03-14 15:01:04.031698872 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-param # -# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -12,13 +12,13 @@ # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. -# Please submit bugfixes or comments via http://bugs.opensuse.org/ +# Please submit bugfixes or comments via https://bugs.opensuse.org/ # %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-param -Version: 1.8.1 +Version: 1.8.2 Release: 0 Summary: Declarative Python programming using Parameters License: BSD-3-Clause ++++++ v1.8.1.tar.gz -> v1.8.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/README.rst new/param-1.8.2/README.rst --- old/param-1.8.1/README.rst 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/README.rst 2019-01-28 03:52:15.000000000 +0100 @@ -13,17 +13,17 @@ commercial use under a BSD license, so that it can easily be included as part of other projects. -Please see `param's website <http://ioam.github.com/param/>`_ for +Please see `param's website <http://param.pyviz.org>`_ for official releases, installation instructions, documentation, and examples. -.. |LinuxTests| image:: https://travis-ci.org/ioam/param.svg?branch=master -.. _LinuxTests: https://travis-ci.org/ioam/param +.. |LinuxTests| image:: https://travis-ci.org/pyviz/param.svg?branch=master +.. _LinuxTests: https://travis-ci.org/pyviz/param -.. |WinTests| image:: https://ci.appveyor.com/api/projects/status/huoiwwamso2or7xw/branch/master?svg=true -.. _WinTests: https://ci.appveyor.com/project/Ioam/param/branch/master +.. |WinTests| image:: https://ci.appveyor.com/api/projects/status/1p5aom8o0tfgok1r?svg=true +.. _WinTests: https://ci.appveyor.com/project/pyviz/param/branch/master -.. |Coverage| image:: https://img.shields.io/coveralls/ioam/param.svg -.. _Coverage: https://coveralls.io/r/ioam/param?branch=master +.. |Coverage| image:: https://img.shields.io/coveralls/pyviz/param.svg +.. _Coverage: https://coveralls.io/r/pyviz/param?branch=master .. |PyPIVersion| image:: http://img.shields.io/pypi/v/param.svg .. _PyPIVersion: https://pypi.python.org/pypi/param diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/numbergen/__init__.py new/param-1.8.2/numbergen/__init__.py --- old/param-1.8.1/numbergen/__init__.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/numbergen/__init__.py 2019-01-28 03:52:15.000000000 +0100 @@ -655,8 +655,8 @@ def __call__(self): Vi = self.starting_value Vm = self.ending_value - return Vm + (Vi - Vm) * self.base**(-1.0*float(self.time_fn())/ - float(self.time_constant)) + exp = -1.0*float(self.time_fn())/float(self.time_constant) + return Vm + (Vi - Vm) * self.base**exp diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/param/__init__.py new/param-1.8.2/param/__init__.py --- old/param-1.8.1/param/__init__.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/param/__init__.py 2019-01-28 03:52:15.000000000 +0100 @@ -27,7 +27,7 @@ from .parameterized import Parameterized, Parameter, String, \ descendents, ParameterizedFunction, ParamOverrides -from .parameterized import depends # noqa: api import +from .parameterized import depends, output # noqa: api import from .parameterized import logging_level # noqa: api import from .parameterized import shared_parameters # noqa: api import @@ -39,7 +39,7 @@ # only two required files. try: from .version import Version - __version__ = str(Version(fpath=__file__, archive_commit="d175211", reponame="param")) + __version__ = str(Version(fpath=__file__, archive_commit="29839ba", reponame="param")) except: __version__ = "0.0.0+unknown" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/param/parameterized.py new/param-1.8.2/param/parameterized.py --- old/param-1.8.1/param/parameterized.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/param/parameterized.py 2019-01-28 03:52:15.000000000 +0100 @@ -211,14 +211,23 @@ @accept_arguments def depends(func, *dependencies, **kw): + """ + Annotates a Parameterized method to express its dependencies. + The specified dependencies can be either be Parameters of this + class, or Parameters of subobjects (Parameterized objects that + are values of this object's parameters). Dependencies can either + be on Parameter values, or on other metadata about the Parameter. + """ + # python3 would allow kw-only args # (i.e. "func,*dependencies,watch=False" rather than **kw and the check below) watch = kw.pop("watch",False) assert len(kw)==0, "@depends accepts only 'watch' kw" # TODO: rename dinfo - _dinfo = {'dependencies': dependencies, - 'watch': watch} + _dinfo = getattr(func, '_dinfo', {}) + _dinfo.update({'dependencies': dependencies, + 'watch': watch}) @wraps(func) def _depends(*args,**kw): @@ -231,6 +240,101 @@ return _depends +@accept_arguments +def output(func, *output, **kw): + """ + output allows annotating a method on a Parameterized class to + declare that it returns an output of a specific type. The outputs + of a Parameterized class can be queried using the + Parameterized.param.outputs method. By default the output will + inherit the method name but a custom name can be declared by + expressing the Parameter type using a keyword argument. Declaring + multiple return types using keywords is only supported in Python >= 3.6. + + The simplest declaration simply declares the method returns an + object without any type guarantees, e.g.: + + @output() + + If a specific parameter type is specified this is a declaration + that the method will return a value of that type, e.g.: + + @output(param.Number()) + + To override the default name of the output the type may be declared + as a keyword argument, e.g.: + + @output(custom_name=param.Number()) + + Multiple outputs may be declared using keywords mapping from + output name to the type for Python >= 3.6 or using tuples of the + same format, which is supported for earlier versions, i.e. these + two declarations are equivalent: + + @output(number=param.Number(), string=param.String()) + + @output(('number', param.Number()), ('string', param.String())) + + output also accepts Python object types which will be upgraded to + a ClassSelector, e.g.: + + @output(int) + """ + if output: + outputs = [] + for i, out in enumerate(output): + i = i if len(output) > 1 else None + if isinstance(out, tuple) and len(out) == 2 and isinstance(out[0], str): + outputs.append(out+(i,)) + elif isinstance(out, str): + outputs.append((out, Parameter(), i)) + else: + outputs.append((None, out, i)) + elif kw: + py_major = sys.version_info.major + py_minor = sys.version_info.minor + if (py_major < 3 or (py_major == 3 and py_minor < 6)) and len(kw) > 1: + raise ValueError('Multiple output declaration using keywords ' + 'only supported in Python >= 3.6.') + # (requires keywords to be kept ordered, which was not true in previous versions) + outputs = [(name, otype, i if len(kw) > 1 else None) + for i, (name, otype) in enumerate(kw.items())] + else: + outputs = [(None, Parameter(), None)] + + names, processed = [], [] + for name, otype, i in outputs: + if isinstance(otype, type): + if issubclass(otype, Parameter): + otype = otype() + else: + from .import ClassSelector + otype = ClassSelector(class_=otype) + elif isinstance(otype, tuple) and all(isinstance(t, type) for t in otype): + from .import ClassSelector + otype = ClassSelector(class_=otype) + if not isinstance(otype, Parameter): + raise ValueError('output type must be declared with a Parameter class, ' + 'instance or a Python object type.') + processed.append((name, otype, i)) + names.append(name) + + if len(set(names)) != len(names): + raise ValueError('When declaring multiple outputs each value ' + 'must be unique.') + + _dinfo = getattr(func, '_dinfo', {}) + _dinfo.update({'outputs': processed}) + + @wraps(func) + def _output(*args,**kw): + return func(*args,**kw) + + _output._dinfo = _dinfo + + return _output + + def _params_depended_on(minfo): params = [] dinfo = getattr(minfo.method,"_dinfo", {}) @@ -736,9 +840,9 @@ @classmethod def is_equal(cls, obj1, obj2): for eq_type, eq in cls.equalities.items(): - if ((isinstance(eq_type, FunctionType) and - eq_type(obj1) and eq_type(obj2)) or - (isinstance(obj1, eq_type) and isinstance(obj2, eq_type))): + if ((isinstance(eq_type, FunctionType) + and eq_type(obj1) and eq_type(obj2)) + or (isinstance(obj1, eq_type) and isinstance(obj2, eq_type))): return eq(obj1, obj2) if isinstance(obj2, (list, set, tuple)): return cls.compare_iterator(obj1, obj2) @@ -1240,6 +1344,24 @@ return _params_depended_on(MInfo(cls=self_.cls,inst=self_.self,name=name,method=getattr(self_.self_or_cls,name))) + def outputs(self_): + """ + Returns a mapping between any declared outputs and a tuple + of the declared Parameter type, the output method, and the + index into the output if multiple outputs are returned. + """ + outputs = {} + for name in dir(self_.self_or_cls): + method = getattr(self_.self_or_cls, name) + dinfo = getattr(method, '_dinfo', {}) + if 'outputs' not in dinfo: + continue + for override, otype, idx in dinfo['outputs']: + if override is not None: + name = override + outputs[name] = (otype, method, idx) + return outputs + def _spec_to_obj(self_,spec): # TODO: when we decide on spec, this method should be # rewritten @@ -1249,7 +1371,7 @@ m = re.match("(?P<path>[^:]*):?(?P<what>.*)", spec) what = m.group('what') path = "."+m.group('path') - m = re.match("(?P<obj>.*)(\.)(?P<attr>.*)",path) + m = re.match(r"(?P<obj>.*)(\.)(?P<attr>.*)",path) obj = m.group('obj') attr = m.group("attr") @@ -1474,7 +1596,7 @@ # everything else access from here rather than from method # object for n,dinfo in dependers: - if dinfo['watch']: + if dinfo.get('watch', False): _watch.append(n) mcs.param._depends = {'watch':_watch} @@ -2025,8 +2147,8 @@ if k in processed: continue # Suppresses automatically generated names. - if k == 'name' and (values[k] is not None and - re.match('^'+self.__class__.__name__+'[0-9]+$', values[k])): + if k == 'name' and (values[k] is not None + and re.match('^'+self.__class__.__name__+'[0-9]+$', values[k])): continue value = pprint(values[k], imports, prefix=prefix,settings=[], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/param/version.py new/param-1.8.2/param/version.py --- old/param-1.8.1/param/version.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/param/version.py 2019-01-28 03:52:15.000000000 +0100 @@ -522,7 +522,7 @@ archive_commit_key = autover_section+'.configparser_workaround.archive_commit' for section in config.sections(): if section.startswith(archive_commit_key): - archive_commit = re.match(".*=\s*(\S*)\s*",section).group(1) + archive_commit = re.match(r".*=\s*(\S*)\s*",section).group(1) ### return get_setup_version(cfg,reponame=reponame,pkgname=pkgname,archive_commit=archive_commit) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API0/testclassselector.py new/param-1.8.2/tests/API0/testclassselector.py --- old/param-1.8.1/tests/API0/testclassselector.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/API0/testclassselector.py 2019-01-28 03:52:15.000000000 +0100 @@ -27,7 +27,7 @@ def test_single_class_instance_error(self): exception = "Parameter 'e' value must be an instance of int, not 'a'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(e='a') + self.P(e='a') def test_single_class_type_constructor(self): p = self.P(f=float) @@ -36,7 +36,7 @@ def test_single_class_type_error(self): exception = "Parameter 'str' must be a subclass of Number, not 'type'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(f=str) + self.P(f=str) def test_multiple_class_instance_constructor1(self): p = self.P(g=1) @@ -49,7 +49,7 @@ def test_multiple_class_instance_error(self): exception = "Parameter 'g' value must be an instance of \(int, str\), not '3.0'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(g=3.0) + self.P(g=3.0) def test_multiple_class_type_constructor1(self): p = self.P(h=int) @@ -62,4 +62,4 @@ def test_multiple_class_type_error(self): exception = "Parameter 'float' must be a subclass of \(int, str\), not 'type'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(h=float) + self.P(h=float) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API0/testdefaults.py new/param-1.8.2/tests/API0/testdefaults.py --- old/param-1.8.1/tests/API0/testdefaults.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/API0/testdefaults.py 2019-01-28 03:52:15.000000000 +0100 @@ -8,7 +8,8 @@ from param import concrete_descendents, Parameter # import all parameter types -from param import * +from param import ClassSelector +from param import * # noqa positional_args = { @@ -18,12 +19,12 @@ skip = [] try: - import numpy + import numpy # noqa except ImportError: skip.append('Array') try: - import pandas + import pandas # noqa except ImportError: skip.append('DataFrame') skip.append('Series') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API0/testipythonmagic.py new/param-1.8.2/tests/API0/testipythonmagic.py --- old/param-1.8.1/tests/API0/testipythonmagic.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/API0/testipythonmagic.py 2019-01-28 03:52:15.000000000 +0100 @@ -9,7 +9,7 @@ try: - import IPython + import IPython # noqa except ImportError: import os if os.getenv('PARAM_TEST_IPYTHON','0') == '1': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API1/testclassselector.py new/param-1.8.2/tests/API1/testclassselector.py --- old/param-1.8.1/tests/API1/testclassselector.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/API1/testclassselector.py 2019-01-28 03:52:15.000000000 +0100 @@ -28,7 +28,7 @@ def test_single_class_instance_error(self): exception = "Parameter 'e' value must be an instance of int, not 'a'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(e='a') + self.P(e='a') def test_single_class_type_constructor(self): p = self.P(f=float) @@ -37,7 +37,7 @@ def test_single_class_type_error(self): exception = "Parameter 'str' must be a subclass of Number, not 'type'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(f=str) + self.P(f=str) def test_multiple_class_instance_constructor1(self): p = self.P(g=1) @@ -50,7 +50,7 @@ def test_multiple_class_instance_error(self): exception = "Parameter 'g' value must be an instance of \(int, str\), not '3.0'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(g=3.0) + self.P(g=3.0) def test_multiple_class_type_constructor1(self): p = self.P(h=int) @@ -63,7 +63,7 @@ def test_multiple_class_type_error(self): exception = "Parameter 'float' must be a subclass of \(int, str\), not 'type'" with self.assertRaisesRegexp(ValueError, exception): - p = self.P(h=float) + self.P(h=float) class TestDictParameters(API1TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API1/testdefaults.py new/param-1.8.2/tests/API1/testdefaults.py --- old/param-1.8.1/tests/API1/testdefaults.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/API1/testdefaults.py 2019-01-28 03:52:15.000000000 +0100 @@ -6,7 +6,8 @@ from param import concrete_descendents, Parameter # import all parameter types -from param import * +from param import * # noqa +from param import ClassSelector from . import API1TestCase positional_args = { @@ -16,11 +17,11 @@ skip = [] try: - import numpy + import numpy # noqa except ImportError: skip.append('Array') try: - import pandas + import pandas # noqa except ImportError: skip.append('DataFrame') skip.append('Series') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API1/testipythonmagic.py new/param-1.8.2/tests/API1/testipythonmagic.py --- old/param-1.8.1/tests/API1/testipythonmagic.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/API1/testipythonmagic.py 2019-01-28 03:52:15.000000000 +0100 @@ -8,7 +8,7 @@ from . import API1TestCase try: - import IPython + import IPython # noqa except ImportError: import os if os.getenv('PARAM_TEST_IPYTHON','0') == '1': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API1/testparamoutput.py new/param-1.8.2/tests/API1/testparamoutput.py --- old/param-1.8.1/tests/API1/testparamoutput.py 1970-01-01 01:00:00.000000000 +0100 +++ new/param-1.8.2/tests/API1/testparamoutput.py 2019-01-28 03:52:15.000000000 +0100 @@ -0,0 +1,201 @@ +""" +Unit test for param.output. +""" +import sys + +from unittest import SkipTest + +import param + +from . import API1TestCase + + +class TestParamDepends(API1TestCase): + + def test_simple_output(self): + class P(param.Parameterized): + + @param.output() + def single_output(self): + return 1 + + p = P() + outputs = p.param.outputs() + self.assertEqual(list(outputs), ['single_output']) + + otype, method, idx = outputs['single_output'] + self.assertIs(type(otype), param.Parameter) + self.assertEqual(method, p.single_output) + self.assertEqual(idx, None) + + def test_named_kwarg_output(self): + class P(param.Parameterized): + + @param.output(value=param.Integer) + def single_output(self): + return 1 + + p = P() + outputs = p.param.outputs() + self.assertEqual(list(outputs), ['value']) + + otype, method, idx = outputs['value'] + self.assertIs(type(otype), param.Integer) + self.assertEqual(method, p.single_output) + self.assertEqual(idx, None) + + def test_named_and_typed_arg_output(self): + class P(param.Parameterized): + + @param.output(('value', param.Integer)) + def single_output(self): + return 1 + + p = P() + outputs = p.param.outputs() + self.assertEqual(list(outputs), ['value']) + + otype, method, idx = outputs['value'] + self.assertIs(type(otype), param.Integer) + self.assertEqual(method, p.single_output) + self.assertEqual(idx, None) + + def test_named_arg_output(self): + class P(param.Parameterized): + + @param.output('value') + def single_output(self): + return 1 + + p = P() + outputs = p.param.outputs() + self.assertEqual(list(outputs), ['value']) + + otype, method, idx = outputs['value'] + self.assertIs(type(otype), param.Parameter) + self.assertEqual(method, p.single_output) + self.assertEqual(idx, None) + + def test_typed_arg_output(self): + class P(param.Parameterized): + + @param.output(int) + def single_output(self): + return 1 + + p = P() + outputs = p.param.outputs() + self.assertEqual(list(outputs), ['single_output']) + + otype, method, idx = outputs['single_output'] + self.assertIs(type(otype), param.ClassSelector) + self.assertIs(otype.class_, int) + self.assertEqual(method, p.single_output) + self.assertEqual(idx, None) + + def test_multiple_named_kwarg_output(self): + py_major = sys.version_info.major + py_minor = sys.version_info.minor + if (py_major < 3 or (py_major == 3 and py_minor < 6)): + raise SkipTest('Multiple keyword output declarations only ' + 'supported in Python >= 3.6, skipping test.') + + class P(param.Parameterized): + + @param.output(value=param.Integer, value2=param.String) + def multi_output(self): + return (1, 'string') + + p = P() + outputs = p.param.outputs() + self.assertEqual(set(outputs), {'value', 'value2'}) + + otype, method, idx = outputs['value'] + self.assertIs(type(otype), param.Integer) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 0) + + otype, method, idx = outputs['value2'] + self.assertIs(type(otype), param.String) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 1) + + def test_multi_named_and_typed_arg_output(self): + class P(param.Parameterized): + + @param.output(('value', param.Integer), ('value2', param.String)) + def multi_output(self): + return (1, 'string') + + p = P() + outputs = p.param.outputs() + self.assertEqual(set(outputs), {'value', 'value2'}) + otype, method, idx = outputs['value'] + self.assertIs(type(otype), param.Integer) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 0) + + otype, method, idx = outputs['value2'] + self.assertIs(type(otype), param.String) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 1) + + def test_multi_named_arg_output(self): + class P(param.Parameterized): + + @param.output('value', 'value2') + def multi_output(self): + return (1, 2) + + p = P() + outputs = p.param.outputs() + self.assertEqual(set(outputs), {'value', 'value2'}) + + otype, method, idx = outputs['value'] + self.assertIs(type(otype), param.Parameter) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 0) + + otype, method, idx = outputs['value2'] + self.assertIs(type(otype), param.Parameter) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 1) + + def test_multi_typed_arg_output(self): + with self.assertRaises(ValueError): + class P(param.Parameterized): + + @param.output(int, str) + def single_output(self): + return 1 + + def test_multi_method_named_and_typed_arg_output(self): + class P(param.Parameterized): + + @param.output(('value', param.Integer), ('value2', str)) + def multi_output(self): + return (1, 'string') + + @param.output(('value3', param.Number)) + def single_output(self): + return 3.0 + + p = P() + outputs = p.param.outputs() + self.assertEqual(set(outputs), {'value', 'value2', 'value3'}) + + otype, method, idx = outputs['value'] + self.assertIs(type(otype), param.Integer) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 0) + + otype, method, idx = outputs['value2'] + self.assertIs(type(otype), param.ClassSelector) + self.assertIs(otype.class_, str) + self.assertEqual(method, p.multi_output) + self.assertEqual(idx, 1) + + otype, method, idx = outputs['value3'] + self.assertIs(type(otype), param.Number) + self.assertEqual(method, p.single_output) + self.assertEqual(idx, None) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/API1/testwatch.py new/param-1.8.2/tests/API1/testwatch.py --- old/param-1.8.1/tests/API1/testwatch.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/API1/testwatch.py 2019-01-28 03:52:15.000000000 +0100 @@ -168,7 +168,7 @@ accumulator = Accumulator() obj = SimpleWatchExample() - watcher = obj.param.watch(accumulator, ['a','b']) + obj.param.watch(accumulator, ['a','b']) obj.a = 2 self.assertEqual(accumulator.call_count(), 1) @@ -196,12 +196,12 @@ obj = SimpleWatchExample() accumulator = Accumulator() - watcher = obj.param.watch(accumulator, ['a', 'c']) + obj.param.watch(accumulator, ['a', 'c']) def set_c(*events): obj.c = 3 - watcher2 = obj.param.watch(set_c, ['a', 'b']) + obj.param.watch(set_c, ['a', 'b']) obj.param.set_param(a=2) self.assertEqual(obj.c, 3) @@ -216,7 +216,7 @@ accumulator = Accumulator() obj = SimpleWatchExample() - watcher = obj.param.watch(accumulator, ['a','b']) + obj.param.watch(accumulator, ['a','b']) obj.param.set_param(a=23, b=42) self.assertEqual(accumulator.call_count(), 1) @@ -265,8 +265,8 @@ accumulator = Accumulator() obj = SimpleWatchExample() - watcher1 = obj.param.watch(accumulator, ['a','b']) - watcher2 = obj.param.watch(accumulator, ['c']) + obj.param.watch(accumulator, ['a','b']) + obj.param.watch(accumulator, ['c']) obj.param.set_param(a=23, b=42, c=99) @@ -429,7 +429,7 @@ accumulator = Accumulator() obj = SimpleWatchExample() - watcher = obj.param.watch_values(accumulator, ['a','b']) + obj.param.watch_values(accumulator, ['a','b']) obj.a = 2 self.assertEqual(accumulator.call_count(), 1) @@ -449,7 +449,7 @@ accumulator = Accumulator() obj = SimpleWatchExample() - watcher = obj.param.watch_values(accumulator, ['a','b']) + obj.param.watch_values(accumulator, ['a','b']) obj.param.set_param(a=23, b=42) self.assertEqual(accumulator.call_count(), 1) @@ -462,8 +462,8 @@ accumulator = Accumulator() obj = SimpleWatchExample() - watcher1 = obj.param.watch_values(accumulator, ['a','b']) - watcher2 = obj.param.watch_values(accumulator, ['c']) + obj.param.watch_values(accumulator, ['a','b']) + obj.param.watch_values(accumulator, ['c']) obj.param.set_param(a=23, b=42, c=99) @@ -488,7 +488,7 @@ def test_simple_trigger_one_param(self): accumulator = Accumulator() obj = SimpleWatchExample() - watcher = obj.param.watch(accumulator, ['a']) + obj.param.watch(accumulator, ['a']) obj.param.trigger('a') self.assertEqual(accumulator.call_count(), 1) @@ -501,7 +501,7 @@ def test_simple_trigger_one_param_change(self): accumulator = Accumulator() obj = SimpleWatchExample() - watcher = obj.param.watch(accumulator, ['a']) + obj.param.watch(accumulator, ['a']) obj.a = 42 self.assertEqual(accumulator.call_count(), 1) @@ -523,7 +523,7 @@ def test_simple_trigger_two_params(self): accumulator = Accumulator() obj = SimpleWatchExample() - watcher = obj.param.watch(accumulator, ['a','b']) + obj.param.watch(accumulator, ['a','b']) obj.param.trigger('a','b') self.assertEqual(accumulator.call_count(), 1) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tests/__init__.py new/param-1.8.2/tests/__init__.py --- old/param-1.8.1/tests/__init__.py 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tests/__init__.py 2019-01-28 03:52:15.000000000 +0100 @@ -1,5 +1,5 @@ import sys -import unittest +import unittest # noqa if sys.version_info[0]==2 and sys.version_info[1]<7: del sys.modules['unittest'] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.8.1/tox.ini new/param-1.8.2/tox.ini --- old/param-1.8.1/tox.ini 2018-10-12 17:27:31.000000000 +0200 +++ new/param-1.8.2/tox.ini 2019-01-28 03:52:15.000000000 +0100 @@ -40,3 +40,8 @@ [testenv:flakes] skip_install = true commands = flake8 + +[flake8] +ignore = E,W,W605 +include = *.py +exclude = .git,__pycache__,.tox,.eggs,*.egg,doc,dist,build,_build,.ipynb_checkpoints,run_test.py