nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: tokio-rs/mio
Pull request #1790 (2024-05-25 13:17:00)

Fix windows cfg

Thomasdezeeuw: CI should be fixed by #1787.

Patch:
diff --git a/Cargo.toml b/Cargo.toml
index 41d525b..f49297b 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -107,3 +107,6 @@ required-features = ["os-poll", "net"]
 [[example]]
 name = "udp_server"
 required-features = ["os-poll", "net"]
+
+[lints.rust]
+unexpected_cfgs = { level = "warn", check-cfg = ['cfg(mio_unsupported_force_poll_poll)', 'cfg(mio_unsupported_force_waker_pipe)'] }
diff --git a/src/sys/wasi/mod.rs b/src/sys/wasi/mod.rs
index 596d365..e1169d2 100644
--- a/src/sys/wasi/mod.rs
+++ b/src/sys/wasi/mod.rs
@@ -334,7 +334,7 @@ pub(crate) mod event {
             fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
                 f.debug_struct("EventFdReadwrite")
                     .field("nbytes", &self.0.nbytes)
-                    .field("flags", &self.0.flags)
+                    .field("flags", &EventrwflagsDetails(self.0.flags))
                     .finish()
             }
         }


Test patch:
diff --git a/tests/unix_stream.rs b/tests/unix_stream.rs
index 9098b7d..87cfbd1 100644
--- a/tests/unix_stream.rs
+++ b/tests/unix_stream.rs
@@ -356,7 +356,7 @@ fn unix_stream_shutdown_both() {
     let err = stream.write(DATA2).unwrap_err();
     #[cfg(unix)]
     assert_eq!(err.kind(), io::ErrorKind::BrokenPipe);
-    #[cfg(window)]
+    #[cfg(windows)]
     assert_eq!(err.kind(), io::ErrorKind::ConnectionAbroted);
 
     // Close the connection to allow the remote to shutdown
Repository: sanic-org/sanic
Pull request #2980 (2024-06-30 07:55:08)

Bad encoding


Patch:
diff --git a/sanic/http/http1.py b/sanic/http/http1.py
index c6b4662b..5e6e8300 100644
--- a/sanic/http/http1.py
+++ b/sanic/http/http1.py
@@ -221,6 +221,10 @@ class Http(Stream, metaclass=TouchUpMeta):
                 name, value = h = name.lower(), value.lstrip()
 
                 if name in ("content-length", "transfer-encoding"):
+                    if request_body:
+                        raise ValueError(
+                            "Duplicate Content-Length or Transfer-Encoding"
+                        )
                     request_body = True
                 elif name == "connection":
                     self.keep_alive = value.lower() == "keep-alive"


Test patch:
diff --git a/tests/test_http.py b/tests/test_http.py
index 4db6f111..88acb6a5 100644
--- a/tests/test_http.py
+++ b/tests/test_http.py
@@ -165,3 +165,29 @@ def test_invalid_chunk_length(chunk_length, client):
 
     assert b"400 Bad Request" in headers
     assert b"Bad chunked encoding" in body
+
+
+def test_smuggle(client):
+    client.send(
+        """
+        POST /upload HTTP/1.1
+        Content-Length: 5
+        Transfer-Encoding: chunked
+        Transfer-Encoding: xchunked
+
+        5
+        hello
+        0
+
+        GET / HTTP/1.1
+        
+        """  # noqa
+    )
+
+    response = client.recv()
+    num_responses = response.count(b"HTTP/1.1")
+    assert num_responses == 1
+
+    headers, body = response.rsplit(b"\r\n\r\n", 1)
+    assert b"400 Bad Request" in headers
+    assert b"Bad Request" in body
Repository: sanic-org/sanic
Pull request #3009 (2024-11-15 04:09:58)

Fix SanicException `quiet` attribute handling when set to False
Fixes an issue where the `quiet` attribute in `SanicException` would default to the class attribute when set to `False`. This occurs when the subclass `quiet` attribute is `True`. The fix ensures only `None` triggers the fallback.

ahopkins: Excellent. Thanks for the test also! 

Patch:
diff --git a/sanic/exceptions.py b/sanic/exceptions.py
index 1a505f6d..902df9ab 100644
--- a/sanic/exceptions.py
+++ b/sanic/exceptions.py
@@ -72,7 +72,11 @@ class SanicException(Exception):
         status_code = status_code or getattr(
             self.__class__, "status_code", None
         )
-        quiet = quiet or getattr(self.__class__, "quiet", None)
+        quiet = (
+            quiet
+            if quiet is not None
+            else getattr(self.__class__, "quiet", None)
+        )
         headers = headers or getattr(self.__class__, "headers", {})
         if message is None:
             message = self.message


Test patch:
diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py
index 8d931ba4..a7bee78d 100644
--- a/tests/test_exceptions.py
+++ b/tests/test_exceptions.py
@@ -417,6 +417,21 @@ def test_exception_message_attribute():
     assert SanicException("").message == ""
 
 
+def test_exception_quiet_attribute():
+    class SilentException(SanicException):
+        quiet = True
+
+    class NoisyException(SanicException):
+        quiet = False
+
+    assert SilentException().quiet
+    assert not NoisyException().quiet
+    assert SilentException(quiet=True).quiet
+    assert NoisyException(quiet=True).quiet
+    assert not SilentException(quiet=False).quiet
+    assert not NoisyException(quiet=False).quiet
+
+
 def test_request_middleware_exception_on_404(app: Sanic):
     """See https://github.com/sanic-org/sanic/issues/2950"""
     counter = count()
Repository: sanic-org/sanic-ext
Pull request #69 (2022-04-13 06:38:28)

fix: serializer not transfer parameters
serializer not transfer parameters；
serializer 装饰器无法传输请求中的参数；


Patch:
diff --git a/sanic_ext/extras/serializer/decorator.py b/sanic_ext/extras/serializer/decorator.py
index 5457d76..5f0bae0 100644
--- a/sanic_ext/extras/serializer/decorator.py
+++ b/sanic_ext/extras/serializer/decorator.py
@@ -1,15 +1,37 @@
 from functools import wraps
-from inspect import isawaitable
+from inspect import isawaitable, signature
+
+from sanic import response
 
 
 def serializer(func, *, status: int = 200):
+    sig = signature(func)
+    simple = len(sig.parameters) == 2 or (
+        func
+        in (
+            response.HTTPResponse,
+            response.file_stream,
+            response.file,
+            response.html,
+            response.json,
+            response.raw,
+            response.redirect,
+            response.text,
+        )
+    )
+
     def decorator(f):
         @wraps(f)
         async def decorated_function(*args, **kwargs):
             retval = f(*args, **kwargs)
             if isawaitable(retval):
                 retval = await retval
-            return func(retval, status=status)
+
+            if simple:
+                return func(retval, status=status)
+            else:
+                kwargs["status"] = status
+                return func(retval, *args, **kwargs)
 
         return decorated_function
 


Test patch:
diff --git a/tests/extra/test_serializer.py b/tests/extra/test_serializer.py
index c3246c3..fd592c3 100644
--- a/tests/extra/test_serializer.py
+++ b/tests/extra/test_serializer.py
@@ -47,3 +47,24 @@ def test_serializer_with_custom(app):
     _, response = app.test_client.get("/201")
     assert response.status_code == 201
     assert response.content_type == "application/json"
+
+
+def test_serializer_with_params(app):
+    def message(retval, request, action, status):
+        return json(
+            {
+                "request_id": str(request.id),
+                "action": action,
+                "message": retval,
+            },
+            status=status,
+        )
+
+    @app.get("/<action>")
+    @serializer(message)
+    async def do_action(request, action: str):
+        return "This is a message"
+
+    _, response = app.test_client.get("/this")
+    assert response.status_code == 200
+    assert response.json["action"] == "this"
Repository: sanic-org/sanic-ext
Pull request #124 (2022-08-16 12:38:24)

added url_for function for use in Jinja2 templates
Added the `app.url_for` function for use in Jinja2 templates as requested in #87. 

Useful for referencing static files and endpoints in html templates. e.g.
- `{{ url_for('static', filename='styles.css') }}`
- `{{ url_for('dashboard') }}`

`url_for` is available within Jinja2 templates for Flask by default as part of the standard context (https://flask.palletsprojects.com/en/2.2.x/templating/). There may be other useful variables / functions to also add by default. e.g. `session` for logged in user details.

kevinchai: No worries. Just ran the tests with `tox` and fixed the identified errors with the second commit. Re-ran tests and they passed.

Patch:
diff --git a/sanic_ext/extensions/templating/extension.py b/sanic_ext/extensions/templating/extension.py
index f74fb63..d5ad2b8 100644
--- a/sanic_ext/extensions/templating/extension.py
+++ b/sanic_ext/extensions/templating/extension.py
@@ -39,6 +39,7 @@ class TemplatingExtension(Extension):
             bootstrap.templating = Templating(
                 environment=bootstrap.environment, config=self.config
             )
+        bootstrap.templating.environment.globals["url_for"] = self.app.url_for
 
     def label(self):
         return f"jinja2=={__version__}"


Test patch:
diff --git a/tests/extensions/templating/test_templating.py b/tests/extensions/templating/test_templating.py
index 3c554b1..9c9bb68 100644
--- a/tests/extensions/templating/test_templating.py
+++ b/tests/extensions/templating/test_templating.py
@@ -96,3 +96,17 @@ def test_config_templating_dir():
     assert app.ext.templating.environment.get_template(
         "foo.html"
     ).filename == str(Path(__file__).parent / "templates" / "foo.html")
+
+
+def test_url_for():
+    app = Sanic("templating-from-string")
+    app.extend()
+
+    template = r"url: {{ url_for('handler') }}"
+
+    @app.get("/one/two/three")
+    async def handler(_):
+        return await render(template_source=template)
+
+    _, response = app.test_client.get("/one/two/three")
+    assert response.text == "url: /one/two/three"
Repository: sanic-org/sanic-ext
Pull request #176 (2022-12-29 20:06:55)

Do not pass items twice to Array
See #175


Patch:
diff --git a/sanic_ext/extensions/openapi/types.py b/sanic_ext/extensions/openapi/types.py
index 228838f..c86a807 100644
--- a/sanic_ext/extensions/openapi/types.py
+++ b/sanic_ext/extensions/openapi/types.py
@@ -179,6 +179,7 @@ class Schema(Definition):
             kwargs["additionalProperties"] = Schema.make(args[1])
             return Object(**kwargs)
         elif (is_generic(value) or is_generic(_type)) and origin == list:
+            kwargs.pop("items", None)
             return Array(Schema.make(args[0]), **kwargs)
         elif _type is type(Enum):
             available = [item.value for item in value.__members__.values()]


Test patch:
diff --git a/tests/extensions/openapi/test_model_fields.py b/tests/extensions/openapi/test_model_fields.py
index 881f054..7246bce 100644
--- a/tests/extensions/openapi/test_model_fields.py
+++ b/tests/extensions/openapi/test_model_fields.py
@@ -1,4 +1,6 @@
 from dataclasses import dataclass, field
+from typing import List
+from uuid import UUID
 
 import attrs
 import pytest
@@ -12,6 +14,7 @@ from .utils import get_spec
 
 @dataclass
 class FooDataclass:
+    links: List[UUID]
     priority: int = field(
         metadata={"openapi": {"exclusiveMinimum": 1, "exclusiveMaximum": 10}}
     )
@@ -22,6 +25,7 @@ class FooDataclass:
 
 @attrs.define
 class FooAttrs:
+    links: List[UUID]
     priority: int = attrs.field(
         metadata={"openapi": {"exclusiveMinimum": 1, "exclusiveMaximum": 10}}
     )
@@ -31,12 +35,14 @@ class FooAttrs:
 
 
 class FooPydanticBaseModel(BaseModel):
+    links: List[UUID]
     priority: int = Field(gt=1, lt=10)
     ident: str = Field("XXXX", example="ABC123")
 
 
 @pydataclass
 class FooPydanticDataclass:
+    links: List[UUID]
     priority: int = Field(gt=1, lt=10)
     ident: str = Field("XXXX", example="ABC123")
 
@@ -61,6 +67,11 @@ def test_pydantic_base_model(app, Foo):
         "application/json"
     ]["schema"]["properties"]
 
+    assert foo_props["links"] == {
+        "title": "Links",
+        "type": "array",
+        "items": {"type": "string", "format": "uuid"},
+    }
     assert foo_props["ident"] == {
         "title": "Ident",
         "type": "string",
Repository: sanic-org/sanic-ext
Pull request #183 (2023-01-13 01:12:01)

feat: passing exception to extra argument
Passing exception pydantic object as extra argument to write custom messages to the http client.

ahopkins: Thanks. Can you add a test too?
alisonsalmeida: Hello, add test.

Patch:
diff --git a/sanic_ext/extras/validation/validators.py b/sanic_ext/extras/validation/validators.py
index a972df5..42062ca 100644
--- a/sanic_ext/extras/validation/validators.py
+++ b/sanic_ext/extras/validation/validators.py
@@ -25,7 +25,8 @@ def validate_body(
         return validator(model, body)
     except VALIDATION_ERROR as e:
         raise ValidationError(
-            f"Invalid request body: {model.__name__}. Error: {e}"
+            f"Invalid request body: {model.__name__}. Error: {e}",
+            extra={"exception": e},
         )
 
 


Test patch:
diff --git a/tests/extra/test_validation_pydantic.py b/tests/extra/test_validation_pydantic.py
index f9d1bad..149d701 100644
--- a/tests/extra/test_validation_pydantic.py
+++ b/tests/extra/test_validation_pydantic.py
@@ -1,10 +1,12 @@
 from typing import List
 
+import pydantic
 from pydantic.dataclasses import dataclass
 from sanic import json
 from sanic.views import HTTPMethodView
 
 from sanic_ext import validate
+from sanic_ext.exceptions import ValidationError
 
 SNOOPY_DATA = {"name": "Snoopy", "alter_ego": ["Flying Ace", "Joe Cool"]}
 
@@ -110,3 +112,38 @@ def test_validate_query(app):
     assert response.status == 200
     assert response.json["is_search"]
     assert response.json["q"] == "Snoopy"
+
+
+class User(pydantic.BaseModel):
+    name: str
+    age: int
+    email: str
+
+
+def test_success_validate_form_custom_message(app):
+    @app.post("/user")
+    @validate(form=User)
+    async def create_user(request, body: User):
+        return json(body.dict())
+
+    user = {"name": "Alison", "age": 25, "email": "alison@almeida.com"}
+    _, response = app.test_client.post("/user", data=user)
+    assert response.status == 200
+
+
+def test_error_validate_form_custom_message(app):
+    async def server_error_validate_form(request, exception: ValidationError):
+        error = exception.extra["exception"]
+        assert isinstance(error, pydantic.ValidationError)
+        return json(error.json(), status=400)
+
+    @app.post("/user")
+    @validate(form=User)
+    async def create_user(request, body: User):
+        return json(body.dict())
+
+    user = {"name": "Alison", "age": 25}
+
+    app.error_handler.add(ValidationError, server_error_validate_form)
+    _, response = app.test_client.post("/user", data=user)
+    assert response.status == 400
Repository: sanic-org/sanic-ext
Pull request #210 (2023-07-11 08:50:10)

When appropriate use a __func__ handler
This comes from a discussion on the forums where classmethods and instance methods (not from a CBV) would not render as defined routes. This resulted because the bound methods were used as routes, and the definitions stores as functions. This PR will check if the handler does not exist, if there is a `__func__`, and if that `__func__` is defined. In that case, then it will use that as the defined handler and not recreate a default route definition.


Patch:
diff --git a/sanic_ext/extensions/openapi/blueprint.py b/sanic_ext/extensions/openapi/blueprint.py
index 1db9253..82b722f 100644
--- a/sanic_ext/extensions/openapi/blueprint.py
+++ b/sanic_ext/extensions/openapi/blueprint.py
@@ -152,7 +152,14 @@ def blueprint_factory(config: Config):
 
                 if hasattr(_handler, "view_class"):
                     _handler = getattr(_handler.view_class, method.lower())
-                operation = OperationStore()[_handler]
+                store = OperationStore()
+                if (
+                    _handler not in store
+                    and (func := getattr(_handler, "__func__", None))
+                    and func in store
+                ):
+                    _handler = func
+                operation = store[_handler]
 
                 if operation._exclude or "openapi" in operation.tags:
                     continue


Test patch:
diff --git a/tests/extensions/openapi/test_func_handler.py b/tests/extensions/openapi/test_func_handler.py
new file mode 100644
index 0000000..dd24d8b
--- /dev/null
+++ b/tests/extensions/openapi/test_func_handler.py
@@ -0,0 +1,51 @@
+from sanic import Sanic
+from sanic.response import text
+
+from sanic_ext import openapi
+
+from .utils import get_spec
+
+
+def test_func_handlers(app: Sanic):
+    class TestClass:
+        @staticmethod
+        @openapi.definition(
+            summary="staticmethod custom summary",
+            tag="Test",
+        )
+        async def staticmethod_handler(request):
+            return text("...")
+
+        @classmethod
+        @openapi.definition(
+            summary="classmethod custom summary",
+            tag="Test",
+        )
+        async def classmethod_handler(cls, request):
+            return text("...")
+
+        @openapi.definition(
+            summary="instance method custom summary",
+            tag="Test",
+        )
+        async def instance_method_handler(self, request):
+            return text("...")
+
+    app.add_route(TestClass.staticmethod_handler, "/staticmethod")
+    app.add_route(TestClass.classmethod_handler, "/classmethod")
+    app.add_route(TestClass().instance_method_handler, "/instance_method")
+
+    spec = get_spec(app)
+    paths = spec["paths"]
+    assert len(paths) == 3
+    assert (
+        paths["/staticmethod"]["get"]["summary"]
+        == "staticmethod custom summary"
+    )
+    assert (
+        paths["/classmethod"]["get"]["summary"] == "classmethod custom summary"
+    )
+    assert (
+        paths["/instance_method"]["get"]["summary"]
+        == "instance method custom summary"
+    )
Repository: sanic-org/sanic-ext
Pull request #212 (2023-07-14 14:48:09)

Removed uri ending slash trim from the doc paths
https://github.com/sanic-org/sanic-ext/issues/211


Patch:
diff --git a/sanic_ext/extensions/openapi/blueprint.py b/sanic_ext/extensions/openapi/blueprint.py
index 82b722f..16364b5 100644
--- a/sanic_ext/extensions/openapi/blueprint.py
+++ b/sanic_ext/extensions/openapi/blueprint.py
@@ -140,8 +140,6 @@ def blueprint_factory(config: Config):
             # Methods
             # --------------------------------------------------------------- #
 
-            uri = uri if uri == "/" else uri.rstrip("/")
-
             for method, _handler in method_handlers:
                 if (
                     (method == "OPTIONS" and app.config.OAS_IGNORE_OPTIONS)


Test patch:
diff --git a/tests/extensions/openapi/test_paths.py b/tests/extensions/openapi/test_paths.py
new file mode 100644
index 0000000..b394a74
--- /dev/null
+++ b/tests/extensions/openapi/test_paths.py
@@ -0,0 +1,61 @@
+import pytest
+from sanic import Sanic
+
+from .utils import get_spec
+
+
+@pytest.fixture(autouse=True)
+def handlers(app: Sanic):
+    @app.route("/test1")
+    async def handler1(_):
+        ...
+
+    @app.route("/test2/1")
+    async def handler2(_):
+        ...
+
+    @app.route("/test3/")
+    async def handler3(_):
+        ...
+
+    @app.route("/test4/2/")
+    async def handler4(_):
+        ...
+
+
+def test_paths_with_all_uri_filter(app: Sanic):
+    app.config.API_URI_FILTER = "all"
+
+    spec = get_spec(app)
+    assert list(spec["paths"].keys()) == [
+        "/test1",
+        "/test1/",
+        "/test2/1",
+        "/test2/1/",
+        "/test3",
+        "/test3/",
+        "/test4/2",
+        "/test4/2/",
+    ]
+
+
+def test_paths_with_slash_uri_filter(app: Sanic):
+    app.config.API_URI_FILTER = "slash"
+    spec = get_spec(app)
+
+    assert list(spec["paths"].keys()) == [
+        "/test1/",
+        "/test2/1/",
+        "/test3/",
+        "/test4/2/",
+    ]
+
+
+def test_paths_without_uri_filter(app: Sanic):
+    spec = get_spec(app)
+    assert list(spec["paths"].keys()) == [
+        "/test1",
+        "/test2/1",
+        "/test3",
+        "/test4/2",
+    ]
Repository: sanic-org/sanic-ext
Pull request #220 (2023-07-25 21:12:51)

Replaced default list server variables with object
Closes https://github.com/sanic-org/sanic-ext/issues/214


Patch:
diff --git a/sanic_ext/extensions/openapi/definitions.py b/sanic_ext/extensions/openapi/definitions.py
index af20519..7603386 100644
--- a/sanic_ext/extensions/openapi/definitions.py
+++ b/sanic_ext/extensions/openapi/definitions.py
@@ -352,7 +352,7 @@ class Server(Definition):
         variables: Optional[Dict[str, Any]] = None,
     ):
         super().__init__(
-            url=url, description=description, variables=variables or []
+            url=url, description=description, variables=variables or {}
         )
 
 


Test patch:
diff --git a/tests/extensions/openapi/test_definitions.py b/tests/extensions/openapi/test_definitions.py
index ae9f7af..23f75a1 100644
--- a/tests/extensions/openapi/test_definitions.py
+++ b/tests/extensions/openapi/test_definitions.py
@@ -2,6 +2,7 @@ from typing import Optional
 
 import pytest
 
+from sanic_ext.extensions.openapi.definitions import Server
 from sanic_ext.extensions.openapi.types import Definition
 
 
@@ -45,3 +46,11 @@ def test_serialize_no_nullable(Thing):
     assert serialized["name"] == "ok"
     assert "foo" not in serialized
     assert "bar" not in serialized
+
+
+def test_server_definitions_defaults():
+    assert Server(url="url").fields == {
+        "url": "url",
+        "description": None,
+        "variables": {},
+    }