1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
from unittest import mock
import pytest
import django
from django.utils.translation import pgettext_lazy
# django<2.0 has only `url` with regex based patterns.
# django>=2.0 renames `url` to `re_path`, and additionally introduces `path`
# for new style URL patterns, e.g. <int:article_id>.
if django.VERSION >= (2, 0):
from django.urls import path, re_path
from django.urls.converters import PathConverter
from django.conf.urls import include
else:
from django.conf.urls import url as re_path, include
if django.VERSION < (1, 9):
included_url_conf = (re_path(r"^foo/bar/(?P<param>[\w]+)", lambda x: ""),), "", ""
else:
included_url_conf = ((re_path(r"^foo/bar/(?P<param>[\w]+)", lambda x: ""),), "")
from sentry_sdk.integrations.django.transactions import RavenResolver
example_url_conf = (
re_path(r"^api/(?P<project_id>[\w_-]+)/store/$", lambda x: ""),
re_path(r"^api/(?P<version>(v1|v2))/author/$", lambda x: ""),
re_path(
r"^api/(?P<project_id>[^\/]+)/product/(?P<pid>(?:\d+|[A-Fa-f0-9-]{32,36}))/$",
lambda x: "",
),
re_path(r"^report/", lambda x: ""),
re_path(r"^example/", include(included_url_conf)),
)
def test_resolver_no_match():
resolver = RavenResolver()
result = resolver.resolve("/foo/bar", example_url_conf)
assert result is None
def test_resolver_re_path_complex_match():
resolver = RavenResolver()
result = resolver.resolve("/api/1234/store/", example_url_conf)
assert result == "/api/{project_id}/store/"
def test_resolver_re_path_complex_either_match():
resolver = RavenResolver()
result = resolver.resolve("/api/v1/author/", example_url_conf)
assert result == "/api/{version}/author/"
result = resolver.resolve("/api/v2/author/", example_url_conf)
assert result == "/api/{version}/author/"
def test_resolver_re_path_included_match():
resolver = RavenResolver()
result = resolver.resolve("/example/foo/bar/baz", example_url_conf)
assert result == "/example/foo/bar/{param}"
def test_resolver_re_path_multiple_groups():
resolver = RavenResolver()
result = resolver.resolve(
"/api/myproject/product/cb4ef1caf3554c34ae134f3c1b3d605f/", example_url_conf
)
assert result == "/api/{project_id}/product/{pid}/"
@pytest.mark.skipif(
django.VERSION < (2, 0),
reason="Django>=2.0 required for <converter:parameter> patterns",
)
def test_resolver_path_group():
url_conf = (path("api/v2/<int:project_id>/store/", lambda x: ""),)
resolver = RavenResolver()
result = resolver.resolve("/api/v2/1234/store/", url_conf)
assert result == "/api/v2/{project_id}/store/"
@pytest.mark.skipif(
django.VERSION < (2, 0),
reason="Django>=2.0 required for <converter:parameter> patterns",
)
def test_resolver_path_multiple_groups():
url_conf = (path("api/v2/<str:project_id>/product/<int:pid>", lambda x: ""),)
resolver = RavenResolver()
result = resolver.resolve("/api/v2/myproject/product/5689", url_conf)
assert result == "/api/v2/{project_id}/product/{pid}"
@pytest.mark.skipif(
django.VERSION < (2, 0),
reason="Django>=2.0 required for <converter:parameter> patterns",
)
@pytest.mark.skipif(
django.VERSION > (5, 1),
reason="get_converter removed in 5.1",
)
def test_resolver_path_complex_path_legacy():
class CustomPathConverter(PathConverter):
regex = r"[^/]+(/[^/]+){0,2}"
with mock.patch(
"django.urls.resolvers.get_converter",
return_value=CustomPathConverter,
):
url_conf = (path("api/v3/<custom_path:my_path>", lambda x: ""),)
resolver = RavenResolver()
result = resolver.resolve("/api/v3/abc/def/ghi", url_conf)
assert result == "/api/v3/{my_path}"
@pytest.mark.skipif(
django.VERSION < (5, 1),
reason="get_converters is used in 5.1",
)
def test_resolver_path_complex_path():
class CustomPathConverter(PathConverter):
regex = r"[^/]+(/[^/]+){0,2}"
with mock.patch(
"django.urls.resolvers.get_converters",
return_value={"custom_path": CustomPathConverter},
):
url_conf = (path("api/v3/<custom_path:my_path>", lambda x: ""),)
resolver = RavenResolver()
result = resolver.resolve("/api/v3/abc/def/ghi", url_conf)
assert result == "/api/v3/{my_path}"
@pytest.mark.skipif(
django.VERSION < (2, 0),
reason="Django>=2.0 required for <converter:parameter> patterns",
)
def test_resolver_path_no_converter():
url_conf = (path("api/v4/<project_id>", lambda x: ""),)
resolver = RavenResolver()
result = resolver.resolve("/api/v4/myproject", url_conf)
assert result == "/api/v4/{project_id}"
@pytest.mark.skipif(
django.VERSION < (2, 0),
reason="Django>=2.0 required for path patterns",
)
def test_resolver_path_with_i18n():
url_conf = (path(pgettext_lazy("url", "pgettext"), lambda x: ""),)
resolver = RavenResolver()
result = resolver.resolve("/pgettext", url_conf)
assert result == "/pgettext"
|