Hello community, here is the log from the commit of package python-param for openSUSE:Factory checked in at 2020-01-22 22:46:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-param (Old) and /work/SRC/openSUSE:Factory/.python-param.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-param" Wed Jan 22 22:46:14 2020 rev:11 rq:766318 version:1.9.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-param/python-param.changes 2019-09-02 13:25:34.185309944 +0200 +++ /work/SRC/openSUSE:Factory/.python-param.new.26092/python-param.changes 2020-01-22 22:46:29.628582362 +0100 @@ -1,0 +2,6 @@ +Wed Jan 22 09:32:08 UTC 2020 - Martin Sirringhaus <martin.sirringh...@suse.com> + +- Update to 1.9.2: + * No upstream changelog + +------------------------------------------------------------------- Old: ---- v1.9.1.tar.gz New: ---- v1.9.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-param.spec ++++++ --- /var/tmp/diff_new_pack.YEPosk/_old 2020-01-22 22:46:30.960583034 +0100 +++ /var/tmp/diff_new_pack.YEPosk/_new 2020-01-22 22:46:30.960583034 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-param # -# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2020 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-param -Version: 1.9.1 +Version: 1.9.2 Release: 0 Summary: Declarative Python programming using Parameters License: BSD-3-Clause ++++++ v1.9.1.tar.gz -> v1.9.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/.travis.yml new/param-1.9.2/.travis.yml --- old/param-1.9.1/.travis.yml 2019-06-01 00:46:54.000000000 +0200 +++ new/param-1.9.2/.travis.yml 2019-10-08 15:18:35.000000000 +0200 @@ -131,7 +131,7 @@ - pip install -e . script: # TODO: nbsite commands will be simplified eventually... - - nbsite generate-rst --org pyviz --repo param + - nbsite generate-rst --org pyviz --repo param --project-name param - mkdir doc/Reference_Manual && nbsite_generate_modules.py param -d ./doc/Reference_Manual -n param -e tests - nbsite build --examples-assets='' deploy: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/param/__init__.py new/param-1.9.2/param/__init__.py --- old/param-1.9.1/param/__init__.py 2019-06-01 00:46:54.000000000 +0200 +++ new/param-1.9.2/param/__init__.py 2019-10-08 15:18:35.000000000 +0200 @@ -41,7 +41,7 @@ # only two required files. try: from .version import Version - __version__ = str(Version(fpath=__file__, archive_commit="4d6d346", reponame="param")) + __version__ = str(Version(fpath=__file__, archive_commit="57c1701", reponame="param")) except: __version__ = "0.0.0+unknown" @@ -54,6 +54,12 @@ except: pass + +try: + import collections.abc as collections_abc +except ImportError: + collections_abc = collections + if sys.version_info[0] >= 3: unicode = str @@ -108,9 +114,9 @@ part of the object has changed. Does not (currently) recursively replace mutable subobjects. """ - if isinstance(x, collections.MutableSequence): + if isinstance(x, collections_abc.MutableSequence): return tuple(x) - elif isinstance(x, collections.MutableMapping): + elif isinstance(x, collections_abc.MutableMapping): return tuple([(k,v) for k,v in x.items()]) else: return x @@ -1164,7 +1170,7 @@ compute_default_fn=None,check_on_set=None,allow_None=None,**params): if objects is None: objects = [] - if isinstance(objects, collections.Mapping): + if isinstance(objects, collections_abc.Mapping): self.names = objects self.objects = list(objects.values()) else: @@ -1812,7 +1818,7 @@ class Date(Number): """ - Date parameter of datetime type. + Date parameter of datetime or date type. """ def __init__(self, default=None, **kwargs): @@ -1827,10 +1833,35 @@ return if not isinstance(val, dt_types) and not (self.allow_None and val is None): - raise ValueError("Date '%s' only takes datetime types."%self.name) + raise ValueError("Date '%s' only takes datetime and date types."%self.name) if self.step is not None and not isinstance(self.step, dt_types): - raise ValueError("Step parameter can only be None or a datetime type") + raise ValueError("Step parameter can only be None, a datetime or datetime type") + + self._checkBounds(val) + + +class CalendarDate(Number): + """ + CalendarDate parameter of date type. + """ + + def __init__(self, default=None, **kwargs): + super(CalendarDate, self).__init__(default=default, **kwargs) + + def _validate(self, val): + """ + Checks that the value is numeric and that it is within the hard + bounds; if not, an exception is raised. + """ + if self.allow_None and val is None: + return + + if not isinstance(val, dt.date) and not (self.allow_None and val is None): + raise ValueError("CalendarDate '%s' only takes datetime types."%self.name) + + if self.step is not None and not isinstance(self.step, dt.date): + raise ValueError("Step parameter can only be None or a date type") self._checkBounds(val) @@ -1929,10 +1960,9 @@ class DateRange(Range): """ - A date range specified as (start_date, end_date). + A datetime or date range specified as (start, end). - Dates must be specified as datetime-like types (see - param.dt_types). + Bounds must be specified as datetime or date types (see param.dt_types). """ def _validate(self, val): if self.allow_None and val is None: @@ -1944,9 +1974,31 @@ start, end = val if not end >= start: - raise ValueError("DateRange '%s': end date %s is before start date %s."%(self.name,val[1],val[0])) + raise ValueError("DateRange '%s': end datetime %s is before start datetime %s."%(self.name,val[1],val[0])) # Calling super(DateRange, self)._check(val) would also check # values are numeric, which is redundant, so just call # _checkBounds(). self._checkBounds(val) + + +class CalendarDateRange(Range): + """ + A date range specified as (start_date, end_date). + """ + def _validate(self, val): + if self.allow_None and val is None: + return + + for n in val: + if not isinstance(n, dt.date): + raise ValueError("CalendarDateRange '%s' only takes date types: %s"%(self.name,val)) + + start, end = val + if not end >= start: + raise ValueError("CalendarDateRange '%s': end date %s is before start date %s."%(self.name,val[1],val[0])) + + # Calling super(CalendarDateRange, self)._check(val) would also check + # values are numeric, which is redundant, so just call + # _checkBounds(). + self._checkBounds(val) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/param/parameterized.py new/param-1.9.2/param/parameterized.py --- old/param-1.9.1/param/parameterized.py 2019-06-01 00:46:54.000000000 +0200 +++ new/param-1.9.2/param/parameterized.py 2019-10-08 15:18:35.000000000 +0200 @@ -88,7 +88,7 @@ @contextmanager -def batch_watch(parameterized, run=True): +def batch_watch(parameterized, enable=True, run=True): """ Context manager to batch watcher events on a parameterized object. The context manager will queue any events triggered by setting a @@ -97,7 +97,7 @@ queued events are not dispatched and should be processed manually. """ BATCH_WATCH = parameterized.param._BATCH_WATCH - parameterized.param._BATCH_WATCH = True + parameterized.param._BATCH_WATCH = enable or parameterized.param._BATCH_WATCH try: yield finally: @@ -112,7 +112,7 @@ Temporarily set parameters on Parameterized object to constant=False to allow editing them. """ - params = parameterized.objects('existing').values() + params = parameterized.param.objects('existing').values() constants = [p.constant for p in params] for p in params: p.constant = False @@ -479,7 +479,7 @@ PInfo = namedtuple("PInfo","inst cls name pobj what") MInfo = namedtuple("MInfo","inst cls name method") Event = namedtuple("Event","what name obj cls old new type") -Watcher = namedtuple("Watcher","inst cls fn mode onlychanged parameter_names what") +Watcher = namedtuple("Watcher","inst cls fn mode onlychanged parameter_names what queued") class ParameterMetaclass(type): """ @@ -1449,13 +1449,13 @@ self_._events.append(event) if watcher not in self_._watchers: self_._watchers.append(watcher) - elif watcher.mode == 'args': - with batch_watch(self_.self_or_cls, run=False): - watcher.fn(self_._update_event_type(watcher, event, self_.self_or_cls.param._TRIGGER)) else: - with batch_watch(self_.self_or_cls, run=False): - event = self_._update_event_type(watcher, event, self_.self_or_cls.param._TRIGGER) - watcher.fn(**{event.name: event.new}) + event = self_._update_event_type(watcher, event, self_.self_or_cls.param._TRIGGER) + with batch_watch(self_.self_or_cls, enable=watcher.queued, run=False): + if watcher.mode == 'args': + watcher.fn(event) + else: + watcher.fn(**{event.name: event.new}) def _batch_call_watchers(self_): @@ -1475,7 +1475,7 @@ self_.self_or_cls.param._TRIGGER) for name in watcher.parameter_names if (name, watcher.what) in event_dict] - with batch_watch(self_.self_or_cls, run=False): + with batch_watch(self_.self_or_cls, enable=watcher.queued, run=False): if watcher.mode == 'args': watcher.fn(*events) else: @@ -1718,11 +1718,11 @@ watchers[what] = [] getattr(watchers[what], action)(watcher) - def watch(self_,fn,parameter_names, what='value', onlychanged=True): + def watch(self_,fn,parameter_names, what='value', onlychanged=True, queued=False): parameter_names = tuple(parameter_names) if isinstance(parameter_names, list) else (parameter_names,) watcher = Watcher(inst=self_.self, cls=self_.cls, fn=fn, mode='args', onlychanged=onlychanged, parameter_names=parameter_names, - what=what) + what=what, queued=queued) self_._watch('append', watcher, what) return watcher @@ -1736,16 +1736,16 @@ self_.warning('No such watcher {watcher} to remove.'.format(watcher=watcher)) - def watch_values(self_,fn,parameter_names,what='value', onlychanged=True): + def watch_values(self_, fn, parameter_names, what='value', onlychanged=True, queued=False): parameter_names = tuple(parameter_names) if isinstance(parameter_names, list) else (parameter_names,) watcher = Watcher(inst=self_.self, cls=self_.cls, fn=fn, mode='kwargs', onlychanged=onlychanged, - parameter_names=parameter_names, what='value') + parameter_names=parameter_names, what='value', + queued=queued) self_._watch('append', watcher, what) return watcher - # Instance methods @@ -1903,10 +1903,11 @@ # everything else access from here rather than from method # object for n,dinfo in dependers: - if dinfo.get('watch', False): - _watch.append(n) + watch = dinfo.get('watch', False) + if watch: + _watch.append((n, watch == 'queued')) - mcs.param._depends = {'watch':_watch} + mcs.param._depends = {'watch': _watch} if docstring_signature: mcs.__class_docstring_signature() @@ -2343,14 +2344,14 @@ for cls in classlist(self.__class__): if not issubclass(cls, Parameterized): continue - for n in cls.param._depends['watch']: + for n, queued in cls.param._depends['watch']: # TODO: should improve this - will happen for every # instantiation of Parameterized with watched deps. Will # probably store expanded deps on class - see metaclass # 'dependers'. for p in self.param.params_depended_on(n): # TODO: can't remember why not just pass m (rather than _m_caller) here - (p.inst or p.cls).param.watch(_m_caller(self,n),p.name,p.what) + (p.inst or p.cls).param.watch(_m_caller(self, n), p.name, p.what, queued=queued) self.initialized=True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/tests/API0/testcalendardateparam.py new/param-1.9.2/tests/API0/testcalendardateparam.py --- old/param-1.9.1/tests/API0/testcalendardateparam.py 1970-01-01 01:00:00.000000000 +0100 +++ new/param-1.9.2/tests/API0/testcalendardateparam.py 2019-10-08 15:18:35.000000000 +0200 @@ -0,0 +1,53 @@ +""" +Unit test for CalendarDate parameters. +""" + +import unittest +import datetime as dt +import param + + +class TestDateTimeParameters(unittest.TestCase): + + def test_initialization_out_of_bounds(self): + try: + class Q(param.Parameterized): + q = param.Date(dt.date(2017,2,27), + bounds=(dt.date(2017,2,1), + dt.date(2017,2,26))) + except ValueError: + pass + else: + raise AssertionError("No exception raised on out-of-bounds date") + + def test_set_out_of_bounds(self): + class Q(param.Parameterized): + q = param.Date(bounds=(dt.date(2017,2,1), + dt.date(2017,2,26))) + try: + Q.q = dt.date(2017,2,27) + except ValueError: + pass + else: + raise AssertionError("No exception raised on out-of-bounds date") + + def test_set_exclusive_out_of_bounds(self): + class Q(param.Parameterized): + q = param.Date(bounds=(dt.date(2017,2,1), + dt.date(2017,2,26)), + inclusive_bounds=(True, False)) + try: + Q.q = dt.date(2017,2,26) + except ValueError: + pass + else: + raise AssertionError("No exception raised on out-of-bounds date") + + def test_get_soft_bounds(self): + q = param.Date(dt.date(2017,2,25), + bounds=(dt.date(2017,2,1), + dt.date(2017,2,26)), + softbounds=(dt.date(2017,2,1), + dt.date(2017,2,25))) + self.assertEqual(q.get_soft_bounds(), (dt.date(2017,2,1), + dt.date(2017,2,25))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/tests/API0/testcalendardaterangeparam.py new/param-1.9.2/tests/API0/testcalendardaterangeparam.py --- old/param-1.9.1/tests/API0/testcalendardaterangeparam.py 1970-01-01 01:00:00.000000000 +0100 +++ new/param-1.9.2/tests/API0/testcalendardaterangeparam.py 2019-10-08 15:18:35.000000000 +0200 @@ -0,0 +1,79 @@ +""" +Unit tests for CalendarDateRange parameter. +""" + +import unittest +import datetime as dt +import param + + +# Assuming tests of range parameter cover most of what's needed to +# test date range. + +class TestDateTimeRange(unittest.TestCase): + + bad_range = (dt.date(2017,2,27),dt.date(2017,2,26)) + + def test_wrong_type_default(self): + try: + class Q(param.Parameterized): + a = param.CalendarDateRange(default=(1.0,2.0)) + except ValueError: + pass + else: + raise AssertionError("Bad date type was accepted.") + + def test_wrong_type_init(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + + try: + Q(a=self.bad_range) + except ValueError: + pass + else: + raise AssertionError("Bad date type was accepted.") + + def test_wrong_type_set(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + q = Q() + + try: + q.a = self.bad_range + except ValueError: + pass + else: + raise AssertionError("Bad date type was accepted.") + + def test_start_before_end_default(self): + try: + class Q(param.Parameterized): + a = param.CalendarDateRange(default=self.bad_range) + except ValueError: + pass + else: + raise AssertionError("Bad date range was accepted.") + + def test_start_before_end_init(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + + try: + Q(a=self.bad_range) + except ValueError: + pass + else: + raise AssertionError("Bad date range was accepted.") + + def test_start_before_end_set(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + + q = Q() + try: + q.a = self.bad_range + except ValueError: + pass + else: + raise AssertionError("Bad date range was accepted.") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/tests/API1/testcalendardateparam.py new/param-1.9.2/tests/API1/testcalendardateparam.py --- old/param-1.9.1/tests/API1/testcalendardateparam.py 1970-01-01 01:00:00.000000000 +0100 +++ new/param-1.9.2/tests/API1/testcalendardateparam.py 2019-10-08 15:18:35.000000000 +0200 @@ -0,0 +1,54 @@ +""" +Unit test for CalendarDate parameters. +""" + + +import datetime as dt +import param +from . import API1TestCase + + +class TestDateTimeParameters(API1TestCase): + + def test_initialization_out_of_bounds(self): + try: + class Q(param.Parameterized): + q = param.CalendarDate(dt.date(2017,2,27), + bounds=(dt.date(2017,2,1), + dt.date(2017,2,26))) + except ValueError: + pass + else: + raise AssertionError("No exception raised on out-of-bounds date") + + def test_set_out_of_bounds(self): + class Q(param.Parameterized): + q = param.CalendarDate(bounds=(dt.date(2017,2,1), + dt.date(2017,2,26))) + try: + Q.q = dt.date(2017,2,27) + except ValueError: + pass + else: + raise AssertionError("No exception raised on out-of-bounds date") + + def test_set_exclusive_out_of_bounds(self): + class Q(param.Parameterized): + q = param.CalendarDate(bounds=(dt.date(2017,2,1), + dt.date(2017,2,26)), + inclusive_bounds=(True, False)) + try: + Q.q = dt.date(2017,2,26) + except ValueError: + pass + else: + raise AssertionError("No exception raised on out-of-bounds date") + + def test_get_soft_bounds(self): + q = param.CalendarDate(dt.date(2017,2,25), + bounds=(dt.date(2017,2,1), + dt.date(2017,2,26)), + softbounds=(dt.date(2017,2,1), + dt.date(2017,2,25))) + self.assertEqual(q.get_soft_bounds(), (dt.date(2017,2,1), + dt.date(2017,2,25))) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/tests/API1/testcalendardaterangeparam.py new/param-1.9.2/tests/API1/testcalendardaterangeparam.py --- old/param-1.9.1/tests/API1/testcalendardaterangeparam.py 1970-01-01 01:00:00.000000000 +0100 +++ new/param-1.9.2/tests/API1/testcalendardaterangeparam.py 2019-10-08 15:18:35.000000000 +0200 @@ -0,0 +1,78 @@ +""" +Unit tests for CalendarDateRange parameter. +""" + +import datetime as dt +import param +from . import API1TestCase + +# Assuming tests of range parameter cover most of what's needed to +# test date range. + +class TestDateTimeRange(API1TestCase): + + bad_range = (dt.date(2017,2,27),dt.date(2017,2,26)) + + def test_wrong_type_default(self): + try: + class Q(param.Parameterized): + a = param.CalendarDateRange(default=(1.0,2.0)) + except ValueError: + pass + else: + raise AssertionError("Bad date type was accepted.") + + def test_wrong_type_init(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + + try: + Q(a=self.bad_range) + except ValueError: + pass + else: + raise AssertionError("Bad date type was accepted.") + + def test_wrong_type_set(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + q = Q() + + try: + q.a = self.bad_range + except ValueError: + pass + else: + raise AssertionError("Bad date type was accepted.") + + def test_start_before_end_default(self): + try: + class Q(param.Parameterized): + a = param.CalendarDateRange(default=self.bad_range) + except ValueError: + pass + else: + raise AssertionError("Bad date range was accepted.") + + def test_start_before_end_init(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + + try: + Q(a=self.bad_range) + except ValueError: + pass + else: + raise AssertionError("Bad date range was accepted.") + + def test_start_before_end_set(self): + class Q(param.Parameterized): + a = param.CalendarDateRange() + + q = Q() + try: + q.a = self.bad_range + except ValueError: + pass + else: + raise AssertionError("Bad date range was accepted.") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/tests/API1/testnumberparameter.py new/param-1.9.2/tests/API1/testnumberparameter.py --- old/param-1.9.1/tests/API1/testnumberparameter.py 2019-06-01 00:46:54.000000000 +0200 +++ new/param-1.9.2/tests/API1/testnumberparameter.py 2019-10-08 15:18:35.000000000 +0200 @@ -43,7 +43,12 @@ with self.assertRaisesRegexp(ValueError, exception): param.Integer(step=3.4) - def test_step_invalid_type_date_parameter(self): - exception = "Step parameter can only be None or a datetime type" + def test_step_invalid_type_datetime_parameter(self): + exception = "Step parameter can only be None, a datetime or datetime type" with self.assertRaisesRegexp(ValueError, exception): param.Date(dt.datetime(2017,2,27), step=3.2) + + def test_step_invalid_type_date_parameter(self): + exception = "Step parameter can only be None or a date type" + with self.assertRaisesRegexp(ValueError, exception): + param.CalendarDate(dt.date(2017,2,27), step=3.2) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.9.1/tests/API1/testwatch.py new/param-1.9.2/tests/API1/testwatch.py --- old/param-1.9.1/tests/API1/testwatch.py 2019-06-01 00:46:54.000000000 +0200 +++ new/param-1.9.2/tests/API1/testwatch.py 2019-10-08 15:18:35.000000000 +0200 @@ -44,12 +44,17 @@ class WatchMethodExample(SimpleWatchSubclass): - @param.depends('a', watch=True) + @param.depends('a', watch='queued') def _clip_a(self): if self.a > 3: self.a = 3 @param.depends('b', watch=True) + def _clip_b(self): + if self.b > 10: + self.b = 10 + + @param.depends('b', watch=True) def _set_c(self): self.c = self.b*2 @@ -451,18 +456,30 @@ obj.b = 3 self.assertEqual(obj.c, 6) - def test_multiple_watcher_dispatch(self): + def test_multiple_watcher_dispatch_queued(self): obj = WatchMethodExample() obj2 = SimpleWatchExample() def link(event): obj2.a = event.new - obj.param.watch(link, 'a') + obj.param.watch(link, 'a', queued=True) obj.a = 4 self.assertEqual(obj.a, 3) self.assertEqual(obj2.a, 3) + def test_multiple_watcher_dispatch(self): + obj = WatchMethodExample() + obj2 = SimpleWatchExample() + + def link(event): + obj2.b = event.new + + obj.param.watch(link, 'b') + obj.b = 11 + self.assertEqual(obj.b, 10) + self.assertEqual(obj2.b, 11) + def test_multiple_watcher_dispatch_on_param_attribute(self): obj = WatchMethodExample() accumulator = Accumulator()