Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-param for openSUSE:Factory checked in at 2022-05-02 16:25:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-param (Old) and /work/SRC/openSUSE:Factory/.python-param.new.1538 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-param" Mon May 2 16:25:31 2022 rev:20 rq:974289 version:1.12.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-param/python-param.changes 2022-02-17 00:31:56.785418658 +0100 +++ /work/SRC/openSUSE:Factory/.python-param.new.1538/python-param.changes 2022-05-02 16:25:37.400841795 +0200 @@ -1,0 +2,21 @@ +Sun May 1 18:58:42 UTC 2022 - Atri Bhattacharya <[email protected]> + +- Update to version 1.12.1: + * Fixed description of shared_parameters (gh#holoviz/param#568). + * Improve the error messages of Date and DateRange + (gh#holoviz/param#579). + * Clarified step error messages and other docs and links + (gh#holoviz/param#604). + * Make iscoroutinefunction more robust (gh#holoviz/param#572). + * Fix for handling misspelled parameter (gh#holoviz/param#575). + * Handle None serialization for Date, CalendarDate, Tuple, + Array, and DataFrame (gh#holoviz/param#582). + * Support async coroutines in param.depends + (gh#holoviz/param#591). + * Handle async functions in depends with watch=True + (gh#holoviz/param#611). + * Avoid equality check on Watcher (gh#holoviz/param#612). + * Fix binder (gh#holoviz/param#564). + * Fixed description of shared_parameters (gh#holoviz/param#568). + +------------------------------------------------------------------- Old: ---- param-1.12.0.tar.gz New: ---- param-1.12.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-param.spec ++++++ --- /var/tmp/diff_new_pack.myxgNW/_old 2022-05-02 16:25:37.912842364 +0200 +++ /var/tmp/diff_new_pack.myxgNW/_new 2022-05-02 16:25:37.916842369 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define modname param Name: python-param -Version: 1.12.0 +Version: 1.12.1 Release: 0 Summary: Declarative Python programming using Parameters License: BSD-3-Clause ++++++ param-1.12.0.tar.gz -> param-1.12.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/.github/workflows/docs.yml new/param-1.12.1/.github/workflows/docs.yml --- old/param-1.12.0/.github/workflows/docs.yml 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/.github/workflows/docs.yml 2022-03-31 17:29:20.000000000 +0200 @@ -34,7 +34,7 @@ id: vars run: echo ::set-output name=tag::${GITHUB_REF#refs/*/} - name: graphviz - run: sudo apt install libgraphviz-dev + run: sudo apt install graphviz graphviz-dev - name: env setup run: | python -m pip install pip==21.0.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/.github/workflows/test.yml new/param-1.12.1/.github/workflows/test.yml --- old/param-1.12.0/.github/workflows/test.yml 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/.github/workflows/test.yml 2022-03-31 17:29:20.000000000 +0200 @@ -1,7 +1,3 @@ -# things not included -# language -# notifications - no email notifications set up - name: pytest on: push: @@ -19,15 +15,13 @@ fail-fast: false matrix: os: ['ubuntu-latest', 'windows-latest', 'macos-latest'] - python-version: [2.7, 3.6, 3.7, 3.8, 3.9, '3.10', pypy3] + python-version: [2.7, 3.6, 3.7, 3.8, 3.9, '3.10', "pypy-3.7"] timeout-minutes: 30 defaults: run: shell: bash -l {0} env: PYTHON_VERSION: ${{ matrix.python-version }} - CHANS_DEV: "-c pyviz/label/dev" - CHANS: "-c pyviz" GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - uses: actions/checkout@v2 @@ -46,27 +40,16 @@ python3 -m pip install --upgrade pip python3 -m pip install tox flake8 - name: lint - run: | - flake8 - - name: unit python - if: (!startsWith(matrix.python-version, 'py')) - run: | - pyver="${{ matrix.python-version }}" - tox_env="py${pyver//.}" - tox -e $tox_env - - name: unit pypy - if: startsWith(matrix.python-version, 'py') - run: | - pyver="${{ matrix.python-version }}" - tox_env="${pyver//.}" - tox -e $tox_env + run: flake8 + - name: unit + run: tox -e py - name: unit with_ipython run: tox -e with_ipython - name: unit with_numpy if: (!startsWith(matrix.python-version, 'py')) run: tox -e with_numpy - name: unit with_pandas - if: (!startsWith(matrix.python-version, 'py') && !(contains(matrix.os, 'windows') && matrix.python-version == '3.10')) + if: (!startsWith(matrix.python-version, 'py')) run: tox -e with_pandas - name: unit with_jsonschema run: tox -e with_jsonschema diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/.gitignore new/param-1.12.1/.gitignore --- old/param-1.12.0/.gitignore 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/.gitignore 2022-03-31 17:29:20.000000000 +0200 @@ -23,3 +23,6 @@ # Unit test / Coverage report .coverage coverage.xml + +# autover +param/.version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/LICENSE.txt new/param-1.12.1/LICENSE.txt --- old/param-1.12.0/LICENSE.txt 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/LICENSE.txt 2022-03-31 17:29:20.000000000 +0200 @@ -1,4 +1,4 @@ -Copyright (c) 2005-2020, HoloViz team. +Copyright (c) 2005-2022, HoloViz team. All rights reserved. Redistribution and use in source and binary forms, with or without diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/binder/environment.yaml new/param-1.12.1/binder/environment.yaml --- old/param-1.12.0/binder/environment.yaml 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/binder/environment.yaml 1970-01-01 01:00:00.000000000 +0100 @@ -1,7 +0,0 @@ -name: param -channels: - - defaults -dependencies: - - python=3.9.7 - - aiohttp=3.7.4 - - panel=0.12.2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/binder/environment.yml new/param-1.12.1/binder/environment.yml --- old/param-1.12.0/binder/environment.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/param-1.12.1/binder/environment.yml 2022-03-31 17:29:20.000000000 +0200 @@ -0,0 +1,9 @@ +name: param +channels: + - pyviz + - defaults +dependencies: + - python=3.9.7 + - aiohttp=3.7.4 + - panel=0.12.4 + - pip diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/binder/postBuild new/param-1.12.1/binder/postBuild --- old/param-1.12.0/binder/postBuild 1970-01-01 01:00:00.000000000 +0100 +++ new/param-1.12.1/binder/postBuild 2022-03-31 17:29:20.000000000 +0200 @@ -0,0 +1,2 @@ +pip uninstall param --yes +pip install . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/doc/comparisons.md new/param-1.12.1/doc/comparisons.md --- old/param-1.12.0/doc/comparisons.md 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/doc/comparisons.md 2022-03-31 17:29:20.000000000 +0200 @@ -31,7 +31,7 @@ ## Runtime checking -Python 3 type annotations allow users to specify types for attributes and function returns, but these types are not normally checked at runtime, and so they do not have the same role of validating user input or programmer error as the type declarations in Params, Traits, Traitlets, pydantic, and attr. They also are limited to the type, so they cannot enforce constraints on range ('state' must be in the list ['Alabama', 'Alaska',...]). Thus even if type hinting is used, programmers still need to write code to actually validate the inputs to functions and methods, which is the role of packages like Param and Traitlets. Note that Pydantic focuses on [generating valid outputs at runtime](https://github.com/samuelcolvin/pydantic/issues/578focused) rather than detecting invalid inputs, so it may or may not be suitable for the same types of applications as the other libraries discussed here. +Python 3 type annotations allow users to specify types for attributes and function returns, but these types are not normally checked at runtime, and so they do not have the same role of validating user input or programmer error as the type declarations in Params, Traits, Traitlets, pydantic, and attr. They also are limited to the type, so they cannot enforce constraints on range ('state' must be in the list ['Alabama', 'Alaska',...]). Thus even if type hinting is used, programmers still need to write code to actually validate the inputs to functions and methods, which is the role of packages like Param and Traitlets. Note that Pydantic focuses on [generating valid outputs at runtime](https://github.com/samuelcolvin/pydantic/issues/578) rather than detecting invalid inputs, so it may or may not be suitable for the same types of applications as the other libraries discussed here. ## Generality and ease of integration with your project diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/doc/conf.py new/param-1.12.1/doc/conf.py --- old/param-1.12.0/doc/conf.py 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/doc/conf.py 2022-03-31 17:29:20.000000000 +0200 @@ -4,7 +4,7 @@ project = u'param' authors = u'HoloViz developers' -copyright = u'2003-2021 ' + authors +copyright = u'2003-2022 ' + authors description = 'Declarative Python programming using Parameters' import param @@ -12,7 +12,7 @@ param.parameterized.docstring_signature = False param.parameterized.docstring_describe_params = False -version = release = str(param.__version__) +version = release = base_version(param.__version__) nbbuild_cell_timeout = 600 @@ -32,20 +32,26 @@ "github_url": "https://github.com/holoviz/param", "icon_links": [ { + 'name': 'Twitter', + 'url': 'https://twitter.com/holoviz_org', + 'icon': 'fab fa-twitter-square', + }, + { "name": "Discourse", "url": "https://discourse.holoviz.org/", "icon": "fab fa-discourse", }, - ] + ], + "footer_items": [ + "copyright", + "last-updated", + ], + 'google_analytics_id': 'UA-154795830-6', } -html_context.update({ - 'PROJECT': project, - 'DESCRIPTION': description, - 'AUTHOR': authors, - 'VERSION': version, - 'theme_google_analytics_id': 'UA-154795830-6', - 'theme_github_url': 'https://github.com/holoviz/param', -}) - extensions += ['sphinx_copybutton'] + +# Override the Sphinx default title that appends `documentation` +html_title = f'{project} v{version}' +# Format of the last updated section in the footer +html_last_updated_fmt = '%Y-%m-%d' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/doc/getting_started.md new/param-1.12.1/doc/getting_started.md --- old/param-1.12.0/doc/getting_started.md 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/doc/getting_started.md 2022-03-31 17:29:20.000000000 +0200 @@ -22,8 +22,6 @@ pip install param ``` -The very latest changes can be obtained via `conda install -c pyviz/label/dev param` or `pip install https://github.com/ioam/param/archive/master.zip`. - ## Using Param to get simple, robust code The `param` library gives you Parameters, which are used in Parameterized classes. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/examples/user_guide/Parameters.ipynb new/param-1.12.1/examples/user_guide/Parameters.ipynb --- old/param-1.12.0/examples/user_guide/Parameters.ipynb 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/examples/user_guide/Parameters.ipynb 2022-03-31 17:29:20.000000000 +0200 @@ -31,9 +31,9 @@ "- **allow_None**: Whether this parameter accepts None as an allowed value, in addition to whatever other types it accepts. Automatically set to True if the default value of this Parameter is None.\n", "- **doc**: Docstring describing this parameter, which can be used by automatic documentation systems.\n", "- **constant**: Parameter whose value can only be changed at the class level or in a Parameterized constructor. Once the Parameterized instance has been created, the value is constant except in the context of `with param.edit_constant(obj)` (see below).\n", - "- **readonly**: Parameter whose value cannot be set by a user either on an instance or at the class level. Can still be changed inside a codebase by temporarily overriding this value, e.g. to report internal state\n", - "- **instantiate**: Whether to deepcopy the default value into a Parameterized instance when it is created. \n", - "- **per_instance**: whether a separate Parameter instance will be created for every Parameterized instance created.\n", + "- **readonly**: Parameter whose value cannot be set by a user either on an instance or at the class level. Can still be changed inside a codebase by temporarily overriding this value, e.g. to report internal state.\n", + "- **instantiate**: Whether to deepcopy the default value into a Parameterized instance when it is created. False by default for Parameter and most of its subtypes, but some Parameter types commonly used with mutable containers default to `instantiate=True` to avoid interaction between separate Parameterized instances, and users can control this when declaring the Parameter (see below). \n", + "- **per_instance**: whether a separate Parameter instance will be created for every Parameterized instance created. Similar to `instantiate`, but applies to the Parameter object rather than to its value.\n", "- **precedence**: Optional numeric value controlling whether this parameter is visible in a listing and if so in what order.\n", "\n", "Most of these settings (apart from **name**) are accepted as keyword arguments to the Parameter's constructor, with `default` also accepted as a positional argument:" @@ -97,7 +97,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Here, we created a Parameterized class `A`, with parameters `question` and `answer`, each with default values. We then instantiated a Python object `a` of type `A`. Without having to write a constructor for `A`, we were able to provide our own values for `question` and `answer`, while inheriting the default value of `ultimate_answer`. This approach gives a lot of (but not too much!) configurability to the user of this class, without much effort by the class author. Any values we provide at instantiation need to be allowed by the `Parameter` declaration; e.g. here we could not provide a value for `ultimate_answer` when declaring `a`, because that parameter is read only." + "Here, we created a Parameterized class `A`, with parameters `question` and `answer`, each with default values. We then instantiated a Python object `a` of type `A`. Without having to write a constructor for `A`, we were able to provide our own values for `question` and `answer`, while inheriting the default value of `ultimate_answer`. This approach gives a lot of (but not too much!) configurability to the user of this class, without much effort by the class author. Any values we provide at instantiation need to be allowed by the `Parameter` declaration; e.g. here we could not provide a value for `ultimate_answer` when declaring `a`, because that parameter is declared read only:" ] }, { @@ -174,7 +174,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If accessing the attribute always gives us a value whether on the instance or the class, what happened to the `Parameter` objects? They are stored on the Parameterized instance or class, and are accessible via a `param` accessor object at either the instance or class levels:" + "If accessing the attribute always gives us a value whether on the instance or the class, what happened to the `Parameter` objects? They are stored on the Parameterized instance or class, and are accessible via a special `param` accessor object at either the instance or class levels:" ] }, { @@ -244,7 +244,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Note that if you do need to change the value of a constant parameter (typically inside of your Parameterized object's own code), you can do so using the `param.edit_constant` context manager:" + "Note that if for some reason you do need to change the value of a constant parameter (typically inside of your Parameterized object's own code), you can do so using the `param.edit_constant` context manager:" ] }, { @@ -341,7 +341,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Parameter inheritance like this lets you (a) define a Parameter only once, no matter how many subclasses it might be used in, and (b) control the value of that parameter conveniently across the entire set of subclasses and instances, as long as that attribute has not been set on those objects already. Using inheritance in this way is a very convenient mechanism for setting default values and other \"global\" parameters, whether before a program starts executing or during it.\n", + "Parameter inheritance like this lets you (a) use a parameter in many subclasses without having to define it more than once, and (b) control the value of that parameter conveniently across the entire set of subclasses and instances, as long as that attribute has not been set on those objects already. Using inheritance in this way is a very convenient mechanism for setting default values and other \"global\" parameters, whether before a program starts executing or during it.\n", "\n", "However, what happens if the value (unlike Python strings) is mutable? Things get a lot more complex:" ] @@ -527,7 +527,7 @@ "source": [ "## Parameter metadata inheritance and instantiation\n", "\n", - "`instantiate` controls how parameter values behave, but similar issues arise for Parameter objects, which offer similar control via the `per_instance` metadata declaration. `per_instance` (True by default) provides a logically distinct Parameter object for every Parameterized instance, allowing each such instance to have different metadata for that parameter. For example, we can set the label separately for each instance without clobbering each other:" + "`instantiate` controls how parameter _values_ behave, but similar issues arise for Parameter _objects_, which offer similar control via the `per_instance` metadata declaration. `per_instance` (True by default) provides a logically distinct Parameter object for every Parameterized instance, allowing each such instance to have different metadata for that parameter. For example, we can set the label separately for each instance without clobbering each other:" ] }, { @@ -556,7 +556,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This capability is useful for situations with dynamically updated metadata, e.g. if you need setting one parameter's value (e.g. 'Continent') to change the allowed values of another parameter (e.g. 'Country'). The underlying Parameter objects are copied lazily (only when actually changed), so that objects are not actually multiplied unless necessary. If you do want parameters to share a single Parameter object so that you can control its behavior globally, you can achieve that with `per_instance=False`, though the effects are confusing in the same way as `instantiate=True` for mutable objects (above):" + "This capability is useful for situations with dynamically updated metadata, e.g. if you need setting one parameter's value (e.g. 'Continent') to change the allowed values of another parameter (e.g. 'Country'). The underlying Parameter objects are copied lazily (only when actually changed), so that objects are not actually multiplied unless necessary. If you do want parameters to share a single Parameter object so that you can control its behavior globally, you can achieve that with `per_instance=False`, though the effects can be confusing in the same way as `instantiate=True` for mutable objects (above):" ] }, { @@ -580,9 +580,9 @@ "source": [ "## Instantiating with shared parameters\n", "\n", - "When creating a large collection of Parameterized objects of the same type, the overhead of having separate parameters for each object can be significant. If you want, you can create the objects to share parameter instances for efficiency, and also so that you can easily change a value on all such objects at the same time. \n", + "When creating a large collection of Parameterized objects of the same type, the overhead of having separate parameters for each object can be significant. If you want, you can create the objects to share parameter values for efficiency, and also so that you can easily change a value on all such objects at the same time. \n", "\n", - "As an example, the default behavior of a set of objects will be to have independent parameter values, such that changing one of them will not affect the others:" + "As an example, let's say you've defined a Parameter value to be independent, such that changing one instance's value will not affect the others:" ] }, { @@ -592,7 +592,7 @@ "outputs": [], "source": [ "class S(param.Parameterized):\n", - " l = param.Parameter([1,2,3])\n", + " l = param.Parameter([1,2,3], instantiate=True)\n", "\n", "ss = [S() for i in range(10)]\n", "ss[0].l[2]=5\n", @@ -603,7 +603,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If you use the context manager `shared_parameters`, any Parameterized objects created within that context will share parameter instances, such that changing one of them will affect all of them:" + "Here changing the value of `l` on `ss[0]` doesn't affect `ss[1]` or any other instances.\n", + "\n", + "What if you as a user of this class are creating a very large number of similar objects and actually do want them to share the same parameter value, either to save memory or to make it easy to change all of their values at once? In that case you can use the context manager `shared_parameters`, and any Parameterized objects created within that context will share parameter values, such that changing one of them will affect all of them:" ] }, { @@ -623,7 +625,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "This approach can provide significant speedup and memory savings in certain cases." + "This approach can provide significant speedup and memory savings in certain cases, but should only be used for good reasons, since it can cause confusion for any code expecting instances to be independent as they have been declared." ] }, { @@ -728,7 +730,7 @@ "\n", "As you can see above, a `Parameter` provides a lot of power already on its own, but in practice you will want to use much more specific parameter types that reject invalid inputs and keep your code clean and simple. A specialized Parameter acts as a \"contract\" with the users of the code you write, declaring and defending precisely what configuration is allowed and how to achieve it. If you need to accept specific inputs like that but don't add an appropriate Parameter type, you'll be stuck adding exceptions and validation code throughout your codebase, whereas anything you can express at the Parameter level will be enforced automatically without any further checks or code.\n", "\n", - "For instance, what if you want to accept a numeric parameter, but (for some reason) can only accept numbers that are integer powers of 2? You'll need a custom Parameter class to express a restriction like that:" + "For instance, what if you want to accept a numeric parameter, but (for some reason) can only accept numbers that are integer powers of 2? You'll need a custom Parameter class to express a restriction like that. In this case you can do it by overriding the `_validate_value` method of the `Parameter` class:" ] }, { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/param/__init__.py new/param-1.12.1/param/__init__.py --- old/param-1.12.0/param/__init__.py 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/param/__init__.py 2022-03-31 17:29:20.000000000 +0200 @@ -43,7 +43,7 @@ # only two required files. try: from .version import Version - __version__ = str(Version(fpath=__file__, archive_commit="d490aa95", reponame="param")) + __version__ = str(Version(fpath=__file__, archive_commit="a11767ef", reponame="param")) except: __version__ = "0.0.0+unknown" @@ -894,7 +894,7 @@ def _validate_step(self, val, step): if step is not None and not _is_number(step): - raise ValueError("Step parameter can only be None or a " + raise ValueError("Step can only be None or a " "numeric value, not type %r." % type(step)) def _validate(self, val): @@ -936,7 +936,7 @@ def _validate_step(self, val, step): if step is not None and not isinstance(step, int): - raise ValueError("Step parameter can only be None or an " + raise ValueError("Step can only be None or an " "integer value, not type %r" % type(step)) @@ -1017,10 +1017,14 @@ @classmethod def serialize(cls, value): + if value is None: + return 'null' return list(value) # As JSON has no tuple representation @classmethod def deserialize(cls, value): + if value == 'null': + return None return tuple(value) # As JSON has no tuple representation @@ -1474,10 +1478,14 @@ @classmethod def serialize(cls, value): + if value is None: + return 'null' return value.tolist() @classmethod def deserialize(cls, value): + if value == 'null': + return None from numpy import asarray return asarray(value) @@ -1557,10 +1565,14 @@ @classmethod def serialize(cls, value): + if value is None: + return 'null' return value.to_dict('records') @classmethod def deserialize(cls, value): + if value == 'null': + return None from pandas import DataFrame as pdDFrame return pdDFrame(value) @@ -1911,26 +1923,36 @@ return if not isinstance(val, dt_types) and not (allow_None and val is None): - raise ValueError("Date parameter %r only takes datetime and date types." % self.name) + raise ValueError( + "Date parameter %r only takes datetime and date types, " + "not type %r." % (self.name, type(val)) + ) def _validate_step(self, val, step): if step is not None and not isinstance(step, dt_types): - raise ValueError("Step parameter can only be None, a datetime or datetime type") + raise ValueError( + "Step can only be None, a datetime " + "or datetime type, not type %r." % type(val) + ) @classmethod def serialize(cls, value): + if value is None: + return 'null' if not isinstance(value, (dt.datetime, dt.date)): # i.e np.datetime64 value = value.astype(dt.datetime) return value.strftime("%Y-%m-%dT%H:%M:%S.%f") @classmethod def deserialize(cls, value): + if value == 'null': + return None return dt.datetime.strptime(value, "%Y-%m-%dT%H:%M:%S.%f") class CalendarDate(Number): """ - CalendarDate parameter of date type. + Parameter specifically allowing dates (not datetimes). """ def __init__(self, default=None, **kwargs): @@ -1949,14 +1971,18 @@ def _validate_step(self, val, step): if step is not None and not isinstance(step, dt.date): - raise ValueError("Step parameter can only be None or a date type.") + raise ValueError("Step can only be None or a date type.") @classmethod def serialize(cls, value): + if value is None: + return 'null' return value.strftime("%Y-%m-%d") @classmethod def deserialize(cls, value): + if value == 'null': + return None return dt.datetime.strptime(value, "%Y-%m-%d").date() @@ -2093,13 +2119,13 @@ if isinstance(n, dt_types): continue raise ValueError("DateRange parameter %r only takes datetime " - "types, not %s." % (self.name, val)) + "types, not %r." % (self.name, type(val))) start, end = val if not end >= start: raise ValueError("DateRange parameter %r's end datetime %s " "is before start datetime %s." % - (self.name,val[1],val[0])) + (self.name, val[1], val[0])) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/param/parameterized.py new/param-1.12.1/param/parameterized.py --- old/param-1.12.0/param/parameterized.py 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/param/parameterized.py 2022-03-31 17:29:20.000000000 +0200 @@ -340,7 +340,14 @@ """ if not hasattr(inspect, 'iscoroutinefunction'): return False - return inspect.isasyncgenfunction(function) or inspect.iscoroutinefunction(function) + import asyncio + try: + return ( + inspect.isasyncgenfunction(function) or + asyncio.iscoroutinefunction(function) + ) + except AttributeError: + return False def instance_descriptor(f): @@ -382,9 +389,15 @@ watch = kw.pop("watch", False) on_init = kw.pop("on_init", False) - @wraps(func) - def _depends(*args, **kw): - return func(*args, **kw) + if iscoroutinefunction(func): + import asyncio + @asyncio.coroutine + def _depends(*args, **kw): + yield from func(*args, **kw) + else: + @wraps(func) + def _depends(*args, **kw): + return func(*args, **kw) deps = list(dependencies)+list(kw.values()) string_specs = False @@ -416,10 +429,18 @@ 'parameters by name.') if not string_specs and watch: # string_specs case handled elsewhere (later), in Parameterized.__init__ - def cb(*events): - args = (getattr(dep.owner, dep.name) for dep in dependencies) - dep_kwargs = {n: getattr(dep.owner, dep.name) for n, dep in kw.items()} - return func(*args, **dep_kwargs) + if iscoroutinefunction(func): + import asyncio + @asyncio.coroutine + def cb(*events): + args = (getattr(dep.owner, dep.name) for dep in dependencies) + dep_kwargs = {n: getattr(dep.owner, dep.name) for n, dep in kw.items()} + yield from func(*args, **dep_kwargs) + else: + def cb(*events): + args = (getattr(dep.owner, dep.name) for dep in dependencies) + dep_kwargs = {n: getattr(dep.owner, dep.name) for n, dep in kw.items()} + return func(*args, **dep_kwargs) grouped = defaultdict(list) for dep in deps: @@ -641,7 +662,7 @@ def caller(*events): if callback: callback(*events) if not _skip_event(*events, what=what, changed=changed): - yield function() + yield from function() else: def caller(*events): if callback: callback(*events) @@ -2010,7 +2031,7 @@ if self_.self_or_cls.param._BATCH_WATCH: self_._events.append(event) - if watcher not in self_._watchers: + if not any(watcher is w for w in self_._watchers): self_._watchers.append(watcher) else: event = self_._update_event_type(watcher, event, self_.self_or_cls.param._TRIGGER) @@ -2351,7 +2372,7 @@ elif hasattr(src, attr): info = MInfo(inst=inst, cls=cls, name=attr, method=getattr(src, attr)) - elif src.abstract: + elif getattr(src, "abstract", None): return [], [] if intermediate == 'only' else [DInfo(spec=spec)] else: raise AttributeError("Attribute %r could not be resolved on %s." diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/setup.py new/param-1.12.1/setup.py --- old/param-1.12.0/setup.py 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/setup.py 2022-03-31 17:29:20.000000000 +0200 @@ -25,10 +25,11 @@ ], 'doc': [ 'pygraphviz', - 'nbsite >=0.6.1', + 'nbsite >=0.7.1', 'pydata-sphinx-theme', + 'jinja2 <3.1', # API breakage 'myst-parser', - 'nbconvert <6.0', + 'nbconvert', 'graphviz', 'myst_nb ==0.12.2', 'sphinx-copybutton', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/tests/API1/testjsonserialization.py new/param-1.12.1/tests/API1/testjsonserialization.py --- old/param-1.12.0/tests/API1/testjsonserialization.py 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/tests/API1/testjsonserialization.py 2022-03-31 17:29:20.000000000 +0200 @@ -41,8 +41,8 @@ __test__ = False - numpy_params = ['r'] - pandas_params = ['s','t','u'] + numpy_params = ['r','y'] + pandas_params = ['s','t','u','z'] conditionally_unsafe = ['f', 'o'] a = param.Integer(default=5, doc='Example doc', bounds=(2,30), inclusive_bounds=(True, False)) @@ -68,6 +68,11 @@ {'A':[1,2,3], 'B':[1.1,2.2,3.3]}), columns=(1,4), rows=(2,5)) u = None if pd is None else param.DataFrame(default=df2, columns=['A', 'B']) v = param.Dict({'1':2}) + w = param.Date(default=None, allow_None=True) + x = param.CalendarDate(default=None, allow_None=True) + y = None if np is None else param.Array(default=None) + z = None if pd is None else param.DataFrame(default=None, allow_None=True) + aa = param.Tuple(default=None, allow_None=True, length=1) test = TestSet(a=29) @@ -184,7 +189,10 @@ serialized = test.param.serialize_parameters(subset=test.pandas_params, mode=self.mode) deserialized = TestSet.param.deserialize_parameters(serialized, mode=self.mode) for pname in test.pandas_params: - self.assertTrue(getattr(test, pname).equals(deserialized[pname])) + if getattr(test, pname) is None: + self.assertTrue(deserialized[pname] is None) + else: + self.assertTrue(getattr(test, pname).equals(deserialized[pname])) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/param-1.12.0/tests/API1/testnumberparameter.py new/param-1.12.1/tests/API1/testnumberparameter.py --- old/param-1.12.0/tests/API1/testnumberparameter.py 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/tests/API1/testnumberparameter.py 2022-03-31 17:29:20.000000000 +0200 @@ -35,21 +35,21 @@ self.assertEqual(qobj.param['q'].step, 0.5) def test_step_invalid_type_number_parameter(self): - exception = "Step parameter can only be None or a numeric value" + exception = "Step can only be None or a numeric value" with self.assertRaisesRegex(ValueError, exception): param.Number(step='invalid value') def test_step_invalid_type_integer_parameter(self): - exception = "Step parameter can only be None or an integer value" + exception = "Step can only be None or an integer value" with self.assertRaisesRegex(ValueError, exception): param.Integer(step=3.4) def test_step_invalid_type_datetime_parameter(self): - exception = "Step parameter can only be None, a datetime or datetime type" + exception = "Step can only be None, a datetime or datetime type" with self.assertRaisesRegex(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" + exception = "Step can only be None or a date type" with self.assertRaisesRegex(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.12.0/tests/API1/testparamdepends.py new/param-1.12.1/tests/API1/testparamdepends.py --- old/param-1.12.0/tests/API1/testparamdepends.py 2021-10-21 14:11:10.000000000 +0200 +++ new/param-1.12.1/tests/API1/testparamdepends.py 2022-03-31 17:29:20.000000000 +0200 @@ -2,6 +2,7 @@ Unit test for param.depends. """ +import pytest import param @@ -709,3 +710,27 @@ self.assertEqual(d, [4]) p.b = 3 self.assertEqual(d, [4, 5]) + + +def test_misspelled_parameter_in_depends(): + class Example(param.Parameterized): + xlim = param.Range((0, 10), bounds=(0, 100)) + + @param.depends("tlim") # <- Misspelled xlim + def test(self): + return True + + example = Example() + with pytest.raises(AttributeError, match="Attribute 'tlim' could not be resolved on"): + # Simulating: pn.panel(example.test) + example.param.method_dependencies(example.test.__name__) + + +def test_misspelled_parameter_in_depends_watch(): + with pytest.raises(AttributeError, match="Attribute 'tlim' could not be resolved on"): + class Example(param.Parameterized): + xlim = param.Range((0, 10), bounds=(0, 100)) + + @param.depends("tlim", watch=True) # <- Misspelled xlim + def test(self): + return True
