From b926a2c9b0da0b5a66295c68d17412d13275cbff Mon Sep 17 00:00:00 2001 From: Enda Farrell Date: Tue, 5 Feb 2019 14:54:48 +0100 Subject: [PATCH] sanic#1480 Allow negative int/number in path (#1481) * sanic#1480 Allow negative int/number * Rerun ``make beautify`` on this change. --- sanic/router.py | 4 ++-- tests/test_url_building.py | 34 ++++++++++++++++++++++++++++++++-- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/sanic/router.py b/sanic/router.py index 6bb3360c..dcf3aeb5 100644 --- a/sanic/router.py +++ b/sanic/router.py @@ -17,8 +17,8 @@ Parameter = namedtuple("Parameter", ["name", "cast"]) 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 6145b064..d752c8a3 100644 --- a/tests/test_url_building.py +++ b/tests/test_url_building.py @@ -170,11 +170,27 @@ def test_fails_with_int_message(app): 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 test_fails_with_number_message(app): 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):