nebius/SWE-bench-extra huggingface dataset:
Repository: marshmallow-code/apispec-webframeworks

Issue:
Bottle plugin path regex bug when using argument type in the url
<a href="https://github.com/genbits"><img src="https://avatars0.githubusercontent.com/u/3424362?v=4" align="left" width="96" height="96" hspace="10"></img></a> **Issue by [genbits](https://github.com/genbits)**
_Monday May 21, 2018 at 10:56 GMT_
_Originally opened as https://github.com/marshmallow-code/apispec/issues/215_

----

When parsing the path of a bottle app in the form: `/path/to/<resourceId:int>`, the generated API path becomes `/path/to/{int}`.

reproduce:

    import re
    RE_URL = re.compile(r'<(?:[^:<>]+:)?([^<>]+)>')
    path = '/path/to/<resourceId:int>'
    RE_URL.sub(r'{\1}', path)  # --> '/path/to/{int}'

This can be fixed easily by replacing RE_URL with: `re.compile(r'<([^:]+)(?::.+)?>')`



Comments:

Patch:
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index b42ae4a..86f2842 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -1,6 +1,12 @@
 Changelog
 ---------
 
+0.5.2 (unreleased)
+++++++++++++++++++
+
+* BottlePlugin: Fix support for typed path arguments (:issue:`16`).
+  Thanks :user:`genbits` for reporting and thanks :user:`elfjes` for the fix.
+
 0.5.1 (2019-11-18)
 ++++++++++++++++++
 
diff --git a/src/apispec_webframeworks/bottle.py b/src/apispec_webframeworks/bottle.py
index 4ed5327..b1bbbcf 100644
--- a/src/apispec_webframeworks/bottle.py
+++ b/src/apispec_webframeworks/bottle.py
@@ -27,8 +27,8 @@ from bottle import default_app
 from apispec import BasePlugin, yaml_utils
 from apispec.exceptions import APISpecError
 
+RE_URL = re.compile(r"<([^<>:]+):?[^>]*>")
 
-RE_URL = re.compile(r"<(?:[^:<>]+:)?([^<>]+)>")
 
 _default_app = default_app()
 


Test patch:
diff --git a/src/apispec_webframeworks/tests/test_ext_bottle.py b/src/apispec_webframeworks/tests/test_ext_bottle.py
index bbaf116..47c168a 100644
--- a/src/apispec_webframeworks/tests/test_ext_bottle.py
+++ b/src/apispec_webframeworks/tests/test_ext_bottle.py
@@ -99,10 +99,13 @@ class TestPathHelpers:
         spec.path(view=get_pet)
         assert "/pet/{pet_id}" in get_paths(spec)
 
-    def test_path_with_params(self, spec):
-        @route("/pet/<pet_id>/<shop_id>", methods=["POST"])
-        def set_pet():
-            return "new pet!"
+    @pytest.mark.parametrize(
+        "path", ["/pet/<pet_id:int>/<shop_id:re:[a-z]+>", "/pet/<pet_id>/<shop_id>"],
+    )
+    def test_path_with_params(self, spec, path):
+        @route(path, methods=["GET"])
+        def handler():
+            pass
 
-        spec.path(view=set_pet)
+        spec.path(view=handler)
         assert "/pet/{pet_id}/{shop_id}" in get_paths(spec)
Repository: marshmallow-code/flask-smorest

Issue:
Inconsistent order of parameters when using rule.arguments from werkzeug inside FlaskPlugin
I'm using this with flask-smorest. In https://flask-smorest.readthedocs.io/en/latest/openapi.html#enforce-order-in-openapi-specification-file, you say to use "ordered = True" so they're ordered and I can do snapshot-testing on the openapi json output.

~~But in this line:https://github.com/marshmallow-code/apispec/blob/dev/src/apispec/ext/marshmallow/common.py#L54, `schema._declared_fields` is not an ordered dict, but a simple dict. The `schema.fields` is ordered though.~~

~~Do you have any idea how to fix this even with classes instead of just objects?~~

See https://github.com/marshmallow-code/flask-smorest/issues/541 for correct issue

Regards,
Dorian


Comments:

Patch:
diff --git a/AUTHORS.rst b/AUTHORS.rst
index 5eb59fa..6af896f 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -26,3 +26,4 @@ Contributors (chronological)
 - Dmitry Erlikh `@derlikh-smart <https://github.com/derlikh-smart>`_
 - 0x78f1935 `@0x78f1935 <https://github.com/0x78f1935>`_
 - One Codex, Inc. `@onecodex <https://github.com/onecodex>`_
+- Dorian Hoxha `@ddorian <https://github.com/ddorian>`_
diff --git a/flask_smorest/spec/plugins.py b/flask_smorest/spec/plugins.py
index e235992..cbafe16 100644
--- a/flask_smorest/spec/plugins.py
+++ b/flask_smorest/spec/plugins.py
@@ -110,7 +110,11 @@ class FlaskPlugin(BasePlugin):
     def rule_to_params(self, rule):
         """Get parameters from flask Rule"""
         params = []
-        for argument in [a for a in rule.arguments if a not in rule.defaults]:
+        for argument in [
+            a
+            for is_dynamic, a in rule._trace
+            if is_dynamic is True and a not in rule.defaults
+        ]:
             param = {
                 "in": "path",
                 "name": argument,


Test patch:
diff --git a/tests/test_spec.py b/tests/test_spec.py
index 33eace7..ea0ceb4 100644
--- a/tests/test_spec.py
+++ b/tests/test_spec.py
@@ -35,6 +35,27 @@ class TestAPISpec:
             assert "produces" not in spec
             assert "consumes" not in spec
 
+    @pytest.mark.parametrize("openapi_version", ["2.0", "3.0.2"])
+    def test_apispec_correct_path_parameters_ordering(self, app, openapi_version):
+        """Test path parameters are sorted from left to right.
+
+        If this test is flaky it's considered a failure.
+        """
+        app.config["OPENAPI_VERSION"] = openapi_version
+        api = Api(app)
+
+        blp = Blueprint("pets", "pets", url_prefix="/pets")
+
+        @blp.route("/project/<project_id>/upload/<part_id>/complete")
+        def do_nothing():
+            return
+
+        api.register_blueprint(blp)
+
+        sorted_params = list(api.spec.to_dict()["paths"].values())[0]["parameters"]
+        assert sorted_params[0]["name"] == "project_id"
+        assert sorted_params[1]["name"] == "part_id"
+
     @pytest.mark.parametrize("openapi_version", ["2.0", "3.0.2"])
     def test_apispec_lazy_registers_error_responses(self, app, openapi_version):
         """Test error responses are registered"""