Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-Werkzeug for openSUSE:Factory 
checked in at 2026-03-18 16:49:25
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Werkzeug (Old)
 and      /work/SRC/openSUSE:Factory/.python-Werkzeug.new.8177 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Werkzeug"

Wed Mar 18 16:49:25 2026 rev:53 rq:1340735 version:3.1.6

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Werkzeug/python-Werkzeug.changes  
2026-01-28 15:07:03.109765675 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-Werkzeug.new.8177/python-Werkzeug.changes    
    2026-03-18 16:50:33.033142739 +0100
@@ -1,0 +2,7 @@
+Tue Mar 17 16:20:02 UTC 2026 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to 3.1.6
+  * ``safe_join`` on Windows does not allow special devices names
+    in multi-segment paths. :ghsa:`29vq-49wr-vm6x`
+
+-------------------------------------------------------------------

Old:
----
  werkzeug-3.1.5.tar.gz

New:
----
  werkzeug-3.1.6.tar.gz

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

Other differences:
------------------
++++++ python-Werkzeug.spec ++++++
--- /var/tmp/diff_new_pack.k8zox6/_old  2026-03-18 16:50:33.941180776 +0100
+++ /var/tmp/diff_new_pack.k8zox6/_new  2026-03-18 16:50:33.945180943 +0100
@@ -27,7 +27,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-Werkzeug%{psuffix}
-Version:        3.1.5
+Version:        3.1.6
 Release:        0
 Summary:        The Swiss Army knife of Python web development
 License:        BSD-3-Clause

++++++ werkzeug-3.1.5.tar.gz -> werkzeug-3.1.6.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/CHANGES.rst 
new/werkzeug-3.1.6/CHANGES.rst
--- old/werkzeug-3.1.5/CHANGES.rst      2026-01-08 18:37:08.000000000 +0100
+++ new/werkzeug-3.1.6/CHANGES.rst      2026-02-19 16:12:36.000000000 +0100
@@ -1,5 +1,14 @@
 .. currentmodule:: werkzeug
 
+Version 3.1.6
+-------------
+
+Released 2026-02-19
+
+-   ``safe_join`` on Windows does not allow special devices names in
+    multi-segment paths. :ghsa:`29vq-49wr-vm6x`
+
+
 Version 3.1.5
 -------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/PKG-INFO new/werkzeug-3.1.6/PKG-INFO
--- old/werkzeug-3.1.5/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
+++ new/werkzeug-3.1.6/PKG-INFO 1970-01-01 01:00:00.000000000 +0100
@@ -1,6 +1,6 @@
 Metadata-Version: 2.4
 Name: Werkzeug
-Version: 3.1.5
+Version: 3.1.6
 Summary: The comprehensive WSGI web application library.
 Maintainer-email: Pallets <[email protected]>
 Requires-Python: >=3.9
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/docs/routing.rst 
new/werkzeug-3.1.6/docs/routing.rst
--- old/werkzeug-3.1.5/docs/routing.rst 2026-01-08 18:37:08.000000000 +0100
+++ new/werkzeug-3.1.6/docs/routing.rst 2026-02-19 16:12:36.000000000 +0100
@@ -87,6 +87,28 @@
 appropriately.
 
 
+Rule Priority
+=============
+
+In general, the map matches more specific rules first. Rules are made up of
+static and variable parts, separated by slash ``/``. For a given segment, rules
+with a static part in that position take priority, and longer static values 
take
+priority over shorter. Variable parts are weighted based on the type of data
+they match.
+
+If you're using subdomain or host matching, the domain part can use converters
+as well. The domain part is matched before the path parts. Like the path parts,
+a static domain part take priority over a variable part.
+
+Rules may end up with the same priority, by having static parts with the same
+length, and dynamic parts with the same weight, in the same positions. In this
+case, sorting is stable, so rules added earlier take priority.
+
+The exact way that rules are sorted internally is pretty complicated, but the
+result should be that you can rely on more specific rules matching before more
+general ones.
+
+
 Built-in Converters
 ===================
 
@@ -127,13 +149,6 @@
    :members: empty
 
 
-Matchers
-========
-
-.. autoclass:: StateMachineMatcher
-   :members:
-
-
 Rule Factories
 ==============
 
@@ -274,34 +289,3 @@
 
     url = adapter.build("comm")
     assert url == "ws://example.org/ws"
-
-
-State Machine Matching
-======================
-
-The default matching algorithm uses a state machine that transitions
-between parts of the request path to find a match. To understand how
-this works consider this rule::
-
-    /resource/<id>
-
-Firstly this rule is decomposed into two ``RulePart``. The first is a
-static part with a content equal to ``resource``, the second is
-dynamic and requires a regex match to ``[^/]+``.
-
-A state machine is then created with an initial state that represents
-the rule's first ``/``. This initial state has a single, static
-transition to the next state which represents the rule's second
-``/``. This second state has a single dynamic transition to the final
-state which includes the rule.
-
-To match a path the matcher starts and the initial state and follows
-transitions that work. Clearly a trial path of ``/resource/2`` has the
-parts ``""``, ``resource``, and ``2`` which match the transitions and
-hence a rule will match. Whereas ``/other/2`` will not match as there
-is no transition for the ``other`` part from the initial state.
-
-The only diversion from this rule is if a ``RulePart`` is not
-part-isolating i.e. it will match ``/``. In this case the ``RulePart``
-is considered final and represents a transition that must include all
-the subsequent parts of the trial path.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/pyproject.toml 
new/werkzeug-3.1.6/pyproject.toml
--- old/werkzeug-3.1.5/pyproject.toml   2026-01-08 18:37:08.000000000 +0100
+++ new/werkzeug-3.1.6/pyproject.toml   2026-02-19 16:12:36.000000000 +0100
@@ -1,6 +1,6 @@
 [project]
 name = "Werkzeug"
-version = "3.1.5"
+version = "3.1.6"
 description = "The comprehensive WSGI web application library."
 readme = "README.md"
 license = "BSD-3-Clause"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/src/werkzeug/routing/map.py 
new/werkzeug-3.1.6/src/werkzeug/routing/map.py
--- old/werkzeug-3.1.5/src/werkzeug/routing/map.py      2026-01-08 
18:37:08.000000000 +0100
+++ new/werkzeug-3.1.6/src/werkzeug/routing/map.py      2026-02-19 
16:12:36.000000000 +0100
@@ -834,69 +834,46 @@
         append_unknown: bool = True,
         url_scheme: str | None = None,
     ) -> str:
-        """Building URLs works pretty much the other way round.  Instead of
-        `match` you call `build` and pass it the endpoint and a dict of
-        arguments for the placeholders.
-
-        The `build` function also accepts an argument called `force_external`
-        which, if you set it to `True` will force external URLs. Per default
-        external URLs (include the server name) will only be used if the
-        target URL is on a different subdomain.
-
-        >>> m = Map([
-        ...     Rule('/', endpoint='index'),
-        ...     Rule('/downloads/', endpoint='downloads/index'),
-        ...     Rule('/downloads/<int:id>', endpoint='downloads/show')
-        ... ])
-        >>> urls = m.bind("example.com", "/")
-        >>> urls.build("index", {})
-        '/'
-        >>> urls.build("downloads/show", {'id': 42})
-        '/downloads/42'
-        >>> urls.build("downloads/show", {'id': 42}, force_external=True)
-        'http://example.com/downloads/42'
-
-        Because URLs cannot contain non ASCII data you will always get
-        bytes back.  Non ASCII characters are urlencoded with the
-        charset defined on the map instance.
-
-        Additional values are converted to strings and appended to the URL as
-        URL querystring parameters:
-
-        >>> urls.build("index", {'q': 'My Searchstring'})
-        '/?q=My+Searchstring'
-
-        When processing those additional values, lists are furthermore
-        interpreted as multiple values (as per
-        :py:class:`werkzeug.datastructures.MultiDict`):
-
-        >>> urls.build("index", {'q': ['a', 'b', 'c']})
-        '/?q=a&q=b&q=c'
-
-        Passing a ``MultiDict`` will also add multiple values:
-
-        >>> urls.build("index", MultiDict((('p', 'z'), ('q', 'a'), ('q', 
'b'))))
-        '/?p=z&q=a&q=b'
-
-        If a rule does not exist when building a `BuildError` exception is
-        raised.
-
-        The build method accepts an argument called `method` which allows you
-        to specify the method you want to have an URL built for if you have
-        different methods for the same endpoint specified.
-
-        :param endpoint: the endpoint of the URL to build.
-        :param values: the values for the URL to build.  Unhandled values are
-                       appended to the URL as query parameters.
-        :param method: the HTTP method for the rule if there are different
-                       URLs for different methods on the same endpoint.
-        :param force_external: enforce full canonical external URLs. If the URL
-                               scheme is not provided, this will generate
-                               a protocol-relative URL.
-        :param append_unknown: unknown parameters are appended to the generated
-                               URL as query string argument.  Disable this
-                               if you want the builder to ignore those.
-        :param url_scheme: Scheme to use in place of the bound
+        """Build a URL by filling in any variable slots in the endpoint's rule
+        with the provided values.
+
+        This produces relative URLs (path only, no host) by default, which is
+        appropriate for most use cases. When using subdomain or host matching,
+        the URL will be absolute if the endpoint is not on the same host as the
+        current request. If you need an absolute URL no matter what, such as
+        when adding a link to an email, pass ``force_external=True``.
+
+        Characters that are not allowed directly in URLs will be 
percent-encoded
+        using UTF-8.
+
+        Additional values that don't match any rule parts are added to the 
query
+        (``?key=value``) part of the URL.
+
+        If a rule is not found, an :exc:`.BuildError` is raised. Converters may
+        also raise exceptions when preparing a value.
+
+        Unlike matching, building does not perform comprehensive validation of
+        the values, it's assumed that they are trusted and correct. It's also
+        possible to build a URL for one endpoint that will be matched by
+        another, or will not match. This is very unlikely to happen or to 
matter
+        in most applications, especially with testing. If you need a
+        stronger guarantee, you can use a helper to verify that
+        ``match(build(endpoint)) == endpoint``.
+
+        :param endpoint: The endpoint for the rule to build.
+        :param values: Values for the variable parts of the rule, which will be
+            converted using the part's converter's
+            :meth:`~.BaseConverter.to_url` method. Keys that don't match
+            variable parts will be converted to a query string unless
+            ``append_unknown`` is disabled.
+        :param method: Further match the rule to build by this HTTP method, for
+            when there are multiple rules for the same endpoint that vary based
+            on method.
+        :param force_external: Always produce an absolute URL, for external 
use.
+            If ``scheme`` is not set, this produces a protocol-relative URL.
+        :param append_unknown: Convert values that don't match any rule parts
+            to a query string. Disable to ignore such values.
+        :param url_scheme: Scheme to use for absolute URLs. Defaults to
             :attr:`url_scheme`.
 
         .. versionchanged:: 2.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/src/werkzeug/security.py 
new/werkzeug-3.1.6/src/werkzeug/security.py
--- old/werkzeug-3.1.5/src/werkzeug/security.py 2026-01-08 18:37:08.000000000 
+0100
+++ new/werkzeug-3.1.6/src/werkzeug/security.py 2026-02-19 16:12:36.000000000 
+0100
@@ -10,7 +10,7 @@
 DEFAULT_PBKDF2_ITERATIONS = 1_000_000
 
 _os_alt_seps: list[str] = list(
-    sep for sep in [os.sep, os.path.altsep] if sep is not None and sep != "/"
+    sep for sep in [os.sep, os.altsep] if sep is not None and sep != "/"
 )
 # https://chrisdenton.github.io/omnipath/Special%20Dos%20Device%20Names.html
 _windows_device_files = {
@@ -142,15 +142,23 @@
     return hmac.compare_digest(_hash_internal(method, salt, password)[0], 
hashval)
 
 
-def safe_join(directory: str, *pathnames: str) -> str | None:
-    """Safely join zero or more untrusted path components to a base
+def safe_join(directory: str, *untrusted: str) -> str | None:
+    """Safely join zero or more untrusted path components to a trusted base
     directory to avoid escaping the base directory.
 
+    The untrusted path is assumed to be from/for a URL, such as for serving
+    files. Therefore, it should only use the forward slash ``/`` path 
separator,
+    and will be joined using that separator. On Windows, the backslash ``\\``
+    separator is not allowed.
+
     :param directory: The trusted base directory.
-    :param pathnames: The untrusted path components relative to the
+    :param untrusted: The untrusted path components relative to the
         base directory.
     :return: A safe path, otherwise ``None``.
 
+    .. versionchanged:: 3.1.6
+        Special device names in multi-segment paths are not allowed on Windows.
+
     .. versionchanged:: 3.1.5
         More special device names, regardless of extension or trailing spaces,
         are not allowed on Windows.
@@ -165,24 +173,29 @@
 
     parts = [directory]
 
-    for filename in pathnames:
-        if filename != "":
-            filename = posixpath.normpath(filename)
+    for part in untrusted:
+        if not part:
+            continue
+
+        part = posixpath.normpath(part)
 
         if (
-            any(sep in filename for sep in _os_alt_seps)
+            os.path.isabs(part)
+            # ntpath.isabs doesn't catch this
+            or part.startswith("/")
+            or part == ".."
+            or part.startswith("../")
+            or any(sep in part for sep in _os_alt_seps)
             or (
                 os.name == "nt"
-                and filename.partition(".")[0].strip().upper() in 
_windows_device_files
+                and any(
+                    p.partition(".")[0].strip().upper() in 
_windows_device_files
+                    for p in part.split("/")
+                )
             )
-            or os.path.isabs(filename)
-            # ntpath.isabs doesn't catch this on Python < 3.11
-            or filename.startswith("/")
-            or filename == ".."
-            or filename.startswith("../")
         ):
             return None
 
-        parts.append(filename)
+        parts.append(part)
 
     return posixpath.join(*parts)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/tests/test_security.py 
new/werkzeug-3.1.6/tests/test_security.py
--- old/werkzeug-3.1.5/tests/test_security.py   2026-01-08 18:37:08.000000000 
+0100
+++ new/werkzeug-3.1.6/tests/test_security.py   2026-02-19 16:12:36.000000000 
+0100
@@ -73,7 +73,7 @@
 
 
 @pytest.mark.parametrize(
-    "name", ["CON", "CON.txt", "CON.txt.html", "CON  ", "CON . txt"]
+    "name", ["CON", "CON.txt", "CON.txt.html", "CON  ", "CON . txt", "b/CON"]
 )
 def test_safe_join_windows_special(monkeypatch: pytest.MonkeyPatch, name: str) 
-> None:
     """Windows special device name is not allowed on Windows."""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/werkzeug-3.1.5/uv.lock new/werkzeug-3.1.6/uv.lock
--- old/werkzeug-3.1.5/uv.lock  2026-01-08 18:37:08.000000000 +0100
+++ new/werkzeug-3.1.6/uv.lock  2026-02-19 16:12:36.000000000 +0100
@@ -1938,7 +1938,7 @@
 
 [[package]]
 name = "werkzeug"
-version = "3.1.5"
+version = "3.1.6"
 source = { editable = "." }
 dependencies = [
     { name = "markupsafe" },

Reply via email to