diff --git a/sanic/router.py b/sanic/router.py index 6bb3360ce4..dcf3aeb5ec 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -17,8 +17,8 @@ REGEX_TYPES = { "string": (str, r"[^/]+"), - "int": (int, r"\d+"), - "number": (float, r"[0-9\\.]+"), + "int": (int, r"-?\d+"), + "number": (float, r"-?[0-9\\.]+"), "alpha": (str, r"[A-Za-z]+"), "path": (str, r"[^/].*?"), "uuid": ( diff --git a/tests/test_url_building.py b/tests/test_url_building.py index 6145b06462..d752c8a351 100644 --- a/tests/test_url_building.py +++ b/tests/test_url_building.py @@ -170,11 +170,27 @@ def fail(request): expected_error = ( 'Value "not_int" for parameter `foo` ' - "does not match pattern for type `int`: \d+" + "does not match pattern for type `int`: -?\d+" ) assert str(e.value) == expected_error +def test_passes_with_negative_int_message(app): + @app.route("path//another-word") + def good(request, possibly_neg): + assert isinstance(possibly_neg, int) + return text("this should pass with `{}`".format(possibly_neg)) + + u_plus_3 = app.url_for("good", possibly_neg=3) + assert u_plus_3 == "/path/3/another-word", u_plus_3 + request, response = app.test_client.get(u_plus_3) + assert response.text == "this should pass with `3`" + u_neg_3 = app.url_for("good", possibly_neg=-3) + assert u_neg_3 == "/path/-3/another-word", u_neg_3 + request, response = app.test_client.get(u_neg_3) + assert response.text == "this should pass with `-3`" + + def test_fails_with_two_letter_string_message(app): @app.route(COMPLEX_PARAM_URL) def fail(request): @@ -207,12 +223,26 @@ def fail(request): expected_error = ( 'Value "foo" for parameter `some_number` ' - "does not match pattern for type `float`: [0-9\\\\.]+" + "does not match pattern for type `float`: -?[0-9\\\\.]+" ) assert str(e.value) == expected_error +@pytest.mark.parametrize("number", [3, -3, 13.123, -13.123]) +def test_passes_with_negative_number_message(app, number): + @app.route("path//another-word") + def good(request, possibly_neg): + assert isinstance(possibly_neg, (int, float)) + return text("this should pass with `{}`".format(possibly_neg)) + + u = app.url_for("good", possibly_neg=number) + assert u == "/path/{}/another-word".format(number), u + request, response = app.test_client.get(u) + # For ``number``, it has been cast to a float - so a ``3`` becomes a ``3.0`` + assert response.text == "this should pass with `{}`".format(float(number)) + + def test_adds_other_supplied_values_as_query_string(app): @app.route(COMPLEX_PARAM_URL) def passes(request):