Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pecan for openSUSE:Factory 
checked in at 2026-04-05 18:23:50
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pecan (Old)
 and      /work/SRC/openSUSE:Factory/.python-pecan.new.21863 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pecan"

Sun Apr  5 18:23:50 2026 rev:37 rq:1344557 version:1.8.0

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pecan/python-pecan.changes        
2025-07-31 17:45:35.794647883 +0200
+++ /work/SRC/openSUSE:Factory/.python-pecan.new.21863/python-pecan.changes     
2026-04-05 18:24:11.129989231 +0200
@@ -1,0 +2,9 @@
+Sat Apr  4 08:07:46 UTC 2026 - Dirk Müller <[email protected]>
+
+- update to 1.8.0:
+  * replaced deprecated pkg_resources with importlib.metadata and
+    importlib.resources
+  * minimum Python version is now 3.10; removed support for
+    Python 3.8 and 3.9
+
+-------------------------------------------------------------------

Old:
----
  pecan-1.7.0.tar.gz

New:
----
  pecan-1.8.0.tar.gz

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

Other differences:
------------------
++++++ python-pecan.spec ++++++
--- /var/tmp/diff_new_pack.QbkUMY/_old  2026-04-05 18:24:11.910021235 +0200
+++ /var/tmp/diff_new_pack.QbkUMY/_new  2026-04-05 18:24:11.910021235 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-pecan
 #
-# Copyright (c) 2025 SUSE LLC
+# Copyright (c) 2026 SUSE LLC and contributors
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -24,7 +24,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-pecan
-Version:        1.7.0
+Version:        1.8.0
 Release:        0
 Summary:        A WSGI object-dispatching web framework
 License:        BSD-3-Clause
@@ -36,6 +36,7 @@
 BuildRequires:  %{python_module SQLAlchemy}
 BuildRequires:  %{python_module WebOb >= 1.8}
 BuildRequires:  %{python_module WebTest >= 1.3.1}
+BuildRequires:  %{python_module base >= 3.10}
 BuildRequires:  %{python_module gunicorn}
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}

++++++ pecan-1.7.0.tar.gz -> pecan-1.8.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/PKG-INFO new/pecan-1.8.0/PKG-INFO
--- old/pecan-1.7.0/PKG-INFO    2025-07-07 18:03:54.867873400 +0200
+++ new/pecan-1.8.0/PKG-INFO    2026-03-12 22:57:01.624453500 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: pecan
-Version: 1.7.0
+Version: 1.8.0
 Summary: A WSGI object-dispatching web framework, designed to be lean and 
fast, with few dependencies.
 Home-page: http://github.com/pecan/pecan
 Author: Jonathan LaCour
@@ -19,15 +19,13 @@
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
 Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
 Classifier: Topic :: Software Development :: Libraries :: Application 
Frameworks
-Requires-Python: >=3.8
+Requires-Python: >=3.10
 License-File: LICENSE
 License-File: AUTHORS
 Requires-Dist: WebOb>=1.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/__init__.py 
new/pecan-1.8.0/pecan/__init__.py
--- old/pecan-1.7.0/pecan/__init__.py   2025-07-07 18:03:44.000000000 +0200
+++ new/pecan-1.8.0/pecan/__init__.py   2026-03-12 22:27:48.000000000 +0100
@@ -15,6 +15,7 @@
 from .configuration import _runtime_conf as conf
 from . import middleware
 
+from logging import captureWarnings
 from logging.config import dictConfig
 
 import warnings
@@ -60,18 +61,8 @@
     debug = kw.get('debug', False)
     if logging:
         if debug:
-            try:
-                #
-                # By default, Python 2.7+ silences DeprecationWarnings.
-                # However, if conf.app.debug is True, we should probably ensure
-                # that users see these types of warnings.
-                #
-                from logging import captureWarnings
-                captureWarnings(True)
-                warnings.simplefilter("default", DeprecationWarning)
-            except ImportError:
-                # No captureWarnings on Python 2.6, DeprecationWarnings are on
-                pass
+            captureWarnings(True)
+            warnings.simplefilter("default", DeprecationWarning)
 
         if isinstance(logging, Config):
             logging = logging.to_dict()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/commands/base.py 
new/pecan-1.8.0/pecan/commands/base.py
--- old/pecan-1.7.0/pecan/commands/base.py      2025-07-07 18:03:44.000000000 
+0200
+++ new/pecan-1.8.0/pecan/commands/base.py      2026-03-12 22:27:48.000000000 
+0100
@@ -1,5 +1,5 @@
-import pkg_resources
 import argparse
+import importlib.metadata
 import logging
 import sys
 from warnings import warn
@@ -31,7 +31,7 @@
         self.load_commands()
 
     def load_commands(self):
-        for ep in pkg_resources.iter_entry_points('pecan.command'):
+        for ep in importlib.metadata.entry_points(group='pecan.command'):
             log.debug('%s loading plugin %s', self.__class__.__name__, ep)
             if ep.name in self.commands:
                 warn(
@@ -98,7 +98,7 @@
 
     @property
     def version(self):
-        return pkg_resources.get_distribution('pecan').version
+        return importlib.metadata.version('pecan')
 
     @property
     def commands(self):
@@ -162,6 +162,7 @@
         from pecan import load_app
         return load_app(self.args.config_file)
 
+
 BaseCommand = BaseCommandMeta('BaseCommand', (BaseCommandParent,), {
     '__doc__': BaseCommandParent.__doc__
 })
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/commands/create.py 
new/pecan-1.8.0/pecan/commands/create.py
--- old/pecan-1.7.0/pecan/commands/create.py    2025-07-07 18:03:44.000000000 
+0200
+++ new/pecan-1.8.0/pecan/commands/create.py    2026-03-12 22:27:48.000000000 
+0100
@@ -1,7 +1,7 @@
 """
 Create command for Pecan
 """
-import pkg_resources
+import importlib.metadata
 import logging
 from warnings import warn
 from pecan.commands import BaseCommand
@@ -18,7 +18,7 @@
         self.load_scaffolds()
 
     def load_scaffolds(self):
-        for ep in pkg_resources.iter_entry_points('pecan.scaffold'):
+        for ep in importlib.metadata.entry_points(group='pecan.scaffold'):
             log.debug('%s loading scaffold %s', self.__class__.__name__, ep)
             try:
                 cmd = ep.load()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/configuration.py 
new/pecan-1.8.0/pecan/configuration.py
--- old/pecan-1.7.0/pecan/configuration.py      2025-07-07 18:03:44.000000000 
+0200
+++ new/pecan-1.8.0/pecan/configuration.py      2026-03-12 22:27:48.000000000 
+0100
@@ -40,9 +40,10 @@
     :param filename: A filename to use for the configuration.
     '''
 
-    def __init__(self, conf_dict={}, filename=''):
+    def __init__(self, conf_dict=None, filename=''):
         self.__values__ = {}
         self.__file__ = filename
+        conf_dict = conf_dict or {}
         self.update(conf_dict)
 
     def empty(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/core.py 
new/pecan-1.8.0/pecan/core.py
--- old/pecan-1.7.0/pecan/core.py       2025-07-07 18:03:44.000000000 +0200
+++ new/pecan-1.8.0/pecan/core.py       2026-03-12 22:27:48.000000000 +0100
@@ -29,12 +29,12 @@
 
 class RoutingState(object):
 
-    def __init__(self, request, response, app, hooks=[], controller=None,
+    def __init__(self, request, response, app, hooks=None, controller=None,
                  arguments=None):
         self.request = request
         self.response = response
         self.app = app
-        self.hooks = hooks
+        self.hooks = hooks or []
         self.controller = controller
         self.arguments = arguments
 
@@ -130,7 +130,7 @@
         del traceback
 
 
-def redirect(location=None, internal=False, code=None, headers={},
+def redirect(location=None, internal=False, code=None, headers=None,
              add_slash=False, request=None):
     '''
     Perform a redirect, either internal or external. An internal redirect
@@ -221,7 +221,7 @@
 
     def __init__(self, root, default_renderer='mako',
                  template_path='templates', hooks=lambda: [],
-                 custom_renderers={}, extra_template_vars={},
+                 custom_renderers=None, extra_template_vars=None,
                  force_canonical=True, guess_content_type_from_ext=True,
                  context_local_factory=None, request_cls=Request,
                  response_cls=Response, **kw):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/jsonify.py 
new/pecan-1.8.0/pecan/jsonify.py
--- old/pecan-1.7.0/pecan/jsonify.py    2025-07-07 18:03:44.000000000 +0200
+++ new/pecan-1.8.0/pecan/jsonify.py    2026-03-12 22:27:48.000000000 +0100
@@ -1,21 +1,9 @@
 from datetime import datetime, date
 from decimal import Decimal
+from functools import singledispatch
 from json import JSONEncoder
 
-# depending on the version WebOb might have 2 types of dicts
-try:
-    # WebOb <= 1.1.1
-    from webob.multidict import MultiDict, UnicodeMultiDict
-    webob_dicts = (MultiDict, UnicodeMultiDict)  # pragma: no cover
-except ImportError:  # pragma no cover
-    # WebOb >= 1.2
-    from webob.multidict import MultiDict
-    webob_dicts = (MultiDict,)
-
-try:
-    from functools import singledispatch
-except ImportError:  # pragma: no cover
-    from singledispatch import singledispatch
+from webob.multidict import MultiDict
 
 try:
     import sqlalchemy  # noqa
@@ -89,8 +77,8 @@
             Casts the RowProxy cursor object into a dictionary, probably
             losing its ordered dictionary behavior in the process but
             making it JSON-friendly.
-        * webob_dicts objects
-            returns webob_dicts.mixed() dictionary, which is guaranteed
+        * webob.multidict.MultiDict objects
+            returns MultiDict.mixed() dictionary, which is guaranteed
             to be JSON-friendly.
         '''
         if hasattr(obj, '__json__') and callable(obj.__json__):
@@ -123,11 +111,12 @@
                 # SQLAlchemy 2.0 support
                 obj = obj._mapping
             return dict(obj)
-        elif isinstance(obj, webob_dicts):
+        elif isinstance(obj, MultiDict):
             return obj.mixed()
         else:
             return JSONEncoder.default(self, obj)
 
+
 _default = GenericJSON()
 
 
@@ -147,6 +136,7 @@
     def default(self, obj):
         return jsonify(obj)
 
+
 _instance = GenericFunctionJSON()
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/log.py new/pecan-1.8.0/pecan/log.py
--- old/pecan-1.7.0/pecan/log.py        2025-07-07 18:03:44.000000000 +0200
+++ new/pecan-1.8.0/pecan/log.py        2026-03-12 22:27:48.000000000 +0100
@@ -8,7 +8,9 @@
     def __init__(self, _logging=None, colorizer=None, *a, **kw):
         logging.Formatter.__init__(self, *a, **kw)
         warn(
-            'pecan.log.ColorFormatter is no longer supported; consider an 
alternative library such as https://pypi.org/project/colorlog/',
+            'pecan.log.ColorFormatter is no longer supported; '
+            'consider an alternative library such as '
+            'https://pypi.org/project/colorlog/',
             DeprecationWarning
         )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/middleware/recursive.py 
new/pecan-1.8.0/pecan/middleware/recursive.py
--- old/pecan-1.7.0/pecan/middleware/recursive.py       2025-07-07 
18:03:44.000000000 +0200
+++ new/pecan-1.8.0/pecan/middleware/recursive.py       2026-03-12 
22:27:48.000000000 +0100
@@ -119,7 +119,8 @@
                 raise ForwardRequestException(environ=new_environ)
     """
 
-    def __init__(self, url=None, environ={}, factory=None, path_info=None):
+    def __init__(self, url=None, environ=None, factory=None, path_info=None):
+        environ = environ or {}
         # Check no incompatible options have been chosen
         if factory and url:
             raise TypeError(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/scaffolds/__init__.py 
new/pecan-1.8.0/pecan/scaffolds/__init__.py
--- old/pecan-1.7.0/pecan/scaffolds/__init__.py 2025-07-07 18:03:44.000000000 
+0200
+++ new/pecan-1.8.0/pecan/scaffolds/__init__.py 2026-03-12 22:27:48.000000000 
+0100
@@ -1,7 +1,7 @@
 import sys
+import importlib.resources
 import os
 import re
-import pkg_resources
 from string import Template
 
 DEFAULT_SCAFFOLD = 'base'
@@ -19,7 +19,7 @@
 
     ...where...
 
-        pkg_resources.resource_listdir(_scaffold_dir[0], _scaffold_dir[1]))
+        importlib.resources.files(_scaffold_dir[0]).joinpath(_scaffold_dir[1])
 
     ...points to some scaffold directory root.
     """
@@ -63,7 +63,6 @@
         out_.write('\n')
         out_.flush()
 
-    names = sorted(pkg_resources.resource_listdir(source[0], source[1]))
     if not os.path.exists(dest):
         out('Creating %s' % dest)
         makedirs(dest)
@@ -71,22 +70,25 @@
         out('%s already exists' % dest)
         return
 
-    for name in names:
+    data_dir = importlib.resources.files(source[0])
+    for path in data_dir.joinpath(source[1]).iterdir():
 
-        full = '/'.join([source[1], name])
-        dest_full = os.path.join(dest, substitute_filename(name, variables))
+        full = os.path.join(source[1], path.name)
+        dest_full = os.path.join(
+            dest, substitute_filename(path.name, variables))
 
         sub_file = False
         if dest_full.endswith('_tmpl'):
             dest_full = dest_full[:-5]
             sub_file = True
 
-        if pkg_resources.resource_isdir(source[0], full):
+        if (data_dir.joinpath(full)).is_dir():
             out('Recursing into %s' % os.path.basename(full))
             copy_dir((source[0], full), dest_full, variables, out_, i + 1)
             continue
         else:
-            content = pkg_resources.resource_string(source[0], full)
+            content = importlib.resources.files(source[0]).joinpath(full)\
+                .read_bytes()
 
         if sub_file:
             content = render_template(content, variables)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/secure.py 
new/pecan-1.8.0/pecan/secure.py
--- old/pecan-1.7.0/pecan/secure.py     2025-07-07 18:03:44.000000000 +0200
+++ new/pecan-1.8.0/pecan/secure.py     2026-03-12 22:27:48.000000000 +0100
@@ -23,6 +23,7 @@
     def __bool__(self):
         return self.__nonzero__()
 
+
 Any = _SecureState('Any', False)
 Protected = _SecureState('Protected', True)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/templating.py 
new/pecan-1.8.0/pecan/templating.py
--- old/pecan-1.7.0/pecan/templating.py 2025-07-07 18:03:44.000000000 +0200
+++ new/pecan-1.8.0/pecan/templating.py 2026-03-12 22:27:48.000000000 +0100
@@ -24,6 +24,7 @@
 
     # TODO: add error formatter for json (pass it through json lint?)
 
+
 _builtin_renderers['json'] = JsonRenderer
 
 #
@@ -197,12 +198,12 @@
         start_lineno = max(lineno - context, 0)
         end_lineno = lineno + context
 
-        lines = [escape(l, True) for l in lines[start_lineno:end_lineno]]
+        lines = [escape(line, True) for line in lines[start_lineno:end_lineno]]
         i = lineno - start_lineno
         lines[i] = '<strong>%s</strong>' % lines[i]
 
     else:
-        lines = [escape(l, True) for l in lines[:context]]
+        lines = [escape(line, True) for line in lines[:context]]
     msg = '<pre style="background-color:#ccc;padding:2em;">%s</pre>'
     return msg % ''.join(lines)
 
@@ -217,7 +218,8 @@
 
     :param extras: dictionary of extra parameters. Defaults to an empty dict.
     '''
-    def __init__(self, extras={}):
+    def __init__(self, extras=None):
+        extras = extras or {}
         self.namespace = dict(extras)
 
     def update(self, d):
@@ -249,10 +251,10 @@
     :param custom_renderers: custom-defined renderers to manufacture
     :param extra_vars: extra vars for the template namespace
     '''
-    def __init__(self, custom_renderers={}, extra_vars={}):
+    def __init__(self, custom_renderers=None, extra_vars=None):
         self._renderers = {}
         self._renderer_classes = dict(_builtin_renderers)
-        self.add_renderers(custom_renderers)
+        self.add_renderers(custom_renderers or {})
         self.extra_vars = ExtraNamespace(extra_vars)
 
     def add_renderers(self, custom_dict):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/tests/scaffold_builder.py 
new/pecan-1.8.0/pecan/tests/scaffold_builder.py
--- old/pecan-1.7.0/pecan/tests/scaffold_builder.py     2025-07-07 
18:03:45.000000000 +0200
+++ new/pecan-1.8.0/pecan/tests/scaffold_builder.py     2026-03-12 
22:27:48.000000000 +0100
@@ -86,7 +86,7 @@
             try:
                 # just in case stdin doesn't close
                 proc.terminate()
-            except:
+            except Exception:
                 pass
 
     class TestThirdPartyServe(TestTemplateBuilds):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/tests/test_base.py 
new/pecan-1.8.0/pecan/tests/test_base.py
--- old/pecan-1.7.0/pecan/tests/test_base.py    2025-07-07 18:03:45.000000000 
+0200
+++ new/pecan-1.8.0/pecan/tests/test_base.py    2026-03-12 22:27:48.000000000 
+0100
@@ -32,7 +32,8 @@
 
     def test_controller_lookup_by_string_path(self):
         app = Pecan('pecan.tests.test_base.SampleRootController')
-        assert app.root and app.root.__class__.__name__ == 
'SampleRootController'
+        assert (
+            app.root and app.root.__class__.__name__ == 'SampleRootController')
 
 
 class TestEmptyContent(PecanTestCase):
@@ -448,7 +449,7 @@
             r = self.app_.get('/')
             assert r.status_int != 200  # pragma: nocover
         except Exception as ex:
-            assert type(ex) == TypeError
+            assert isinstance(ex, TypeError)
             assert ex.args[0] in (
                 "index() takes exactly 2 arguments (1 given)",
                 "index() missing 1 required positional argument: 'id'",
@@ -987,7 +988,7 @@
             r = self.app_.get('/eater')
             assert r.status_int != 200  # pragma: nocover
         except Exception as ex:
-            assert type(ex) == TypeError
+            assert isinstance(ex, TypeError)
             assert ex.args[0] in (
                 "eater() takes exactly 2 arguments (1 given)",
                 "eater() missing 1 required positional argument: 'id'",
@@ -1133,7 +1134,7 @@
         try:
             try:
                 raise Exception('Bottom Exception')
-            except:
+            except Exception:
                 abort(404)
         except Exception:
             last_exc, _, last_traceback = sys.exc_info()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/tests/test_no_thread_locals.py 
new/pecan-1.8.0/pecan/tests/test_no_thread_locals.py
--- old/pecan-1.7.0/pecan/tests/test_no_thread_locals.py        2025-07-07 
18:03:45.000000000 +0200
+++ new/pecan-1.8.0/pecan/tests/test_no_thread_locals.py        2026-03-12 
22:27:48.000000000 +0100
@@ -357,7 +357,7 @@
             r = self.app_.get('/')
             assert r.status_int != 200  # pragma: nocover
         except Exception as ex:
-            assert type(ex) == TypeError
+            assert isinstance(ex, TypeError)
             assert ex.args[0] in (
                 "index() takes exactly 2 arguments (1 given)",
                 "index() missing 1 required positional argument: 'id'",
@@ -763,7 +763,7 @@
             r = self.app_.get('/eater')
             assert r.status_int != 200  # pragma: nocover
         except Exception as ex:
-            assert type(ex) == TypeError
+            assert isinstance(ex, TypeError)
             assert ex.args[0] in (
                 "eater() takes exactly 2 arguments (1 given)",
                 "eater() missing 1 required positional argument: 'id'",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan/tests/test_secure.py 
new/pecan-1.8.0/pecan/tests/test_secure.py
--- old/pecan-1.7.0/pecan/tests/test_secure.py  2025-07-07 18:03:45.000000000 
+0200
+++ new/pecan-1.8.0/pecan/tests/test_secure.py  2026-03-12 22:27:48.000000000 
+0100
@@ -7,11 +7,6 @@
 from pecan.secure import secure, unlocked, SecureController
 from pecan.tests import PecanTestCase
 
-try:
-    set()
-except:
-    from sets import Set as set
-
 
 class TestSecure(PecanTestCase):
     def test_simple_secure(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/pecan.egg-info/PKG-INFO 
new/pecan-1.8.0/pecan.egg-info/PKG-INFO
--- old/pecan-1.7.0/pecan.egg-info/PKG-INFO     2025-07-07 18:03:54.000000000 
+0200
+++ new/pecan-1.8.0/pecan.egg-info/PKG-INFO     2026-03-12 22:57:01.000000000 
+0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: pecan
-Version: 1.7.0
+Version: 1.8.0
 Summary: A WSGI object-dispatching web framework, designed to be lean and 
fast, with few dependencies.
 Home-page: http://github.com/pecan/pecan
 Author: Jonathan LaCour
@@ -19,15 +19,13 @@
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 3 :: Only
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.8
-Classifier: Programming Language :: Python :: 3.9
 Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: 3.11
 Classifier: Programming Language :: Python :: 3.12
 Classifier: Programming Language :: Python :: 3.13
 Classifier: Topic :: Internet :: WWW/HTTP :: WSGI
 Classifier: Topic :: Software Development :: Libraries :: Application 
Frameworks
-Requires-Python: >=3.8
+Requires-Python: >=3.10
 License-File: LICENSE
 License-File: AUTHORS
 Requires-Dist: WebOb>=1.8
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/setup.py new/pecan-1.8.0/setup.py
--- old/pecan-1.7.0/setup.py    2025-07-07 18:03:45.000000000 +0200
+++ new/pecan-1.8.0/setup.py    2026-03-12 22:46:14.000000000 +0100
@@ -1,9 +1,6 @@
-import sys
-import platform
-
 from setuptools import setup, find_packages
 
-version = '1.7.0'
+version = '1.8.0'
 
 #
 # determine requirements
@@ -20,31 +17,8 @@
         if (line and not line.startswith('-'))
     ]
 
-try:
-    from functools import singledispatch  # noqa
-except:
-    #
-    # This was introduced in Python 3.4 - the singledispatch package contains
-    # a backported replacement for 2.6 through 3.4
-    #
-    requirements.append('singledispatch')
-    try:
-        from collections import OrderedDict
-    except:
-        requirements.append('ordereddict')
-
-
 tests_require = requirements + test_requirements
 
-if sys.version_info < (3, 0):
-    # These don't support Python3 yet - don't run their tests
-    if platform.python_implementation() != 'PyPy':
-        # Kajiki is not pypy-compatible
-        tests_require += ['Kajiki']
-    tests_require += ['Genshi']
-else:
-    # Genshi added Python3 support in 0.7
-    tests_require += ['Genshi>=0.7']
 
 #
 # call setup
@@ -68,8 +42,6 @@
         'Programming Language :: Python',
         'Programming Language :: Python :: 3 :: Only',
         'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.8',
-        'Programming Language :: Python :: 3.9',
         'Programming Language :: Python :: 3.10',
         'Programming Language :: Python :: 3.11',
         'Programming Language :: Python :: 3.12',
@@ -85,7 +57,7 @@
     packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
     include_package_data=True,
     zip_safe=False,
-    python_requires='>=3.8',
+    python_requires='>=3.10',
     install_requires=requirements,
     tests_require=tests_require,
     test_suite='pecan',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pecan-1.7.0/test-requirements.txt 
new/pecan-1.8.0/test-requirements.txt
--- old/pecan-1.7.0/test-requirements.txt       2025-07-07 18:03:45.000000000 
+0200
+++ new/pecan-1.8.0/test-requirements.txt       2026-03-12 22:27:48.000000000 
+0100
@@ -1,6 +1,7 @@
+Genshi>=0.7
 gunicorn
-Jinja2<3  # >= 3 not compatible py35
-pep8
+Jinja2
+pycodestyle
 sqlalchemy
 uwsgi
 virtualenv

Reply via email to