Hello community,

here is the log from the commit of package python-CherryPy for openSUSE:Factory 
checked in at 2020-05-04 18:32:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-CherryPy (Old)
 and      /work/SRC/openSUSE:Factory/.python-CherryPy.new.2738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-CherryPy"

Mon May  4 18:32:49 2020 rev:27 rq:799973 version:18.6.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-CherryPy/python-CherryPy.changes  
2020-03-08 22:23:04.080037870 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-CherryPy.new.2738/python-CherryPy.changes    
    2020-05-04 18:33:15.900164970 +0200
@@ -1,0 +2,6 @@
+Mon May  4 06:56:30 UTC 2020 - Johannes Grassler <[email protected]>
+
+- update to 18.6.0
+  * Add support for UTF-8 encoded attachment
+
+-------------------------------------------------------------------

Old:
----
  CherryPy-18.5.0.tar.gz

New:
----
  CherryPy-18.6.0.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-CherryPy.spec ++++++
--- /var/tmp/diff_new_pack.WeqOrZ/_old  2020-05-04 18:33:17.948169119 +0200
+++ /var/tmp/diff_new_pack.WeqOrZ/_new  2020-05-04 18:33:17.952169128 +0200
@@ -19,7 +19,7 @@
 %define skip_python2 1
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-CherryPy
-Version:        18.5.0
+Version:        18.6.0
 Release:        0
 Summary:        Object-Oriented HTTP framework
 License:        BSD-3-Clause

++++++ CherryPy-18.5.0.tar.gz -> CherryPy-18.6.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/.gitignore 
new/CherryPy-18.6.0/.gitignore
--- old/CherryPy-18.5.0/.gitignore      2019-11-27 17:12:08.000000000 +0100
+++ new/CherryPy-18.6.0/.gitignore      2020-04-17 20:29:06.000000000 +0200
@@ -43,3 +43,18 @@
 /graph_AppResponse_*.png
 /graph_Response_*.png
 /graph_Request_*.png
+
+# Covers JetBrains IDEs: IntelliJ, PyCharm
+# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
+
+# User-specific stuff
+.idea/
+
+# IntelliJ
+out/
+
+# mpeltonen/sbt-idea plugin
+.idea_modules/
+
+# Editor-based Rest Client
+.idea/httpRequests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/.yamllint 
new/CherryPy-18.6.0/.yamllint
--- old/CherryPy-18.5.0/.yamllint       1970-01-01 01:00:00.000000000 +0100
+++ new/CherryPy-18.6.0/.yamllint       2020-04-17 20:29:06.000000000 +0200
@@ -0,0 +1,2 @@
+indentation:
+  indent-sequences: false
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/.zuul.yaml 
new/CherryPy-18.6.0/.zuul.yaml
--- old/CherryPy-18.5.0/.zuul.yaml      1970-01-01 01:00:00.000000000 +0100
+++ new/CherryPy-18.6.0/.zuul.yaml      2020-04-17 20:29:06.000000000 +0200
@@ -0,0 +1,78 @@
+---
+- job:
+    name: tox-build-docs
+    parent: tox
+    vars:
+      tox_envlist: build-docs
+
+- job:
+    name: tox-dist-check
+    parent: tox
+    vars:
+      tox_envlist: dist-check
+
+- job:
+    name: tox-pre-commit
+    parent: tox
+    vars:
+      tox_envlist: pre-commit
+
+- job:
+    name: tox-pre-commit-pep257
+    parent: tox
+    voting: false
+    vars:
+      tox_envlist: pre-commit-pep257
+
+- job:
+    name: tox-py27-setup-check
+    vars:
+      tox_envlist: setup-check
+      python_version: 2.7
+      python_use_pyenv: false
+    parent: tox
+
+- job:
+    name: tox-py35-setup-check
+    vars:
+      tox_envlist: setup-check
+      python_version: 3.5
+      python_use_pyenv: true
+    parent: tox
+
+- job:
+    name: tox-py36-setup-check
+    vars:
+      tox_envlist: setup-check
+      python_version: 3.6
+      python_use_pyenv: true
+    parent: tox
+
+- job:
+    name: tox-py37-setup-check
+    vars:
+      tox_envlist: setup-check
+      python_version: 3.7
+      python_use_pyenv: false
+    parent: tox
+
+- job:
+    name: tox-py38-setup-check
+    vars:
+      tox_envlist: setup-check
+      python_version: 3.8
+      python_use_pyenv: true
+    parent: tox
+
+- project:
+    check:
+      jobs:
+      - tox-build-docs
+      - tox-dist-check
+      - tox-pre-commit
+      - tox-pre-commit-pep257
+      - tox-py27-setup-check
+      - tox-py35-setup-check
+      - tox-py36-setup-check
+      - tox-py37-setup-check
+      - tox-py38-setup-check
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/CHANGES.rst 
new/CherryPy-18.6.0/CHANGES.rst
--- old/CherryPy-18.5.0/CHANGES.rst     2019-11-27 17:12:08.000000000 +0100
+++ new/CherryPy-18.6.0/CHANGES.rst     2020-04-17 20:29:06.000000000 +0200
@@ -1,3 +1,9 @@
+v18.6.0
+-------
+
+* :issue:`1776` via :pr:`1851`: Add support for UTF-8 encoded attachment
+  file names in ``Content-Disposition`` header via :rfc:`6266#appendix-D`.
+
 v18.5.0
 -------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/CherryPy.egg-info/PKG-INFO 
new/CherryPy-18.6.0/CherryPy.egg-info/PKG-INFO
--- old/CherryPy-18.5.0/CherryPy.egg-info/PKG-INFO      2019-11-27 
17:12:34.000000000 +0100
+++ new/CherryPy-18.6.0/CherryPy.egg-info/PKG-INFO      2020-04-17 
20:29:28.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: CherryPy
-Version: 18.5.0
+Version: 18.6.0
 Summary: Object-Oriented HTTP framework
 Home-page: https://www.cherrypy.org
 Author: CherryPy Team
@@ -12,6 +12,7 @@
 Project-URL: Docs: RTD, https://docs.cherrypy.org
 Project-URL: GitHub: issues, https://github.com/cherrypy/cherrypy/issues
 Project-URL: GitHub: repo, https://github.com/cherrypy/cherrypy
+Project-URL: Tidelift: funding, 
https://tidelift.com/subscription/pkg/pypi-cherrypy?utm_source=pypi-cherrypy&utm_medium=referral&utm_campaign=pypi
 Description: .. image:: https://img.shields.io/pypi/v/cherrypy.svg
            :target: https://pypi.org/project/cherrypy
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/CherryPy.egg-info/SOURCES.txt 
new/CherryPy-18.6.0/CherryPy.egg-info/SOURCES.txt
--- old/CherryPy-18.5.0/CherryPy.egg-info/SOURCES.txt   2019-11-27 
17:12:34.000000000 +0100
+++ new/CherryPy-18.6.0/CherryPy.egg-info/SOURCES.txt   2020-04-17 
20:29:28.000000000 +0200
@@ -8,9 +8,12 @@
 .pre-commit-config.yaml
 .readthedocs.yml
 .travis.yml
+.yamllint
+.zuul.yaml
 CHANGES.rst
 LICENSE.md
 README.rst
+bindep.txt
 conftest.py
 pytest.ini
 setup.cfg
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/CherryPy.egg-info/requires.txt 
new/CherryPy-18.6.0/CherryPy.egg-info/requires.txt
--- old/CherryPy-18.5.0/CherryPy.egg-info/requires.txt  2019-11-27 
17:12:34.000000000 +0100
+++ new/CherryPy-18.6.0/CherryPy.egg-info/requires.txt  2020-04-17 
20:29:28.000000000 +0200
@@ -30,7 +30,7 @@
 coverage
 codecov
 objgraph
-pytest>=2.8
+pytest<5.4.0,>=5.3.5
 pytest-cov
 pytest-sugar
 backports.unittest_mock
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/PKG-INFO new/CherryPy-18.6.0/PKG-INFO
--- old/CherryPy-18.5.0/PKG-INFO        2019-11-27 17:12:34.000000000 +0100
+++ new/CherryPy-18.6.0/PKG-INFO        2020-04-17 20:29:28.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: CherryPy
-Version: 18.5.0
+Version: 18.6.0
 Summary: Object-Oriented HTTP framework
 Home-page: https://www.cherrypy.org
 Author: CherryPy Team
@@ -12,6 +12,7 @@
 Project-URL: Docs: RTD, https://docs.cherrypy.org
 Project-URL: GitHub: issues, https://github.com/cherrypy/cherrypy/issues
 Project-URL: GitHub: repo, https://github.com/cherrypy/cherrypy
+Project-URL: Tidelift: funding, 
https://tidelift.com/subscription/pkg/pypi-cherrypy?utm_source=pypi-cherrypy&utm_medium=referral&utm_campaign=pypi
 Description: .. image:: https://img.shields.io/pypi/v/cherrypy.svg
            :target: https://pypi.org/project/cherrypy
         
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/bindep.txt 
new/CherryPy-18.6.0/bindep.txt
--- old/CherryPy-18.5.0/bindep.txt      1970-01-01 01:00:00.000000000 +0100
+++ new/CherryPy-18.6.0/bindep.txt      2020-04-17 20:29:06.000000000 +0200
@@ -0,0 +1,3 @@
+gcc                     [platform:dpkg]
+libenchant1c2a          [platform:dpkg]
+python3-dev             [platform:dpkg]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/cherrypy/lib/static.py 
new/CherryPy-18.6.0/cherrypy/lib/static.py
--- old/CherryPy-18.5.0/cherrypy/lib/static.py  2019-11-27 17:12:08.000000000 
+0100
+++ new/CherryPy-18.6.0/cherrypy/lib/static.py  2020-04-17 20:29:06.000000000 
+0200
@@ -6,6 +6,7 @@
 import stat
 import mimetypes
 import urllib.parse
+import unicodedata
 
 from email.generator import _make_boundary as make_boundary
 from io import UnsupportedOperation
@@ -28,6 +29,30 @@
 _setup_mimetypes()
 
 
+def _make_content_disposition(disposition, file_name):
+    """Create HTTP header for downloading a file with a UTF-8 filename.
+
+    This function implements the recommendations of :rfc:`6266#appendix-D`.
+    See this and related answers: https://stackoverflow.com/a/8996249/2173868.
+    """
+    # As normalization algorithm for `unicodedata` is used composed form (NFC
+    # and NFKC) with compatibility equivalence criteria (NFK), so "NFKC" is the
+    # one. It first applies the compatibility decomposition, followed by the
+    # canonical composition. Should be displayed in the same manner, should be
+    # treated in the same way by applications such as alphabetizing names or
+    # searching, and may be substituted for each other.
+    # See: https://en.wikipedia.org/wiki/Unicode_equivalence.
+    ascii_name = (
+        unicodedata.normalize('NFKC', file_name).
+        encode('ascii', errors='ignore').decode()
+    )
+    header = '{}; filename="{}"'.format(disposition, ascii_name)
+    if ascii_name != file_name:
+        quoted_name = urllib.parse.quote(file_name)
+        header += '; filename*=UTF-8\'\'{}'.format(quoted_name)
+    return header
+
+
 def serve_file(path, content_type=None, disposition=None, name=None,
                debug=False):
     """Set status, headers, and body in order to serve the given path.
@@ -37,9 +62,10 @@
     of the 'path' argument.
 
     If disposition is not None, the Content-Disposition header will be set
-    to "<disposition>; filename=<name>". If name is None, it will be set
-    to the basename of path. If disposition is None, no Content-Disposition
-    header will be written.
+    to "<disposition>; filename=<name>; filename*=utf-8''<name>"
+    as described in :rfc:`6266#appendix-D`.
+    If name is None, it will be set to the basename of path.
+    If disposition is None, no Content-Disposition header will be written.
     """
     response = cherrypy.serving.response
 
@@ -92,7 +118,7 @@
     if disposition is not None:
         if name is None:
             name = os.path.basename(path)
-        cd = '%s; filename="%s"' % (disposition, name)
+        cd = _make_content_disposition(disposition, name)
         response.headers['Content-Disposition'] = cd
     if debug:
         cherrypy.log('Content-Disposition: %r' % cd, 'TOOLS.STATIC')
@@ -111,9 +137,10 @@
     The Content-Type header will be set to the content_type arg, if provided.
 
     If disposition is not None, the Content-Disposition header will be set
-    to "<disposition>; filename=<name>". If name is None, 'filename' will
-    not be set. If disposition is None, no Content-Disposition header will
-    be written.
+    to "<disposition>; filename=<name>; filename*=utf-8''<name>"
+    as described in :rfc:`6266#appendix-D`.
+    If name is None, 'filename' will not be set.
+    If disposition is None, no Content-Disposition header will be written.
 
     CAUTION: If the request contains a 'Range' header, one or more seek()s will
     be performed on the file object.  This may cause undesired behavior if
@@ -149,7 +176,7 @@
         if name is None:
             cd = disposition
         else:
-            cd = '%s; filename="%s"' % (disposition, name)
+            cd = _make_content_disposition(disposition, name)
         response.headers['Content-Disposition'] = cd
     if debug:
         cherrypy.log('Content-Disposition: %r' % cd, 'TOOLS.STATIC')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/cherrypy/test/test_static.py 
new/CherryPy-18.6.0/cherrypy/test/test_static.py
--- old/CherryPy-18.5.0/cherrypy/test/test_static.py    2019-11-27 
17:12:08.000000000 +0100
+++ new/CherryPy-18.6.0/cherrypy/test/test_static.py    2020-04-17 
20:29:06.000000000 +0200
@@ -97,6 +97,20 @@
                 f = io.BytesIO(b'Fee\nfie\nfo\nfum')
                 return static.serve_fileobj(f, content_type='text/plain')
 
+            @cherrypy.expose
+            def serve_file_utf8_filename(self):
+                return static.serve_file(
+                    __file__,
+                    disposition='attachment',
+                    name='has_utf-8_character_☃.html')
+
+            @cherrypy.expose
+            def serve_fileobj_utf8_filename(self):
+                return static.serve_fileobj(
+                    io.BytesIO('☃\nfie\nfo\nfum'.encode('utf-8')),
+                    disposition='attachment',
+                    name='has_utf-8_character_☃.html')
+
         class Static:
 
             @cherrypy.expose
@@ -193,6 +207,22 @@
         #   we just check the content
         self.assertMatchesBody('^Dummy stylesheet')
 
+        # Check a filename with utf-8 characters in it
+        ascii_fn = 'has_utf-8_character_.html'
+        url_quote_fn = 'has_utf-8_character_%E2%98%83.html'  # %E2%98%83 == ☃
+        expected_content_disposition = (
+            'attachment; filename="{!s}"; filename*=UTF-8\'\'{!s}'.
+            format(ascii_fn, url_quote_fn)
+        )
+
+        self.getPage('/serve_file_utf8_filename')
+        self.assertStatus('200 OK')
+        self.assertHeader('Content-Disposition', expected_content_disposition)
+
+        self.getPage('/serve_fileobj_utf8_filename')
+        self.assertStatus('200 OK')
+        self.assertHeader('Content-Disposition', expected_content_disposition)
+
     @pytest.mark.skipif(platform.system() != 'Windows', reason='Windows only')
     def test_static_longpath(self):
         """Test serving of a file in subdir of a Windows long-path
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/pytest.ini 
new/CherryPy-18.6.0/pytest.ini
--- old/CherryPy-18.5.0/pytest.ini      2019-11-27 17:12:08.000000000 +0100
+++ new/CherryPy-18.6.0/pytest.ini      2020-04-17 20:29:06.000000000 +0200
@@ -1,6 +1,36 @@
 [pytest]
-norecursedirs = dist build .tox .eggs
-addopts = --durations=10 -v -rxXs -l 
--junitxml=.test-results/pytest/results.xml --cov=cherrypy --cov-report 
term-missing:skip-covered --cov-report xml --doctest-modules
+addopts =
+    # `pytest-xdist`:
+    #--numprocesses=auto
+
+    # `pytest-mon`:
+    # useful for live testing with `pytest-watch` during development:
+    #--testmon
+
+    # show 10 slowest invocations:
+    --durations=10
+
+    # a bit of verbosity doesn't hurt:
+    -v
+
+    # report all the things == -rxXs:
+    -ra
+
+    # show values of the local vars in errors:
+    --showlocals
+
+    # autocollect and invoke the doctests from all modules:
+    --doctest-modules
+
+    # dump the test results in junit format:
+    --junitxml=.test-results/pytest/results.xml
+
+    # `pytest-cov`:
+    --cov=cherrypy
+    --cov-report term-missing:skip-covered
+    --cov-report xml
+    # --cov-report xml:.test-results/pytest/cov.xml  # alternatively move it 
here
+doctest_optionflags = ALLOW_UNICODE ELLIPSIS
 filterwarnings =
     error
     ignore:Use cheroot.test.webtest:DeprecationWarning
@@ -10,7 +40,18 @@
     # ref: 
https://github.com/mhammond/pywin32/issues/1256#issuecomment-527972824 :
     ignore:the imp module is deprecated in favour of importlib; see the 
module's documentation for alternative uses:DeprecationWarning
     ignore:the imp module is deprecated in favour of importlib; see the 
module's documentation for alternative uses:PendingDeprecationWarning
-doctest_optionflags = ALLOW_UNICODE ELLIPSIS
 junit_duration_report = call
+junit_family = xunit2
 junit_suite_name = cherrypy_test_suite
+minversion = 5.3.5
+norecursedirs =
+    build
+    cherrypy.egg-info
+    dist
+    docs
+    .cache
+    .eggs
+    .git
+    .github
+    .tox
 testpaths = cherrypy/test/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/setup.py new/CherryPy-18.6.0/setup.py
--- old/CherryPy-18.5.0/setup.py        2019-11-27 17:12:08.000000000 +0100
+++ new/CherryPy-18.6.0/setup.py        2020-04-17 20:29:06.000000000 +0200
@@ -49,6 +49,9 @@
         'Docs: RTD': 'https://docs.cherrypy.org',
         'GitHub: issues': '{}/issues'.format(repo_url),
         'GitHub: repo': repo_url,
+        'Tidelift: funding':
+        'https://tidelift.com/subscription/pkg/pypi-cherrypy'
+        '?utm_source=pypi-cherrypy&utm_medium=referral&utm_campaign=pypi',
     },
     packages=[
         'cherrypy', 'cherrypy.lib',
@@ -83,7 +86,11 @@
             # cherrypy.lib.gctools
             'objgraph',
 
-            'pytest>=2.8',
+            # pytest >= 5.4.0 doesn't work with pytest-sugar <= 0.9.2
+            # once https://github.com/Teemu/pytest-sugar/pull/188 is
+            # merged, the upper bound can be removed.
+            # Ref: https://github.com/pytest-dev/pytest/issues/6931
+            'pytest>=5.3.5,<5.4.0',
             'pytest-cov',
             'pytest-sugar',
             'backports.unittest_mock',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/CherryPy-18.5.0/tox.ini new/CherryPy-18.6.0/tox.ini
--- old/CherryPy-18.5.0/tox.ini 2019-11-27 17:12:08.000000000 +0100
+++ new/CherryPy-18.6.0/tox.ini 2020-04-17 20:29:06.000000000 +0200
@@ -31,9 +31,14 @@
 
 [testenv:pre-commit]
 deps =
-    git+https://github.com/yaml/pyyaml@master#egg=pyyaml;python_version=="3.7";
     pre-commit
-commands = pre-commit run --all-files {posargs}
+commands =
+    {envpython} -m pre_commit run --show-diff-on-failure {posargs:--all-files}
+
+    # Print out the advice of how to install pre-commit from this env into Git:
+    -{envpython} -c \
+    'cmd = "{envpython} -m pre_commit install"; scr_width = len(cmd) + 10; sep 
= "=" * scr_width; cmd_str = "    $ " + cmd; '\
+    'print("\n" + sep + "\nTo install pre-commit hooks into the Git repo, 
run:\n\n" + cmd_str + "\n\n" + sep + "\n")'
 
 [testenv:pre-commit-pep257]
 deps = pre-commit
@@ -63,13 +68,17 @@
 # https://github.com/jaraco/rst.linker/issues/7
 # And once all other warnings are gone.
 commands =
-    python -m sphinx \
-      -a -n -j auto \
-      -b html --color \
+    {envpython} -m sphinx \
+      -a \
+      -j auto \
+      -b html \
+      --color \
+      -n \
       -d "{toxinidir}/build/html_docs_doctree" \
-      . "{toxinidir}/build/html"
+      . \
+      "{toxinidir}/build/html"
 
     # Print out the output docs dir and a way to serve html:
-    python -c \
-    'import pathlib; '\
-    'docs_dir = pathlib.Path(r"{toxinidir}") / "build" / "html"; index_file = 
docs_dir / "index.html"; print(f"\nDocumentation available under 
`file://\{index_file\}`\n\nTo serve docs, use `python3 -m http.server 
--directory \{docs_dir\} 0`\n")'
+    -{envpython} -c \
+    'import pathlib; docs_dir = pathlib.Path(r"{toxinidir}") / "build" / 
"html"; index_file = docs_dir / "index.html"; '\
+    'print("\n" + "=" * 120 + f"\n\nDocumentation available under 
`file://\{index_file\}`\n\nTo serve docs, use `python3 -m http.server 
--directory \{docs_dir\} 0`\n\n" + "=" * 120)'


Reply via email to