Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-ipywidgets for openSUSE:Factory checked in at 2022-08-02 22:08:52 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-ipywidgets (Old) and /work/SRC/openSUSE:Factory/.python-ipywidgets.new.1533 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-ipywidgets" Tue Aug 2 22:08:52 2022 rev:9 rq:992081 version:7.7.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-ipywidgets/python-ipywidgets.changes 2022-01-07 12:47:10.711878675 +0100 +++ /work/SRC/openSUSE:Factory/.python-ipywidgets.new.1533/python-ipywidgets.changes 2022-08-02 22:09:22.817805070 +0200 @@ -1,0 +2,41 @@ +Mon Aug 1 17:41:47 UTC 2022 - Ben Greiner <c...@bnavigator.de> + +- Update to version 7.7.1 + * Fix broken link icon for FontAwesome 4 and 5 #3495 + * Fix message throttling bug #3494 + * Fix state message parsing to be more permissive #3486 + * Fix tests on Python 3.11 #3480 + * Add better front-page docs #3496 +- Release 7.7 + * Fix installation on Python 3.10. #3368 + * Throw an error if we cannot render a widget, enabling the + rendering system to fall back to rendering a different data + type if available. #3290 + * Create a new widget control comm channel, enabling more + efficient fetching of kernel widget state. #3201 + * Refactor logic for fetching kernel widget state to the manager + base class. This logic first tries to use the new widget + control comm channel, falling back to the existing method of + requesting each widget's state individually. #3337 + * Enable HTMLManager output widgets to render state updates. + #3372 + * Do not reset JupyterLab CSS variables if they are already + defined. #3344 + * Fix variable inspector example. #3302 + * Introduce new widget manager has_model method for synchronously + checking if a widget model is registered. #3377 + * Work around bug in Chrome rendering Combobox arrows. #3375 + * Optionally echo update messages from frontends to other + frontends. This enables widget views in different frontends to + maintain consistent state simultaneously, and also makes sure + that simultaneous updates from the kernel and frontend resolve + to a consistent state. This is off by default in ipywidgets + 7.7, and it is anticipated this will be on by default in + ipywidgets 8.0. To enable echo update messages across + ipywidgets, set the environment variable JUPYTER_WIDGETS_ECHO + to 1. To opt a specific attribute out of echo updates, tag the + attribute with echo_update=False metadata (we do this in core + for the FileUpload widget's data attribute). #3400, #3394 +- Drop ipywidgets-pr2655-collectionsabc.patch + +------------------------------------------------------------------- Old: ---- ipywidgets-7.6.5.tar.gz ipywidgets-pr2655-collectionsabc.patch New: ---- ipywidgets-7.7.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-ipywidgets.spec ++++++ --- /var/tmp/diff_new_pack.nn57aa/_old 2022-08-02 22:09:23.649807469 +0200 +++ /var/tmp/diff_new_pack.nn57aa/_new 2022-08-02 22:09:23.653807480 +0200 @@ -19,15 +19,13 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-ipywidgets -Version: 7.6.5 +Version: 7.7.1 Release: 0 Summary: IPython HTML widgets for Jupyter License: BSD-3-Clause Group: Development/Languages/Python URL: https://github.com/jupyter-widgets/ipywidgets Source0: https://files.pythonhosted.org/packages/source/i/ipywidgets/ipywidgets-%{version}.tar.gz -# PATCH-FIX-UPSTREAM ipywidgets-pr2655-collectionsabc.patch -- gh#jupyter-widgets/ipywidgets#2655 -Patch0: https://github.com/jupyter-widgets/ipywidgets/commit/f9a13dbb3b8f1ffefef483bdb4c14f04f7743ff1.patch#/ipywidgets-pr2655-collectionsabc.patch BuildRequires: %{python_module setuptools} BuildRequires: fdupes BuildRequires: python-rpm-macros @@ -36,9 +34,8 @@ Requires: python-ipython >= 4 Requires: python-ipython_genutils >= 0.2 Requires: python-jupyterlab_widgets >= 1 -Requires: python-nbformat >= 4.2 Requires: python-traitlets >= 4.3.1 -Requires: python-widgetsnbextension >= 3.5.0 +Requires: python-widgetsnbextension >= 3.6.0 Provides: python-jupyter_ipywidgets = %{version} Obsoletes: python-jupyter_ipywidgets < %{version} BuildArch: noarch @@ -47,10 +44,9 @@ BuildRequires: %{python_module ipython >= 4} BuildRequires: %{python_module ipython_genutils >= 0.2} BuildRequires: %{python_module jupyterlab_widgets >= 1} -BuildRequires: %{python_module nbformat >= 4.2.0} BuildRequires: %{python_module pytest >= 3.6.0} BuildRequires: %{python_module traitlets >= 4.3.1} -BuildRequires: %{python_module widgetsnbextension >= 3.5.0} +BuildRequires: %{python_module widgetsnbextension >= 3.6.0} # /SECTION %if "%{python_flavor}" == "python3" || "%{?python_provides}" == "python3" Provides: jupyter-ipywidgets = %{version} ++++++ ipywidgets-7.6.5.tar.gz -> ipywidgets-7.7.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/PKG-INFO new/ipywidgets-7.7.1/PKG-INFO --- old/ipywidgets-7.6.5/PKG-INFO 2021-09-14 01:41:09.782837900 +0200 +++ new/ipywidgets-7.7.1/PKG-INFO 2022-06-22 19:40:16.771635000 +0200 @@ -1,33 +1,11 @@ -Metadata-Version: 1.1 +Metadata-Version: 2.1 Name: ipywidgets -Version: 7.6.5 +Version: 7.7.1 Summary: IPython HTML widgets for Jupyter Home-page: http://ipython.org Author: IPython Development Team Author-email: ipython-...@scipy.org License: BSD -Description: - .. image:: https://img.shields.io/pypi/v/ipywidgets.svg - :target: https://pypi.python.org/pypi/ipywidgets/ - :alt: Version Number - - .. image:: https://img.shields.io/pypi/dm/ipywidgets.svg - :target: https://pypi.python.org/pypi/ipywidgets/ - :alt: Number of PyPI downloads - - Interactive HTML Widgets - ======================== - - Interactive HTML widgets for Jupyter notebooks and the IPython kernel. - - Usage - ===== - - .. code-block:: python - - from ipywidgets import IntSlider - IntSlider() - Keywords: Interactive,Interpreter,Shell,Web Platform: Linux Platform: Mac OS X @@ -43,3 +21,27 @@ Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: 3.5 Classifier: Framework :: Jupyter +Provides-Extra: test +License-File: LICENSE + + +.. image:: https://img.shields.io/pypi/v/ipywidgets.svg + :target: https://pypi.python.org/pypi/ipywidgets/ + :alt: Version Number + +.. image:: https://img.shields.io/pypi/dm/ipywidgets.svg + :target: https://pypi.python.org/pypi/ipywidgets/ + :alt: Number of PyPI downloads + +Interactive HTML Widgets +======================== + +Interactive HTML widgets for Jupyter notebooks and the IPython kernel. + +Usage +===== + +.. code-block:: python + + from ipywidgets import IntSlider + IntSlider() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/docs/requirements.txt new/ipywidgets-7.7.1/docs/requirements.txt --- old/ipywidgets-7.6.5/docs/requirements.txt 2021-09-14 01:30:14.885464400 +0200 +++ new/ipywidgets-7.7.1/docs/requirements.txt 2022-06-22 19:32:54.793054000 +0200 @@ -7,4 +7,5 @@ numpy recommonmark sphinx>=1.4.6 +jinja2==3.0.0 # pin since newer jinja2 conflicts with sphinx 1.8.6, the default on readthedocs sphinx_rtd_theme diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/docs/source/changelog.md new/ipywidgets-7.7.1/docs/source/changelog.md --- old/ipywidgets-7.6.5/docs/source/changelog.md 2021-09-14 01:30:14.885993500 +0200 +++ new/ipywidgets-7.7.1/docs/source/changelog.md 2022-06-22 19:32:54.793225000 +0200 @@ -3,6 +3,37 @@ A summary of changes in ipywidgets. For more detailed information, see the issues and pull requests for the appropriate milestone on [GitHub](https://github.com/jupyter-widgets/ipywidgets). +7.7.1 +----- + +To see the full list of pull requests, see the [7.7.1 milestone](https://github.com/jupyter-widgets/ipywidgets/milestone/36?closed=1) on GitHub. + +Highlights include: + +- Fix broken link icon for FontAwesome 4 and 5 [#3495](https://github.com/jupyter-widgets/ipywidgets/pull/3495) +- Fix message throttling bug [#3494](https://github.com/jupyter-widgets/ipywidgets/pull/3494) +- Fix state message parsing to be more permissive [#3486](https://github.com/jupyter-widgets/ipywidgets/pull/3486) +- Fix tests on Python 3.11 [#3480](https://github.com/jupyter-widgets/ipywidgets/pull/3480) +- Add better front-page docs [#3496](https://github.com/jupyter-widgets/ipywidgets/pull/3496) + +7.7 +--- + +To see the full list of pull requests and issues, see the [7.7 milestone](https://github.com/jupyter-widgets/ipywidgets/milestone/35?closed=1) on GitHub. + +Highlights include: + +- Fix installation on Python 3.10. [#3368](https://github.com/jupyter-widgets/ipywidgets/pull/3368) +- Throw an error if we cannot render a widget, enabling the rendering system to fall back to rendering a different data type if available. [#3290](https://github.com/jupyter-widgets/ipywidgets/pull/3290) +- Create a new widget control comm channel, enabling more efficient fetching of kernel widget state. [#3201](https://github.com/jupyter-widgets/ipywidgets/pull/3021) +- Refactor logic for fetching kernel widget state to the manager base class. This logic first tries to use the new widget control comm channel, falling back to the existing method of requesting each widget's state individually. [#3337](https://github.com/jupyter-widgets/ipywidgets/pull/3337) +- Enable HTMLManager output widgets to render state updates. [#3372](https://github.com/jupyter-widgets/ipywidgets/pull/3372) +- Do not reset JupyterLab CSS variables if they are already defined. [#3344](https://github.com/jupyter-widgets/ipywidgets/pull/3344) +- Fix variable inspector example. [#3302](https://github.com/jupyter-widgets/ipywidgets/pull/3302) +- Introduce new widget manager `has_model` method for synchronously checking if a widget model is registered. [#3377](https://github.com/jupyter-widgets/ipywidgets/pull/3377) +- Work around bug in Chrome rendering Combobox arrows. [#3375](https://github.com/jupyter-widgets/ipywidgets/pull/3375) +- Optionally echo update messages from frontends to other frontends. This enables widget views in different frontends to maintain consistent state simultaneously, and also makes sure that simultaneous updates from the kernel and frontend resolve to a consistent state. This is off by default in ipywidgets 7.7, and it is anticipated this will be on by default in ipywidgets 8.0. To enable echo update messages across ipwyidgets, set the environment variable `JUPYTER_WIDGETS_ECHO` to 1. To opt a specific attribute out of echo updates, tag the attribute with `echo_update=False` metadata (we do this in core for the FileUpload widget's `data` attribute). [#3400](https://github.com/jupyter-widgets/ipywidgets/pull/3400) + 7.6 --- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/docs/source/conf.py new/ipywidgets-7.7.1/docs/source/conf.py --- old/ipywidgets-7.6.5/docs/source/conf.py 2021-09-14 01:30:14.886560700 +0200 +++ new/ipywidgets-7.7.1/docs/source/conf.py 2022-06-22 19:32:54.793347800 +0200 @@ -42,10 +42,10 @@ master_doc = 'index' project = 'Jupyter Widgets' -copyright = '2017 Project Jupyter' +copyright = '2017-2022 Project Jupyter' author = 'Jupyter Team' -language = None +language = "en" exclude_patterns = [ '**.ipynb_checkpoints', 'examples.md', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/docs/source/dev_install.md new/ipywidgets-7.7.1/docs/source/dev_install.md --- old/ipywidgets-7.6.5/docs/source/dev_install.md 2021-09-14 01:30:14.887445000 +0200 +++ new/ipywidgets-7.7.1/docs/source/dev_install.md 2022-06-22 19:32:54.793535500 +0200 @@ -1,5 +1,9 @@ # Developer Install +The core Jupyter Widgets packages are developed in the +[https://github.com/jupyter-widgets/ipywidgets](https://github.com/jupyter-widgets/ipywidgets) git repository. + + ## Prerequisites To install ipywidgets from git, you will need: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/docs/source/developer_docs.rst new/ipywidgets-7.7.1/docs/source/developer_docs.rst --- old/ipywidgets-7.6.5/docs/source/developer_docs.rst 2021-09-14 01:30:14.888560500 +0200 +++ new/ipywidgets-7.7.1/docs/source/developer_docs.rst 1970-01-01 01:00:00.000000000 +0100 @@ -1,27 +0,0 @@ -Developer Docs -=============== - -The Jupyter widgets packages are developed in the `https://github.com/jupyter-widgets/ipywidgets <https://github.com/jupyter-widgets/ipywidgets>`_ git repository. See the issue tracker, README, and other Github documents for the most recent information. - - -Scope of ipywidgets -------------------- - -``ipywidgets`` is a framework to provide eventful python objects that have a representation in the browser (see :doc:`examples/Widget Basics.ipynb` for more on the definition of widgets). This requires two components: - -1. The framework for widget interactions between the widgets represented in the Python kernel and the (javascript) representation of the widgets in the browser. -2. A basic, lightweight set of form controls that *use* this framework, based on standard HTML form controls. These included controls include a text area, text box, select and multiselect controls, checkbox, etc. A few more advanced controls that are very popular are also included, such as a slider and basic tab panels. - -The framework for building rich interactive objects is the foremost purpose of the ipywidgets project, and the set of included reference form controls is purposefully kept small and self-contained to serve as something like a reference implementation. We encourage and support a robust ecosystem of packages built on top of the ipywidgets framework to provide more complicated interactive objects, such as maps or 2d and 3d visualizations, or other form control systems built on a variety of popular Javascript frameworks such as Material or Vue. - - -Additional Developer Docs -------------------------- - -.. toctree:: - :maxdepth: 3 - - dev_install.md - dev_testing.md - dev_docs - dev_release.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/ipywidgets-7.6.5/docs/source/examples/Layout Example.ipynb" "new/ipywidgets-7.7.1/docs/source/examples/Layout Example.ipynb" --- "old/ipywidgets-7.6.5/docs/source/examples/Layout Example.ipynb" 2021-09-14 01:30:14.890474800 +0200 +++ "new/ipywidgets-7.7.1/docs/source/examples/Layout Example.ipynb" 2022-06-22 19:32:54.794555700 +0200 @@ -57,7 +57,7 @@ "metadata": {}, "outputs": [], "source": [ - "m = Map(center=(52, 10), zoom=5, basemap=basemaps.Hydda.Full)" + "m = Map(center=(52, 10), zoom=5, basemap=basemaps.OpenStreetMap.Mapnik)" ] }, { @@ -66,7 +66,7 @@ "metadata": {}, "outputs": [], "source": [ - "maps = {'Hydda' : basemaps.Hydda.Full,\n", + "maps = {'Mapnik' : basemaps.OpenStreetMap.Mapnik,\n", " 'Esri' : basemaps.Esri.DeLorme}" ] }, @@ -91,7 +91,7 @@ "metadata": {}, "outputs": [], "source": [ - "basemap_selector.value = 'Hydda'\n", + "basemap_selector.value = 'Mapnik'\n", "m.layout.height='600px'" ] }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' "old/ipywidgets-7.6.5/docs/source/examples/Variable Inspector.ipynb" "new/ipywidgets-7.7.1/docs/source/examples/Variable Inspector.ipynb" --- "old/ipywidgets-7.6.5/docs/source/examples/Variable Inspector.ipynb" 2021-09-14 01:30:14.895717100 +0200 +++ "new/ipywidgets-7.7.1/docs/source/examples/Variable Inspector.ipynb" 2022-06-22 19:32:54.796830200 +0200 @@ -73,7 +73,7 @@ " self.closed = True\n", " VariableInspectorWindow.instance = None\n", "\n", - " def _fill(self):\n", + " def _fill(self, _result):\n", " \"\"\"Fill self with variable information.\"\"\"\n", " values = self.namespace.who_ls()\n", " self._table.value = '<div class=\"rendered_html jp-RenderedHTMLCommon\"><table><thead><tr><th>Name</th><th>Type</th><th>Value</th></tr></thead><tr><td>' + \\\n", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/docs/source/index.rst new/ipywidgets-7.7.1/docs/source/index.rst --- old/ipywidgets-7.6.5/docs/source/index.rst 2021-09-14 01:30:14.902526600 +0200 +++ new/ipywidgets-7.7.1/docs/source/index.rst 2022-06-22 19:32:54.801359400 +0200 @@ -1,11 +1,104 @@ -ipywidgets -========== +Jupyter Widgets +=============== -Full Table of Contents ----------------------- +.. only:: html + + :Release: |release| + :Date: |today| + +Jupyter Widgets are `interactive browser controls +<https://github.com/jupyter-widgets/ipywidgets/blob/master/docs/source/examples/Index.ipynb>`_ +for Jupyter notebooks. Examples include: + +* Basic form controls like sliders, checkboxes, text inputs +* Container controls like tabs, accordions, horizontal and vertical layout boxes, grid layouts +* Advanced controls like maps, 2d and 3d visualizations, datagrids, and more + +Notebooks come alive when interactive widgets are used. Users can visualize and +manipulate their data in intuitive and easy ways. Researchers can easily see +how changing inputs to a model impact the results. Scientists can share +interactive results with graphical user interfaces that others can play with +without seeing code. Exploring, learning, and sharing becomes a fun immersive +experience. + +.. todo: Add screenshot + +Core Jupyter Widgets +-------------------- + +Jupyter Widgets is primarily a framework to provide interactive controls (see +:doc:`examples/Widget Basics` for more information). The ``ipywidgets`` package +also provides a basic, lightweight set of core form controls that *use* this +framework. These included controls include a text area, text box, select and +multiselect controls, checkbox, sliders, tab panels, grid layout, etc. + +The framework for building rich interactive objects is the foremost purpose of +the Jupyter Widgets project, and the set of included core form controls is +purposefully kept small and self-contained. We encourage and support a robust +ecosystem of packages built on top of the Jupyter Widgets framework to provide +more complicated interactive objects, such as maps, 2d and 3d visualizations, or +other form control systems built on a variety of popular Javascript frameworks +such as Material or Vue. + +See the `Jupyter Widgets wiki page +<https://github.com/jupyter/jupyter/wiki/Jupyter-Widgets>`_ for more information +about custom widget packages built on top of the Jupyter Widgets framework. + +Jupyter Widgets components +-------------------------- + +The Jupyter Widgets framework has several components: + +1. A package in the kernel to provide an interface for widgets. The + ``ipywidgets`` Python package provides Jupyter Widgets for the IPython + kernel. Other kernels may also provide Jupyter Widgets support. +2. An extension for the browser Jupyter frontend to manage Jupyter Widgets. + Installing ``ipywidgets`` automatically installs extensions for JupyterLab + and Jupyter Notebook (the ``jupyterlab-widgets`` and ``widgetsnbextension`` + packages). The Jupyter Widgets project also maintains a plain HTML interface + for embedding Jupyter Widgets on a webpage, and many other frontends support + Jupyter Widgets. + +See the `Jupyter Widgets wiki +page <https://github.com/jupyter/jupyter/wiki/Jupyter-Widgets>`_ for more +information from the community about kernels and frontends that support Jupyter Widgets, as well as +some custom widget packages built on top of the Jupyter Widgets framework. .. toctree:: :maxdepth: 2 - user_guide - developer_docs + user_install.md + examples/Widget Basics.ipynb + examples/Widget List.ipynb + examples/Output Widget.ipynb + examples/Widget Events.ipynb + examples/Widget Styling.ipynb + examples/Layout Templates.ipynb + examples/Widget Custom.ipynb + examples/Using Interact.ipynb + examples/Widget Low Level.ipynb + examples/Widget Asynchronous.ipynb + embedding.md + +.. toctree:: + :caption: Changelog and Migration + :maxdepth: 1 + + changelog.md + migration_guides.md + +.. toctree:: + :caption: Developer Guide + :maxdepth: 1 + + dev_install.md + dev_testing.md + dev_docs.md + contributing.md + dev_release.md + +.. only:: html + + * :ref:`genindex` + * :ref:`modindex` + * :ref:`search` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/ipywidgets/__init__.py new/ipywidgets-7.7.1/ipywidgets/__init__.py --- old/ipywidgets-7.6.5/ipywidgets/__init__.py 2021-09-14 01:30:14.909575000 +0200 +++ new/ipywidgets-7.7.1/ipywidgets/__init__.py 2022-06-22 19:32:54.803705200 +0200 @@ -38,6 +38,7 @@ if kernel is None: kernel = get_ipython().kernel kernel.comm_manager.register_target('jupyter.widget', Widget.handle_comm_opened) + kernel.comm_manager.register_target('jupyter.widget.control', Widget.handle_control_comm_opened) # deprecated alias handle_kernel = register_comm_target diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/ipywidgets/_version.py new/ipywidgets-7.7.1/ipywidgets/_version.py --- old/ipywidgets-7.6.5/ipywidgets/_version.py 2021-09-14 01:40:57.517728600 +0200 +++ new/ipywidgets-7.7.1/ipywidgets/_version.py 2022-06-22 19:40:05.534478700 +0200 @@ -1,14 +1,15 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. -version_info = (7, 6, 5, 'final', 0) +version_info = (7, 7, 1, 'final', 0) _specifier_ = {'alpha': 'a', 'beta': 'b', 'candidate': 'rc', 'final': ''} __version__ = '%s.%s.%s%s'%(version_info[0], version_info[1], version_info[2], '' if version_info[3]=='final' else _specifier_[version_info[3]]+str(version_info[4])) -__protocol_version__ = '2.0.0' +__protocol_version__ = '2.1.0' +__control_protocol_version__ = '1.0.0' # These are *protocol* versions for each package, *not* npm versions. To check, look at each package's src/version.ts file for the protocol version the package implements. __jupyter_widgets_base_version__ = '1.2.0' @@ -16,4 +17,4 @@ __jupyter_widgets_controls_version__ = '1.5.0' # A compatible @jupyter-widgets/html-manager npm package semver range -__html_manager_version__ = '^0.20.0' +__html_manager_version__ = '^0.20.1' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/ipywidgets/widgets/tests/test_interaction.py new/ipywidgets-7.7.1/ipywidgets/widgets/tests/test_interaction.py --- old/ipywidgets-7.6.5/ipywidgets/widgets/tests/test_interaction.py 2021-09-14 01:30:14.912984600 +0200 +++ new/ipywidgets-7.7.1/ipywidgets/widgets/tests/test_interaction.py 2022-06-22 19:32:54.805021500 +0200 @@ -254,7 +254,12 @@ check_widgets(c, lis=d) def test_mapping(): - from collections import Mapping, OrderedDict + try: + # Python 3 + from collections.abc import Mapping + except ImportError: + # Python 2 + from collections import Mapping class TestMapping(Mapping): def __init__(self, values): self.values = values @@ -698,7 +703,7 @@ def test_interact_noinspect(): a = u'hello' - c = interactive(print, a=a) + c = interactive(dict, a=a) w = c.children[0] check_widget(w, cls=widgets.Text, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/ipywidgets/widgets/tests/test_send_state.py new/ipywidgets-7.7.1/ipywidgets/widgets/tests/test_send_state.py --- old/ipywidgets-7.6.5/ipywidgets/widgets/tests/test_send_state.py 2021-09-14 01:29:56.141703100 +0200 +++ new/ipywidgets-7.7.1/ipywidgets/widgets/tests/test_send_state.py 2022-06-22 19:32:54.805210000 +0200 @@ -3,10 +3,12 @@ from traitlets import Bool, Tuple, List -from .utils import setup, teardown +from .utils import setup, teardown, DummyComm from ..widget import Widget +from ..._version import __control_protocol_version__ + # A widget with simple traits class SimpleWidget(Widget): a = Bool().tag(sync=True) @@ -23,3 +25,16 @@ with w.hold_sync(): pass assert w.comm.messages == [] + + +def test_control(): + comm = DummyComm() + Widget.close_all() + w = SimpleWidget() + Widget.handle_control_comm_opened( + comm, dict(metadata={'version': __control_protocol_version__}) + ) + Widget._handle_control_comm_msg(dict(content=dict( + data={'method': 'request_states'} + ))) + assert comm.messages diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/ipywidgets/widgets/tests/test_set_state.py new/ipywidgets-7.7.1/ipywidgets/widgets/tests/test_set_state.py --- old/ipywidgets-7.6.5/ipywidgets/widgets/tests/test_set_state.py 2021-09-14 01:30:14.913266000 +0200 +++ new/ipywidgets-7.7.1/ipywidgets/widgets/tests/test_set_state.py 2022-06-22 19:32:54.805292000 +0200 @@ -1,20 +1,26 @@ # Copyright (c) Jupyter Development Team. # Distributed under the terms of the Modified BSD License. -from ipython_genutils.py3compat import PY3 - import pytest try: from unittest import mock except ImportError: import mock - from traitlets import Bool, Tuple, List, Instance, CFloat, CInt, Float, Int, TraitError, observe from .utils import setup, teardown -from ..widget import Widget +import ipywidgets +from ipywidgets import Widget + + +@pytest.fixture(params=[True, False]) +def echo(request): + oldvalue = ipywidgets.widgets.widget.JUPYTER_WIDGETS_ECHO + ipywidgets.widgets.widget.JUPYTER_WIDGETS_ECHO = request.param + yield request.param + ipywidgets.widgets.widget.JUPYTER_WIDGETS_ECHO = oldvalue # # First some widgets to test on: @@ -78,7 +84,7 @@ # Actual tests: # -def test_set_state_simple(): +def test_set_state_simple(echo): w = SimpleWidget() w.set_state(dict( a=True, @@ -86,35 +92,47 @@ c=[False, True, False], )) - assert w.comm.messages == [] + assert len(w.comm.messages) == (1 if echo else 0) -def test_set_state_transformer(): +def test_set_state_transformer(echo): w = TransformerWidget() w.set_state(dict( d=[True, False, True] )) # Since the deserialize step changes the state, this should send an update - assert w.comm.messages == [((), dict( + expected = [] + if echo: + expected.append( + ((), dict( + buffers=[], + data=dict( + buffer_paths=[], + method='echo_update', + state=dict(d=[True, False, True]), + )))) + expected.append( + ((), dict( buffers=[], data=dict( buffer_paths=[], method='update', - state=dict(d=[False, True, False]) - )))] + state=dict(d=[False, True, False]), + )))) + assert w.comm.messages == expected -def test_set_state_data(): +def test_set_state_data(echo): w = DataWidget() data = memoryview(b'x'*30) w.set_state(dict( a=True, d={'data': data}, )) - assert w.comm.messages == [] + assert len(w.comm.messages) == (1 if echo else 0) -def test_set_state_data_truncate(): +def test_set_state_data_truncate(echo): w = TruncateDataWidget() data = memoryview(b'x'*30) w.set_state(dict( @@ -122,15 +140,15 @@ d={'data': data}, )) # Get message for checking - assert len(w.comm.messages) == 1 # ensure we didn't get more than expected - msg = w.comm.messages[0] + assert len(w.comm.messages) == 2 if echo else 1 # ensure we didn't get more than expected + msg = w.comm.messages[-1] # Assert that the data update (truncation) sends an update buffers = msg[1].pop('buffers') assert msg == ((), dict( data=dict( - buffer_paths=[['d', 'data']], method='update', - state=dict(d={}) + state=dict(d={}), + buffer_paths=[['d', 'data']] ))) # Sanity: @@ -138,7 +156,7 @@ assert buffers[0] == data[:20].tobytes() -def test_set_state_numbers_int(): +def test_set_state_numbers_int(echo): # JS does not differentiate between float/int. # Instead, it formats exact floats as ints in JSON (1.0 -> '1'). @@ -150,11 +168,11 @@ i = 3, ci = 4, )) - # Ensure no update message gets produced - assert len(w.comm.messages) == 0 + # Ensure one update message gets produced + assert len(w.comm.messages) == (1 if echo else 0) -def test_set_state_numbers_float(): +def test_set_state_numbers_float(echo): w = NumberWidget() # Set floats to int-like floats w.set_state(dict( @@ -162,22 +180,22 @@ cf = 2.0, ci = 4.0 )) - # Ensure no update message gets produced - assert len(w.comm.messages) == 0 + # Ensure one update message gets produced + assert len(w.comm.messages) == (1 if echo else 0) -def test_set_state_float_to_float(): +def test_set_state_float_to_float(echo): w = NumberWidget() # Set floats to float w.set_state(dict( f = 1.2, cf = 2.6, )) - # Ensure no update message gets produced - assert len(w.comm.messages) == 0 + # Ensure one message gets produced + assert len(w.comm.messages) == (1 if echo else 0) -def test_set_state_cint_to_float(): +def test_set_state_cint_to_float(echo): w = NumberWidget() # Set CInt to float @@ -185,8 +203,8 @@ ci = 5.6 )) # Ensure an update message gets produced - assert len(w.comm.messages) == 1 - msg = w.comm.messages[0] + assert len(w.comm.messages) == (2 if echo else 1) + msg = w.comm.messages[-1] data = msg[1]['data'] assert data['method'] == 'update' assert data['state'] == {'ci': 5} @@ -208,7 +226,7 @@ assert len(w.comm.messages) == 0 -def test_set_state_int_to_float(): +def test_set_state_int_to_float(echo): w = NumberWidget() # Set Int to float @@ -217,7 +235,7 @@ i = 3.5 )) -def test_property_lock(): +def test_property_lock(echo): # when this widget's value is set to 42, it sets itself to 2, and then back to 42 again (and then stops) class AnnoyingWidget(Widget): value = Float().tag(sync=True) @@ -241,13 +259,136 @@ # this mimics a value coming from the front end widget.set_state({'value': 42}) assert widget.value == 42 + assert widget.stop is True + + # we expect no new state to be sent + calls = [] + widget._send.assert_has_calls(calls) + + +def test_hold_sync(echo): + # when this widget's value is set to 42, it sets the value to 2, and also sets a different trait value + class AnnoyingWidget(Widget): + value = Float().tag(sync=True) + other = Float().tag(sync=True) + + @observe('value') + def _propagate_value(self, change): + print('_propagate_value', change.new) + if change.new == 42: + with self.hold_sync(): + self.value = 2 + self.other = 11 - # we expect first the {'value': 2.0} state to be send, followed by the {'value': 42.0} state - msg = {'method': 'update', 'state': {'value': 2.0}, 'buffer_paths': []} + widget = AnnoyingWidget(value=1) + assert widget.value == 1 + + widget._send = mock.MagicMock() + # this mimics a value coming from the front end + widget.set_state({'value': 42}) + assert widget.value == 2 + assert widget.other == 11 + + msg = {'method': 'echo_update', 'state': {'value': 42.0}, 'buffer_paths': []} + call42 = mock.call(msg, buffers=[]) + + msg = {'method': 'update', 'state': {'value': 2.0, 'other': 11.0}, 'buffer_paths': []} call2 = mock.call(msg, buffers=[]) - msg = {'method': 'update', 'state': {'value': 42.0}, 'buffer_paths': []} + calls = [call42, call2] if echo else [call2] + widget._send.assert_has_calls(calls) + + +def test_echo(echo): + # we always echo values back to the frontend if configured + class ValueWidget(Widget): + value = Float().tag(sync=True) + + widget = ValueWidget(value=1) + assert widget.value == 1 + + widget._send = mock.MagicMock() + # this mimics a state coming from the front end + widget.set_state({'value': 42, 'unexpected_field': 43}) + assert widget.value == 42 + + # we expect this to be echoed + msg = {'method': 'echo_update', 'state': {'value': 42.0}, 'buffer_paths': []} call42 = mock.call(msg, buffers=[]) - calls = [call2, call42] + calls = [call42] if echo else [] + widget._send.assert_has_calls(calls) + + + +def test_echo_single(echo): + # we always echo multiple changes back in 1 update + class ValueWidget(Widget): + value = Float().tag(sync=True) + square = Float().tag(sync=True) + @observe('value') + def _square(self, change): + self.square = self.value**2 + + widget = ValueWidget(value=1) + assert widget.value == 1 + + widget._send = mock.MagicMock() + # this mimics a value coming from the front end + widget._handle_msg({ + 'content': { + 'data': { + 'method': 'update', + 'state': { + 'value': 8, + } + } + } + }) + assert widget.value == 8 + assert widget.square == 64 + + # we expect this to be echoed + # note that only value is echoed, not square + msg = {'method': 'echo_update', 'state': {'value': 8.0}, 'buffer_paths': []} + call = mock.call(msg, buffers=[]) + + msg = {'method': 'update', 'state': {'square': 64}, 'buffer_paths': []} + call2 = mock.call(msg, buffers=[]) + + + calls = [call, call2] if echo else [call2] widget._send.assert_has_calls(calls) + + +def test_no_echo(echo): + # in cases where values coming from the frontend are 'heavy', we might want to opt out + class ValueWidget(Widget): + value = Float().tag(sync=True, echo_update=False) + + widget = ValueWidget(value=1) + assert widget.value == 1 + + widget._send = mock.MagicMock() + # this mimics a value coming from the front end + widget._handle_msg({ + 'content': { + 'data': { + 'method': 'update', + 'state': { + 'value': 42, + } + } + } + }) + assert widget.value == 42 + + # widget._send.assert_not_called(calls) + widget._send.assert_not_called() + + # a regular set should sync to the frontend + widget.value = 43 + widget._send.assert_has_calls([mock.call({'method': 'update', 'state': {'value': 43.0}, 'buffer_paths': []}, buffers=[])]) + + + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/ipywidgets/widgets/widget.py new/ipywidgets-7.7.1/ipywidgets/widgets/widget.py --- old/ipywidgets-7.6.5/ipywidgets/widgets/widget.py 2021-09-14 01:30:14.916297400 +0200 +++ new/ipywidgets-7.7.1/ipywidgets/widgets/widget.py 2022-06-22 19:32:54.806524500 +0200 @@ -7,6 +7,7 @@ in the IPython notebook front-end. """ +import os from contextlib import contextmanager try: from collections.abc import Iterable @@ -25,8 +26,27 @@ from base64 import standard_b64encode -from .._version import __protocol_version__, __jupyter_widgets_base_version__ +from .._version import __protocol_version__, __control_protocol_version__, __jupyter_widgets_base_version__ + + +# Based on jupyter_core.paths.envset +def envset(name, default): + """Return True if the given environment variable is turned on, otherwise False + If the environment variable is set, True will be returned if it is assigned to a value + other than 'no', 'n', 'false', 'off', '0', or '0.0' (case insensitive). + If the environment variable is not set, the default value is returned. + """ + if name in os.environ: + return os.environ[name].lower() not in ['no', 'n', 'false', 'off', '0', '0.0'] + else: + return bool(default) + + + + PROTOCOL_VERSION_MAJOR = __protocol_version__.split('.')[0] +CONTROL_PROTOCOL_VERSION_MAJOR = __control_protocol_version__.split('.')[0] +JUPYTER_WIDGETS_ECHO = envset('JUPYTER_WIDGETS_ECHO', default=False) def _widget_to_json(x, obj): if isinstance(x, dict): @@ -290,6 +310,7 @@ # Class attributes #------------------------------------------------------------------------- _widget_construction_callback = None + _control_comm = None # widgets is a dictionary of all active widget objects widgets = {} @@ -302,7 +323,6 @@ for widget in list(cls.widgets.values()): widget.close() - @staticmethod def on_widget_constructed(callback): """Registers a callback to be called when a widget is constructed. @@ -317,6 +337,51 @@ if Widget._widget_construction_callback is not None and callable(Widget._widget_construction_callback): Widget._widget_construction_callback(widget) + @classmethod + def handle_control_comm_opened(cls, comm, msg): + """ + Class method, called when the comm-open message on the + "jupyter.widget.control" comm channel is received + """ + version = msg.get('metadata', {}).get('version', '') + if version.split('.')[0] != CONTROL_PROTOCOL_VERSION_MAJOR: + raise ValueError("Incompatible widget control protocol versions: received version %r, expected version %r"%(version, __control_protocol_version__)) + + cls._control_comm = comm + cls._control_comm.on_msg(cls._handle_control_comm_msg) + + @classmethod + def _handle_control_comm_msg(cls, msg): + # This shouldn't happen unless someone calls this method manually + if cls._control_comm is None: + raise RuntimeError('Control comm has not been properly opened') + + data = msg['content']['data'] + method = data['method'] + + if method == 'request_states': + # Send back the full widgets state + cls.get_manager_state() + widgets = cls.widgets.values() + full_state = {} + drop_defaults = False + for widget in widgets: + full_state[widget.model_id] = { + 'model_name': widget._model_name, + 'model_module': widget._model_module, + 'model_module_version': widget._model_module_version, + 'state': widget.get_state(drop_defaults=drop_defaults), + } + full_state, buffer_paths, buffers = _remove_buffers(full_state) + cls._control_comm.send(dict( + method='update_states', + states=full_state, + buffer_paths=buffer_paths + ), buffers=buffers) + + else: + raise RuntimeError('Unknown front-end to back-end widget control msg with method "%s"' % method) + @staticmethod def handle_comm_opened(comm, msg): """Static method, called when a widget is constructed.""" @@ -534,6 +599,21 @@ def set_state(self, sync_data): """Called when a state is received from the front-end.""" + # Send an echo update message immediately + if JUPYTER_WIDGETS_ECHO: + echo_state = {} + for attr, value in sync_data.items(): + if attr in self.keys and self.trait_metadata(attr, 'echo_update', default=True): + echo_state[attr] = value + if echo_state: + echo_state, echo_buffer_paths, echo_buffers = _remove_buffers(echo_state) + msg = { + 'method': 'echo_update', + 'state': echo_state, + 'buffer_paths': echo_buffer_paths, + } + self._send(msg, buffers=echo_buffers) + # The order of these context managers is important. Properties must # be locked when the hold_trait_notification context manager is # released and notifications are fired. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/ipywidgets/widgets/widget_upload.py new/ipywidgets-7.7.1/ipywidgets/widgets/widget_upload.py --- old/ipywidgets-7.6.5/ipywidgets/widgets/widget_upload.py 2021-09-14 01:30:14.920732700 +0200 +++ new/ipywidgets-7.7.1/ipywidgets/widgets/widget_upload.py 2022-06-22 19:32:54.808712200 +0200 @@ -45,7 +45,7 @@ style = InstanceDict(ButtonStyle).tag(sync=True, **widget_serialization) metadata = List(Dict(), help='List of file metadata').tag(sync=True) data = List(Bytes(), help='List of file content (bytes)').tag( - sync=True, from_json=content_from_json + sync=True, echo_update=False, from_json=content_from_json ) error = Unicode(help='Error message').tag(sync=True) value = Dict(read_only=True) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/package.json new/ipywidgets-7.7.1/package.json --- old/ipywidgets-7.6.5/package.json 2021-09-14 01:30:14.924390300 +0200 +++ new/ipywidgets-7.7.1/package.json 2022-06-22 19:32:54.810718800 +0200 @@ -12,7 +12,7 @@ "clean": "lerna run clean", "integrity": "node scripts/package-integrity.js", "lint": "lerna run lint", - "publish": "yarn run clean && yarn run build && lerna publish -m \"Publish npm packages\"", + "publish": "yarn run clean && yarn run build && lerna publish -m \"Publish npm packages\" --pre-dist-tag next", "update-dependency": "update-dependency --lerna", "updated": "lerna updated" }, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ipywidgets-7.6.5/setup.py new/ipywidgets-7.7.1/setup.py --- old/ipywidgets-7.6.5/setup.py 2021-09-14 01:30:14.964580800 +0200 +++ new/ipywidgets-7.7.1/setup.py 2022-06-22 19:32:54.825371000 +0200 @@ -113,14 +113,11 @@ 'ipykernel>=4.5.1', 'ipython_genutils~=0.2.0', 'traitlets>=4.3.1', - # Requiring nbformat to specify bugfix version which is not required by - # notebook. - 'nbformat>=4.2.0', # TODO: Dynamically add this dependency # only if notebook 4.x is installed in this # interpreter, to allow ipywidgets to be # installed on bare kernels. - 'widgetsnbextension~=3.5.0' + 'widgetsnbextension~=3.6.0' ] extras_require = setuptools_args['extras_require'] = {