diff --git a/.gitignore b/.gitignore index 764f6a7..bc1ff1e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ Paste-1.7.5.1.tar.gz /Paste-2.0.2.tar.gz +/Paste-2.0.3.tar.gz diff --git a/python-paste-2.0.2-py3k.patch b/python-paste-2.0.2-py3k.patch deleted file mode 100644 index fbc634a..0000000 --- a/python-paste-2.0.2-py3k.patch +++ /dev/null @@ -1,343 +0,0 @@ -From 125d122b1a0337e657f0ee935a41021986ded722 Mon Sep 17 00:00:00 2001 -From: Nils Philippsen -Date: Wed, 19 Aug 2015 16:32:16 +0200 -Subject: [PATCH] Python 3: various fixes - -* App must always return binary type. Fixes - tests.test_wsgiwrappers.test_wsgirequest_charset. - -* Always encode params if passed as text types. Fixes - tests.test_wsgiwrappers.test_wsgirequest_charset. - -* Don't mangle strangely encoded input. In Python 3, cgi.FieldStorage - needs to know about encodings like shiftjis in order to decode it - properly (in Python 2 it's simply not decoded at all). Fixes - tests.test_wsgiwrappers.test_wsgirequest_charset - -* Use the same python interpreter for CGI scripts. Fixes - tests.test_cgiapp. - -* Add workarounds for cgi.FieldStorage. It keeps some keys as str, some - as the repr() of the byte-encoded key, duh. Fixes (well...): - tests.test_cgiapp.test_form. - -* Avoid spurious warnings. The dict.has_keys() method doesn't exist - anymore in python 3, check if the locals() object has a .keys() method - instead. - -* dict.items() doesn't return a list anymore. Use sorted() instead, - which works on lists as well as dict_items objects. - -* Ignore exception details in doctests. Exception details are formatted - differently between Python 2 and 3. - -* Let html_quote() and url() always return the same type. Mixing binary - and text types causes errors later on. - -* Use compatible print syntax in example text. ---- - paste/exceptions/collector.py | 2 +- - paste/exceptions/formatter.py | 4 +-- - paste/fixture.py | 4 +-- - paste/request.py | 11 ++++++-- - paste/util/template.py | 11 ++++---- - paste/wsgiwrappers.py | 3 ++- - tests/cgiapp_data/form.cgi | 59 ++++++++++++++++++++++++++++++++++++++++++- - tests/test_cgiapp.py | 23 +++++++++++++++++ - tests/test_doctests.py | 5 +++- - tests/test_template.txt | 4 +-- - tests/test_wsgiwrappers.py | 2 +- - 11 files changed, 109 insertions(+), 19 deletions(-) - -diff --git a/paste/exceptions/collector.py b/paste/exceptions/collector.py -index 8867bf7..632ce06 100644 ---- a/paste/exceptions/collector.py -+++ b/paste/exceptions/collector.py -@@ -266,7 +266,7 @@ class ExceptionCollector(object): - name = co.co_name - globals = f.f_globals - locals = f.f_locals -- if not hasattr(locals, 'has_key'): -+ if not hasattr(locals, 'keys'): - # Something weird about this frame; it's not a real dict - warnings.warn( - "Frame %s has an invalid locals(): %r" % ( -diff --git a/paste/exceptions/formatter.py b/paste/exceptions/formatter.py -index c83ab50..09309de 100644 ---- a/paste/exceptions/formatter.py -+++ b/paste/exceptions/formatter.py -@@ -217,7 +217,7 @@ class TextFormatter(AbstractFormatter): - elif isinstance(value, dict): - lines = ['\n', title, '-'*len(title)] - items = value.items() -- items.sort() -+ items = sorted(items) - for n, v in items: - try: - v = repr(v) -@@ -303,7 +303,7 @@ class HTMLFormatter(TextFormatter): - def zebra_table(self, title, rows, table_class="variables"): - if isinstance(rows, dict): - rows = rows.items() -- rows.sort() -+ rows = sorted(rows) - table = ['' % table_class, - '' - % self.quote(title)] -diff --git a/paste/fixture.py b/paste/fixture.py -index df1c75d..363f119 100644 ---- a/paste/fixture.py -+++ b/paste/fixture.py -@@ -226,8 +226,8 @@ class TestApp(object): - if hasattr(params, 'items'): - # Some other multi-dict like format - params = urlencode(params.items()) -- if six.PY3: -- params = params.encode('utf8') -+ if six.PY3 and isinstance(params, six.text_type): -+ params = params.encode('utf8') - if upload_files: - params = urlparse.parse_qsl(params, keep_blank_values=True) - content_type, params = self.encode_multipart( -diff --git a/paste/request.py b/paste/request.py -index f0d91c1..8d5e5c3 100644 ---- a/paste/request.py -+++ b/paste/request.py -@@ -140,7 +140,7 @@ def parse_dict_querystring(environ): - environ['paste.parsed_dict_querystring'] = (multi, source) - return multi - --def parse_formvars(environ, include_get_vars=True): -+def parse_formvars(environ, include_get_vars=True, encoding=None, errors=None): - """Parses the request, returning a MultiDict of form variables. - - If ``include_get_vars`` is true then GET (query string) variables -@@ -182,9 +182,16 @@ def parse_formvars(environ, include_get_vars=True): - environ['CONTENT_TYPE'] = '' - else: - input = environ['wsgi.input'] -+ kwparms = {} -+ if six.PY3: -+ if encoding: -+ kwparms['encoding'] = encoding -+ if errors: -+ kwparms['errors'] = errors - fs = cgi.FieldStorage(fp=input, - environ=environ, -- keep_blank_values=1) -+ keep_blank_values=1, -+ **kwparms) - environ['QUERY_STRING'] = old_query_string - if fake_out_cgi: - environ['CONTENT_TYPE'] = old_content_type -diff --git a/paste/util/template.py b/paste/util/template.py -index f0826af..5a63664 100644 ---- a/paste/util/template.py -+++ b/paste/util/template.py -@@ -318,28 +318,27 @@ def html_quote(value): - if value is None: - return '' - if not isinstance(value, six.string_types): -- if hasattr(value, '__unicode__'): -+ if six.PY2 and hasattr(value, '__unicode__'): - value = unicode(value) - else: - value = str(value) - value = cgi.escape(value, 1) -- if isinstance(value, unicode): -+ if six.PY2 and isinstance(value, unicode): - value = value.encode('ascii', 'xmlcharrefreplace') - return value - - def url(v): - if not isinstance(v, six.string_types): -- if hasattr(v, '__unicode__'): -+ if six.PY2 and hasattr(v, '__unicode__'): - v = unicode(v) - else: - v = str(v) -- if isinstance(v, unicode): -+ if six.PY2 and isinstance(v, unicode): - v = v.encode('utf8') - return quote(v) - - def attr(**kw): -- kw = kw.items() -- kw.sort() -+ kw = sorted(kw.items()) - parts = [] - for name, value in kw: - if value is None: -diff --git a/paste/wsgiwrappers.py b/paste/wsgiwrappers.py -index 7b8f6de..674054f 100644 ---- a/paste/wsgiwrappers.py -+++ b/paste/wsgiwrappers.py -@@ -199,7 +199,8 @@ class WSGIRequest(object): - GET = property(GET, doc=GET.__doc__) - - def _POST(self): -- return parse_formvars(self.environ, include_get_vars=False) -+ return parse_formvars(self.environ, include_get_vars=False, -+ encoding=self.charset, errors=self.errors) - - def POST(self): - """Dictionary-like object representing the POST body. -diff --git a/tests/cgiapp_data/form.cgi b/tests/cgiapp_data/form.cgi -index 2181998..c4c562d 100755 ---- a/tests/cgiapp_data/form.cgi -+++ b/tests/cgiapp_data/form.cgi -@@ -1,11 +1,68 @@ - #!/usr/bin/env python - -+from __future__ import print_function -+ - import cgi -+import six - - print('Content-type: text/plain') - print('') - --form = cgi.FieldStorage() -+if six.PY3: -+ # Python 3: cgi.FieldStorage keeps some field names as unicode and some as -+ # the repr() of byte strings, duh. -+ -+ class FieldStorage(cgi.FieldStorage): -+ -+ def _key_candidates(self, key): -+ yield key -+ -+ try: -+ # assume bytes, coerce to str -+ try: -+ yield key.decode(self.encoding) -+ except UnicodeDecodeError: -+ pass -+ except AttributeError: -+ # assume str, coerce to bytes -+ try: -+ yield key.encode(self.encoding) -+ except UnicodeEncodeError: -+ pass -+ -+ def __getitem__(self, key): -+ -+ superobj = super(FieldStorage, self) -+ -+ error = None -+ -+ for candidate in self._key_candidates(key): -+ if isinstance(candidate, bytes): -+ # ouch -+ candidate = repr(candidate) -+ try: -+ return superobj.__getitem__(candidate) -+ except KeyError as e: -+ if error is None: -+ error = e -+ -+ # fall through, re-raise the first KeyError -+ raise error -+ -+ def __contains__(self, key): -+ superobj = super(FieldStorage, self) -+ -+ for candidate in self._key_candidates(key): -+ if superobj.__contains__(candidate): -+ return True -+ return False -+ -+else: # PY2 -+ -+ FieldStorage = cgi.FieldStorage -+ -+ -+form = FieldStorage() - - print('Filename: %s' % form['up'].filename) - print('Name: %s' % form['name'].value) -diff --git a/tests/test_cgiapp.py b/tests/test_cgiapp.py -index 12cb2be..900e83e 100644 ---- a/tests/test_cgiapp.py -+++ b/tests/test_cgiapp.py -@@ -8,6 +8,29 @@ data_dir = os.path.join(os.path.dirname(__file__), 'cgiapp_data') - - # these CGI scripts can't work on Windows or Jython - if sys.platform != 'win32' and not sys.platform.startswith('java'): -+ -+ # Ensure the CGI scripts are called with the same python interpreter. Put a -+ # symlink to the interpreter executable into the path... -+ def setup_module(): -+ global oldpath, pyexelink -+ oldpath = os.environ.get('PATH', None) -+ os.environ['PATH'] = data_dir + os.path.pathsep + oldpath -+ pyexelink = os.path.join(data_dir, "python") -+ try: -+ os.unlink(pyexelink) -+ except OSError: -+ pass -+ os.symlink(sys.executable, pyexelink) -+ -+ # ... and clean up again. -+ def teardown_module(): -+ global oldpath, pyexelink -+ os.unlink(pyexelink) -+ if oldpath is not None: -+ os.environ['PATH'] = oldpath -+ else: -+ del os.environ['PATH'] -+ - def test_ok(): - app = TestApp(CGIApplication({}, script='ok.cgi', path=[data_dir])) - res = app.get('') -diff --git a/tests/test_doctests.py b/tests/test_doctests.py -index 875fbc2..d59d666 100644 ---- a/tests/test_doctests.py -+++ b/tests/test_doctests.py -@@ -1,3 +1,4 @@ -+import six - import doctest - from paste.util.import_string import simple_import - import os -@@ -25,7 +26,9 @@ modules = [ - 'paste.request', - ] - --options = doctest.ELLIPSIS|doctest.REPORT_ONLY_FIRST_FAILURE -+options = doctest.ELLIPSIS | doctest.REPORT_ONLY_FIRST_FAILURE -+if six.PY3: -+ options |= doctest.IGNORE_EXCEPTION_DETAIL - - def test_doctests(): - for filename in filenames: -diff --git a/tests/test_template.txt b/tests/test_template.txt -index 45a85e2..f3466f2 100644 ---- a/tests/test_template.txt -+++ b/tests/test_template.txt -@@ -97,8 +97,8 @@ in Python, but it's more useful in templates generally):: - ... elif item == 'orange': - ... assert loop.last - ... if loop.first_group(lambda i: i[0].upper()): -- ... print '%s:' % item[0].upper() -- ... print loop.number, item -+ ... print('%s:' % item[0].upper()) -+ ... print("%s %s" % (loop.number, item)) - A: - 1 apple - 2 asparagus -diff --git a/tests/test_wsgiwrappers.py b/tests/test_wsgiwrappers.py -index 8719693..75d03ed 100644 ---- a/tests/test_wsgiwrappers.py -+++ b/tests/test_wsgiwrappers.py -@@ -13,7 +13,7 @@ class AssertApp(object): - def __call__(self, environ, start_response): - start_response('200 OK', [('Content-type','text/plain')]) - self.assertfunc(environ) -- return ['Passed'] -+ return [b'Passed'] - - no_encoding = object() - def valid_name(name, encoding=no_encoding, post=False): --- -2.5.0 - diff --git a/python-paste.spec b/python-paste.spec index 2e37c13..29b2861 100644 --- a/python-paste.spec +++ b/python-paste.spec @@ -1,70 +1,77 @@ -%if 0%{?fedora} || 0%{?rhel} > 6 -%global with_python3 1 -%else -%{!?python_sitelib: %global python_sitelib %(%{__python} -c "from distutils.sysconfig import get_python_lib; print get_python_lib()")} -%endif +%global desc These provide several pieces of "middleware" (or filters) that can be nested\ +to build web applications. Each piece of middleware uses the WSGI (PEP 333)\ +interface, and should be compatible with other middleware based on those\ +interfaces. +%global sum Tools for using a Web Server Gateway Interface stack Name: python-paste -Version: 2.0.2 -Release: 5%{?dist} -Summary: Tools for using a Web Server Gateway Interface stack -Group: System Environment/Libraries +Version: 2.0.3 +Release: 1%{?dist} +BuildArch: noarch + # Most of the code is MIT # paste/exceptions/collector.py is ZPLv2.0 # paste/evalexception/media/MochiKit.packed.js AFL (2.1) or MIT # paste/lint.py MIT or Apache v2 # PySourceColor.py, Python -License: MIT and ZPLv2.0 and Python and (AFL or MIT) and (MIT or ASL 2.0) -URL: http://pythonpaste.org +License: MIT and ZPLv2.0 and Python and (AFL or MIT) and (MIT or ASL 2.0) +Summary: %sum +URL: https://bitbucket.org/ianb/paste/ Source0: https://files.pythonhosted.org/packages/source/P/Paste/Paste-%{version}.tar.gz -# Upstreamed (as single commits) at -# https://bitbucket.org/ianb/paste/issues/13/tests-failing-under-python-3 -Patch0: python-paste-2.0.2-py3k.patch -BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) -BuildArch: noarch +BuildRequires: pyOpenSSL +BuildRequires: python-tempita BuildRequires: python2-devel -BuildRequires: python-setuptools -BuildRequires: python-nose -BuildRequires: python-tempita -BuildRequires: pyOpenSSL -Requires: python-tempita -Requires: pyOpenSSL -Requires: python-setuptools +BuildRequires: python2-setuptools +BuildRequires: python2-six >= 1.4.0 +BuildRequires: python2-nose >= 0.11 +BuildRequires: python3-devel +BuildRequires: python3-nose +BuildRequires: python3-pyOpenSSL +BuildRequires: python3-setuptools +BuildRequires: python3-six >= 1.4.0 +BuildRequires: python3-tempita -%if 0%{?with_python3} -BuildRequires: python3-devel -BuildRequires: python3-setuptools -BuildRequires: python3-nose -BuildRequires: python3-tempita -BuildRequires: python3-pyOpenSSL -%endif # if with_python3 %description -These provide several pieces of "middleware" (or filters) that can be nested -to build web applications. Each piece of middleware uses the WSGI (PEP 333) -interface, and should be compatible with other middleware based on those -interfaces. +%desc + + +%package -n python2-paste +Summary: %sum + +%{?python_provide:%python_provide python2-paste} + +Requires: pyOpenSSL +Requires: python-tempita +Requires: python2-setuptools +Requires: python2-six >= 1.4.0 + + +%description -n python2-paste +%{desc} + -%if 0%{?with_python3} %package -n python3-paste Summary: Tools for using a Web Server Gateway Interface stack -Group: System Environment/Libraries -Requires: python3-tempita -Requires: python3-setuptools + +%{?python_provide:%python_provide python3-paste} + Requires: python3-pyOpenSSL +Requires: python3-setuptools +Requires: python3-six +Requires: python3-tempita + %description -n python3-paste -These provide several pieces of "middleware" (or filters) that can be nested -to build web applications. Each piece of middleware uses the WSGI (PEP 333) -interface, and should be compatible with other middleware based on those -interfaces. -%endif # with_python3 +%{desc} %prep -%setup -q -n Paste-%{version} -%patch0 -p1 -b .py3k +%autosetup -n Paste-%{version} + +# Paste-2.0.3 seems to have a few .py.orig files that don't appear in upstream scm. Let's drop them. +find . -name "*.orig" -delete # Strip #! lines that make these seem like scripts %{__sed} -i -e '/^#!.*/,1 d' paste/util/scgiserver.py paste/debug/doctest_webapp.py @@ -74,61 +81,70 @@ pushd docs rm StyleGuide.txt popd -%if 0%{?with_python3} rm -rf %{py3dir} cp -a . %{py3dir} -%endif # with_python3 + %build %{__python} setup.py build -%if 0%{?with_python3} pushd %{py3dir} %{__python3} setup.py build popd -%endif # with_python3 %install -rm -rf %{buildroot} %{__python} setup.py install --skip-build --root %{buildroot} -%if 0%{?with_python3} pushd %{py3dir} -%{__python3} setup.py install --skip-build --root $RPM_BUILD_ROOT +%{__python3} setup.py install --skip-build --root %{buildroot} popd -%endif # with_python3 + %check export PYTHONPATH=$(pwd) # We don't have access to the wider internet in the buildsystem nosetests-%{python2_version} -e '.*test_paste_website' -%if 0%{?with_python3} pushd %{py3dir} export PYTHONPATH=$(pwd) # We don't have access to the wider internet in the buildsystem nosetests-%{python3_version} -e '.*test_paste_website' popd -%endif # with_python3 -%clean -rm -rf %{buildroot} - -%files -%defattr(-,root,root,-) +%files -n python2-paste +%license docs/license.txt %doc docs/* -%{python_sitelib}/* +%{python2_sitelib}/paste +%{python2_sitelib}/Paste-%{version}-py%{python2_version}.egg-info +%{python2_sitelib}/Paste-%{version}-py%{python2_version}-nspkg.pth + -%if 0%{?with_python3} %files -n python3-paste -%defattr(-,root,root,-) -%{python3_sitelib}/* -%endif +%license docs/license.txt +%doc docs/* +%{python3_sitelib}/paste +%{python3_sitelib}/Paste-%{version}-py%{python3_version}.egg-info +%{python3_sitelib}/Paste-%{version}-py%{python3_version}-nspkg.pth %changelog +* Thu Jan 05 2017 Randy Barlow - 2.0.3-1 +- Update to 2.0.3 (#1316101). +- Use the python_provides macro and rename python-paste to python2-paste. +- Drop conditionals on building python3-paste. +- Use the license macro. +- Dropped py3 fixes patch, since it is included in the upstream 2.0.3 release. +- Update URL, since old one doesn't load anymore. +- Reorganize spec file. +- Don't rm the buildroot before install. +- Drop some .orig files. +- Add BuildRequires on six. +- Drop unneeded clean section. +- Drop unneeded defattr in the files sections. +- Don't use * to select files in the Python sitelib, list them explicitly. + * Mon Dec 19 2016 Miro HronĨok - 2.0.2-5 - Rebuild for Python 3.6 diff --git a/sources b/sources index 085f199..aa9b616 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -4bfc8a7eaf858f6309d2ac0f40fc951c Paste-2.0.2.tar.gz +SHA512 (Paste-2.0.3.tar.gz) = 174b06d77bc6e1d4079e8de7df40412ffda098364efd4e3f915f858be1188c8a6fb546fe4ab981ccc067ec77b7171083b2469e7db6fc3b777d5a24151c928362
%s