Hello community, here is the log from the commit of package python-dash for openSUSE:Factory checked in at 2020-02-03 11:13:26 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-dash (Old) and /work/SRC/openSUSE:Factory/.python-dash.new.26092 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-dash" Mon Feb 3 11:13:26 2020 rev:4 rq:768873 version:1.8.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-dash/python-dash.changes 2019-12-07 15:09:21.923847018 +0100 +++ /work/SRC/openSUSE:Factory/.python-dash.new.26092/python-dash.changes 2020-02-03 11:13:31.765851334 +0100 @@ -1,0 +2,12 @@ +Thu Jan 30 19:09:44 UTC 2020 - Todd R <[email protected]> + +- Update to version 1.8.0 + + Added + * Two new functions to simplify usage handling URLs and pathnames: `app.get_relative_path` & `app.trim_relative_path`. + + Changed + * Simplify our build process. + * Error messages when providing an incorrect property to a component have been improved: they now specify the component type, library, version, and ID (if available). + + Fixed + * Fix no_update test to allow copies, such as those stored and retrieved from a cache. + +------------------------------------------------------------------- Old: ---- dash-1.7.0.tar.gz New: ---- dash-1.8.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-dash.spec ++++++ --- /var/tmp/diff_new_pack.7pm3gx/_old 2020-02-03 11:13:33.293852107 +0100 +++ /var/tmp/diff_new_pack.7pm3gx/_new 2020-02-03 11:13:33.317852119 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-dash # -# Copyright (c) 2018 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 @@ -19,14 +19,12 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-dash -Version: 1.7.0 +Version: 1.8.0 Release: 0 -# For the license file -%define tag ff93d2c4331a576b445be87bb3b77576f18b030a Summary: Python framework for building reactive web-apps License: MIT Group: Development/Languages/Python -Url: https://plot.ly/dash +URL: https://github.com/plotly/dash Source: https://files.pythonhosted.org/packages/source/d/dash/dash-%{version}.tar.gz BuildRequires: %{python_module setuptools} BuildRequires: python-rpm-macros ++++++ dash-1.7.0.tar.gz -> dash-1.8.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/PKG-INFO new/dash-1.8.0/PKG-INFO --- old/dash-1.7.0/PKG-INFO 2019-11-27 21:30:20.000000000 +0100 +++ new/dash-1.8.0/PKG-INFO 2020-01-14 19:23:01.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: dash -Version: 1.7.0 +Version: 1.8.0 Summary: A Python framework for building reactive web-apps. Developed by Plotly. Home-page: https://plot.ly/dash Author: Chris Parmer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash/_utils.py new/dash-1.8.0/dash/_utils.py --- old/dash-1.7.0/dash/_utils.py 2019-10-29 17:47:24.000000000 +0100 +++ new/dash-1.8.0/dash/_utils.py 2020-01-14 19:12:44.000000000 +0100 @@ -10,6 +10,7 @@ from io import open # pylint: disable=redefined-builtin from functools import wraps import future.utils as utils +from . import exceptions logger = logging.getLogger() @@ -54,6 +55,49 @@ ) +def get_relative_path(requests_pathname, path): + if requests_pathname == '/' and path == '': + return '/' + elif requests_pathname != '/' and path == '': + return requests_pathname + elif not path.startswith('/'): + raise exceptions.UnsupportedRelativePath( + "Paths that aren't prefixed with a leading / are not supported.\n" + + "You supplied: {}".format(path) + ) + return "/".join( + [ + requests_pathname.rstrip("/"), + path.lstrip("/") + ] + ) + +def strip_relative_path(requests_pathname, path): + if path is None: + return None + elif ((requests_pathname != '/' and + not path.startswith(requests_pathname.rstrip('/'))) + or (requests_pathname == '/' and not path.startswith('/'))): + raise exceptions.UnsupportedRelativePath( + "Paths that aren't prefixed with a leading " + + "requests_pathname_prefix are not supported.\n" + + "You supplied: {} and requests_pathname_prefix was {}".format( + path, + requests_pathname + ) + ) + if (requests_pathname != '/' and + path.startswith(requests_pathname.rstrip('/'))): + path = path.replace( + # handle the case where the path might be `/my-dash-app` + # but the requests_pathname_prefix is `/my-dash-app/` + requests_pathname.rstrip('/'), + '', + 1 + ) + return path.strip('/') + + # pylint: disable=no-member def patch_collections_abc(member): return getattr(collections if utils.PY2 else collections.abc, member) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash/dash.py new/dash-1.8.0/dash/dash.py --- old/dash-1.7.0/dash/dash.py 2019-11-27 21:24:11.000000000 +0100 +++ new/dash-1.8.0/dash/dash.py 2020-01-14 19:12:44.000000000 +0100 @@ -36,6 +36,8 @@ from . import _watch from ._utils import get_asset_path as _get_asset_path from ._utils import create_callback_id as _create_callback_id +from ._utils import get_relative_path as _get_relative_path +from ._utils import strip_relative_path as _strip_relative_path from ._configs import get_combined_config, pathname_configs from .version import __version__ @@ -1357,7 +1359,7 @@ has_update = False for i, o in enumerate(output): val = output_value[i] - if val is not no_update: + if not isinstance(val, _NoUpdate): has_update = True o_id, o_prop = o.component_id, o.component_property component_ids[o_id][o_prop] = val @@ -1367,7 +1369,7 @@ response = {"response": component_ids, "multi": True} else: - if output_value is no_update: + if isinstance(output_value, _NoUpdate): raise exceptions.PreventUpdate response = { @@ -1565,6 +1567,102 @@ return asset + def get_relative_path(self, path): + """ + Return a path with `requests_pathname_prefix` prefixed before it. + Use this function when specifying local URL paths that will work + in environments regardless of what `requests_pathname_prefix` is. + In some deployment environments, like Dash Enterprise, + `requests_pathname_prefix` is set to the application name, + e.g. `my-dash-app`. + When working locally, `requests_pathname_prefix` might be unset and + so a relative URL like `/page-2` can just be `/page-2`. + However, when the app is deployed to a URL like `/my-dash-app`, then + `app.get_relative_path('/page-2')` will return `/my-dash-app/page-2`. + This can be used as an alternative to `get_asset_url` as well with + `app.get_relative_path('/assets/logo.png')` + + Use this function with `app.strip_relative_path` in callbacks that + deal with `dcc.Location` `pathname` routing. + That is, your usage may look like: + ``` + app.layout = html.Div([ + dcc.Location(id='url'), + html.Div(id='content') + ]) + @app.callback(Output('content', 'children'), [Input('url', 'pathname')]) + def display_content(path): + page_name = app.strip_relative_path(path) + if not page_name: # None or '' + return html.Div([ + dcc.Link(href=app.get_relative_path('/page-1')), + dcc.Link(href=app.get_relative_path('/page-2')), + ]) + elif page_name == 'page-1': + return chapters.page_1 + if page_name == "page-2": + return chapters.page_2 + ``` + """ + asset = _get_relative_path( + self.config.requests_pathname_prefix, + path, + ) + + return asset + + def strip_relative_path(self, path): + """ + Return a path with `requests_pathname_prefix` and leading and trailing + slashes stripped from it. Also, if None is passed in, None is returned. + Use this function with `get_relative_path` in callbacks that deal + with `dcc.Location` `pathname` routing. + That is, your usage may look like: + ``` + app.layout = html.Div([ + dcc.Location(id='url'), + html.Div(id='content') + ]) + @app.callback(Output('content', 'children'), [Input('url', 'pathname')]) + def display_content(path): + page_name = app.strip_relative_path(path) + if not page_name: # None or '' + return html.Div([ + dcc.Link(href=app.get_relative_path('/page-1')), + dcc.Link(href=app.get_relative_path('/page-2')), + ]) + elif page_name == 'page-1': + return chapters.page_1 + if page_name == "page-2": + return chapters.page_2 + ``` + Note that `chapters.page_1` will be served if the user visits `/page-1` + _or_ `/page-1/` since `strip_relative_path` removes the trailing slash. + + Also note that `strip_relative_path` is compatible with + `get_relative_path` in environments where `requests_pathname_prefix` set. + In some deployment environments, like Dash Enterprise, + `requests_pathname_prefix` is set to the application name, e.g. `my-dash-app`. + When working locally, `requests_pathname_prefix` might be unset and + so a relative URL like `/page-2` can just be `/page-2`. + However, when the app is deployed to a URL like `/my-dash-app`, then + `app.get_relative_path('/page-2')` will return `/my-dash-app/page-2` + + The `pathname` property of `dcc.Location` will return '`/my-dash-app/page-2`' + to the callback. + In this case, `app.strip_relative_path('/my-dash-app/page-2')` + will return `'page-2'` + + For nested URLs, slashes are still included: + `app.strip_relative_path('/page-1/sub-page-1/')` will return + `page-1/sub-page-1` + ``` + """ + return _strip_relative_path( + self.config.requests_pathname_prefix, + path, + ) + def _setup_dev_tools(self, **kwargs): debug = kwargs.get("debug", False) dev_tools = self._dev_tools = _AttributeDict() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash/development/_r_components_generation.py new/dash-1.8.0/dash/development/_r_components_generation.py --- old/dash-1.7.0/dash/development/_r_components_generation.py 2019-10-18 16:15:07.000000000 +0200 +++ new/dash-1.8.0/dash/development/_r_components_generation.py 2020-01-14 19:12:44.000000000 +0100 @@ -46,14 +46,14 @@ file = "deps"), meta = NULL, script = {script_name}, stylesheet = {css_name}, head = NULL, attachment = NULL, package = "{rpkgname}", -all_files = FALSE), class = "html_dependency")""" # noqa:E501 +all_files = FALSE{async_or_dynamic}), class = "html_dependency")""" # noqa:E501 frame_body_template = """`{project_shortname}` = structure(list(name = "{project_shortname}", version = "{project_ver}", src = list(href = NULL, file = "deps"), meta = NULL, script = {script_name}, stylesheet = {css_name}, head = NULL, attachment = NULL, package = "{rpkgname}", -all_files = FALSE), class = "html_dependency")""" # noqa:E501 +all_files = FALSE{async_or_dynamic}), class = "html_dependency")""" # noqa:E501 frame_close_template = """) return(deps_metadata) @@ -81,9 +81,8 @@ """ description_template = """Package: {package_name} -Title: {package_description} +Title: {package_title} Version: {package_version} -Authors @R: as.person(c({package_author})) Description: {package_description} Depends: R (>= 3.0.2){package_depends} Imports: {package_imports} @@ -92,7 +91,8 @@ URL: {package_url} BugReports: {package_issues} Encoding: UTF-8 -LazyData: true +LazyData: true{vignette_builder} +KeepSource: true Author: {package_author_no_email} Maintainer: {maintainer} """ @@ -276,18 +276,23 @@ # pylint: disable=consider-using-enumerate if len(alldist) > 1: for dep in range(len(alldist)): - rpp = alldist[dep]["relative_package_path"] + curr_dep = alldist[dep] + rpp = curr_dep["relative_package_path"] + + async_or_dynamic = get_async_type(curr_dep) + if "dash_" in rpp: dep_name = rpp.split(".")[0] else: dep_name = "{}".format(project_shortname) - project_ver = str(dep) + if "css" in rpp: css_name = "'{}'".format(rpp) script_name = 'NULL' else: script_name = "'{}'".format(rpp) css_name = 'NULL' + function_frame += [ frame_element_template.format( dep_name=dep_name, @@ -296,23 +301,30 @@ project_shortname=project_shortname, script_name=script_name, css_name=css_name, + async_or_dynamic=async_or_dynamic, ) ] function_frame_body = ",\n".join(function_frame) elif len(alldist) == 1: - rpp = alldist[0]["relative_package_path"] + dep = alldist[0] + rpp = dep["relative_package_path"] + + async_or_dynamic = get_async_type(dep) + if "css" in rpp: css_name = "'{}'".format(rpp) script_name = "NULL" else: script_name = "'{}'".format(rpp) css_name = "NULL" + function_frame_body = frame_body_template.format( project_shortname=project_shortname, project_ver=project_ver, rpkgname=rpkgname, script_name=script_name, css_name=css_name, + async_or_dynamic=async_or_dynamic, ) function_string = "".join( @@ -322,6 +334,24 @@ return function_string +# determine whether dependency uses async or dynamic flag +# then return the properly formatted string if so, i.e. +# " async = TRUE,". a dependency can have async or +# dynamic elements, neither of these, but never both. +def get_async_type(dep): + async_or_dynamic = "" + for key in dep.keys(): + if key in ['async', 'dynamic']: + keyval = dep[key] + if not isinstance(keyval, bool): + keyval = "'{}'".format(keyval.lower()) + else: + keyval = str(keyval).upper() + async_or_dynamic = \ + ", {} = {}".format(key, keyval) + return async_or_dynamic + + # This method wraps code within arbitrary LaTeX-like tags, which are used # by R's internal help parser for constructing man pages def wrap(tag, code): @@ -369,6 +399,15 @@ for p in prop_keys ) + # auto-replace any unescaped backslashes for compatibility with R docs + description = re.sub(r"(?<!\\)%", "\\%", description) + item_text = re.sub(r"(?<!\\)%", "\\%", item_text) + + # scrub examples which begin with **Example Usage**, as these should be + # provided as R code within dash-info.yaml + if "**Example Usage**" in description: + description = description.split("**Example Usage**")[0].rstrip() + if any(key.endswith("-*") for key in prop_keys): default_argtext += ', ...' item_text += wildcard_help_template.format(get_wildcards_r(prop_keys)) @@ -400,6 +439,7 @@ fa.write(result + '\n') +# pylint: disable=too-many-arguments def write_class_file(name, props, description, @@ -509,7 +549,21 @@ package_name = snake_case_to_camel_case(project_shortname) lib_name = pkg_data.get("name") - package_description = pkg_data.get("description", "") + + if rpkg_data is not None: + if rpkg_data.get("pkg_help_title"): + package_title = rpkg_data.get("pkg_help_title", + pkg_data.get("description", + "")) + if rpkg_data.get("pkg_help_description"): + package_description = rpkg_data.get("pkg_help_description", + pkg_data.get("description", + "")) + else: + # fall back to using description in package.json, if present + package_title = pkg_data.get("description", "") + package_description = pkg_data.get("description", "") + package_version = pkg_data.get("version", "0.0.1") # remove leading and trailing commas @@ -547,6 +601,16 @@ maintainer = pkg_data.get("maintainer", pkg_data.get("author")) + if "<" not in package_author or "<" not in maintainer: + print( + "Error, aborting R package generation: " + "R packages require a properly formatted author or " + "maintainer field or installation will fail. Please include " + "an email address enclosed within < > brackets in package.json. ", + file=sys.stderr, + ) + sys.exit(1) + if not (os.path.isfile("LICENSE") or os.path.isfile("LICENSE.txt")): package_license = pkg_data.get("license", "") else: @@ -565,6 +629,14 @@ for rpackage in rpackage_list: packages_string += "\nimport({})\n".format(rpackage) + if os.path.exists("vignettes"): + vignette_builder = "\nVignetteBuilder: knitr" + if "knitr" not in package_suggests and \ + "rmarkdown" not in package_suggests: + package_suggests += ", knitr, rmarkdown".lstrip(", ") + else: + vignette_builder = "" + pkghelp_stub_path = os.path.join("man", package_name + "-package.Rd") # generate the internal (not exported to the user) functions which @@ -582,6 +654,7 @@ description_string = description_template.format( package_name=package_name, + package_title=package_title, package_description=package_description, package_version=package_version, package_author=package_author, @@ -591,6 +664,7 @@ package_license=package_license, package_url=package_url, package_issues=package_issues, + vignette_builder=vignette_builder, package_author_no_email=package_author_no_email, maintainer=maintainer, ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash/development/base_component.py new/dash-1.8.0/dash/development/base_component.py --- old/dash-1.7.0/dash/development/base_component.py 2019-11-27 21:24:11.000000000 +0100 +++ new/dash-1.8.0/dash/development/base_component.py 2020-01-14 19:12:44.000000000 +0100 @@ -86,18 +86,38 @@ k_in_wildcards = any( [k.startswith(w) for w in self._valid_wildcard_attributes] ) + # e.g. "The dash_core_components.Dropdown component (version 1.6.0) + # with the ID "my-dropdown" + try: + error_string_prefix = 'The `{}.{}` component (version {}){}'.format( + self._namespace, + self._type, + getattr(__import__(self._namespace), '__version__', 'unknown'), + ' with the ID "{}"'.format(kwargs['id']) + if 'id' in kwargs else '' + ) + except ImportError: + # Our tests create mock components with libraries that + # aren't importable + error_string_prefix = 'The `{}` component{}'.format( + self._type, + ' with the ID "{}"'.format(kwargs['id']) + if 'id' in kwargs else '' + ) + if not k_in_propnames and not k_in_wildcards: raise TypeError( - "Unexpected keyword argument `{}`".format(k) - + "\nAllowed arguments: {}".format( - # pylint: disable=no-member + "{} received an unexpected keyword argument: `{}`".format( + error_string_prefix, k + ) + "\nAllowed arguments: {}".format( # pylint: disable=no-member ", ".join(sorted(self._prop_names)) ) ) if k != "children" and isinstance(v, Component): raise TypeError( - "Component detected as a prop other than `children`\n" + + error_string_prefix + + " detected a Component for a prop other than `children`\n" + "Did you forget to wrap multiple `children` in an array?\n" + "Prop {} has value {}\n".format(k, repr(v)) ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash/exceptions.py new/dash-1.8.0/dash/exceptions.py --- old/dash-1.7.0/dash/exceptions.py 2019-06-21 20:11:29.000000000 +0200 +++ new/dash-1.8.0/dash/exceptions.py 2020-01-14 19:12:44.000000000 +0100 @@ -98,3 +98,7 @@ class MissingCallbackContextException(CallbackException): pass + + +class UnsupportedRelativePath(CallbackException): + pass diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash/version.py new/dash-1.8.0/dash/version.py --- old/dash-1.7.0/dash/version.py 2019-11-27 21:24:11.000000000 +0100 +++ new/dash-1.8.0/dash/version.py 2020-01-14 19:12:44.000000000 +0100 @@ -1 +1 @@ -__version__ = '1.7.0' +__version__ = '1.8.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash.egg-info/PKG-INFO new/dash-1.8.0/dash.egg-info/PKG-INFO --- old/dash-1.7.0/dash.egg-info/PKG-INFO 2019-11-27 21:30:20.000000000 +0100 +++ new/dash-1.8.0/dash.egg-info/PKG-INFO 2020-01-14 19:23:01.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: dash -Version: 1.7.0 +Version: 1.8.0 Summary: A Python framework for building reactive web-apps. Developed by Plotly. Home-page: https://plot.ly/dash Author: Chris Parmer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/dash.egg-info/requires.txt new/dash-1.8.0/dash.egg-info/requires.txt --- old/dash-1.7.0/dash.egg-info/requires.txt 2019-11-27 21:30:20.000000000 +0100 +++ new/dash-1.8.0/dash.egg-info/requires.txt 2020-01-14 19:23:01.000000000 +0100 @@ -1,10 +1,10 @@ Flask>=1.0.2 flask-compress plotly -dash_renderer==1.2.2 -dash-core-components==1.6.0 +dash_renderer==1.2.3 +dash-core-components==1.7.0 dash-html-components==1.0.2 -dash-table==4.5.1 +dash-table==4.6.0 future [dev] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/dash-1.7.0/requires-install.txt new/dash-1.8.0/requires-install.txt --- old/dash-1.7.0/requires-install.txt 2019-11-27 21:24:21.000000000 +0100 +++ new/dash-1.8.0/requires-install.txt 2020-01-14 19:16:58.000000000 +0100 @@ -1,8 +1,8 @@ Flask>=1.0.2 flask-compress plotly -dash_renderer==1.2.2 -dash-core-components==1.6.0 +dash_renderer==1.2.3 +dash-core-components==1.7.0 dash-html-components==1.0.2 -dash-table==4.5.1 +dash-table==4.6.0 future \ No newline at end of file
