Skip to content
Projeler
Gruplar
Parçacıklar
Yardım
Yükleniyor...
Oturum aç / Kaydol
Gezinmeyi değiştir
D
django
Proje
Proje
Ayrıntılar
Etkinlik
Cycle Analytics
Depo (repository)
Depo (repository)
Dosyalar
Kayıtlar (commit)
Dallar (branch)
Etiketler
Katkıda bulunanlar
Grafik
Karşılaştır
Grafikler
Konular (issue)
0
Konular (issue)
0
Liste
Pano
Etiketler
Kilometre Taşları
Birleştirme (merge) Talepleri
0
Birleştirme (merge) Talepleri
0
CI / CD
CI / CD
İş akışları (pipeline)
İşler
Zamanlamalar
Grafikler
Paketler
Paketler
Wiki
Wiki
Parçacıklar
Parçacıklar
Üyeler
Üyeler
Collapse sidebar
Close sidebar
Etkinlik
Grafik
Grafikler
Yeni bir konu (issue) oluştur
İşler
Kayıtlar (commit)
Konu (issue) Panoları
Kenar çubuğunu aç
Batuhan Osman TASKAYA
django
Commits
f0ef0c49
Kaydet (Commit)
f0ef0c49
authored
May 30, 2016
tarafından
Ketan Bhatt
Kaydeden (comit)
Tim Graham
Ock 03, 2017
Dosyalara gözat
Seçenekler
Dosyalara Gözat
İndir
Eposta Yamaları
Sade Fark
Fixed #26621 -- Corrected simplify_regex()'s handling of named capture groups.
üst
fd2f7e47
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
102 additions
and
12 deletions
+102
-12
utils.py
django/contrib/admindocs/utils.py
+91
-0
views.py
django/contrib/admindocs/views.py
+6
-12
test_views.py
tests/admin_docs/test_views.py
+5
-0
No files found.
django/contrib/admindocs/utils.py
Dosyayı görüntüle @
f0ef0c49
...
...
@@ -144,3 +144,94 @@ if docutils_is_available:
for
name
,
urlbase
in
ROLES
.
items
():
create_reference_role
(
name
,
urlbase
)
# Match the beginning of a named or unnamed group.
named_group_matcher
=
re
.
compile
(
r'\(\?P(<\w+>)'
)
unnamed_group_matcher
=
re
.
compile
(
r'\('
)
def
replace_named_groups
(
pattern
):
r"""
Find named groups in `pattern` and replace them with the group name. E.g.,
1. ^(?P<a>\w+)/b/(\w+)$ ==> ^<a>/b/(\w+)$
2. ^(?P<a>\w+)/b/(?P<c>\w+)/$ ==> ^<a>/b/<c>/$
"""
named_group_indices
=
[
(
m
.
start
(
0
),
m
.
end
(
0
),
m
.
group
(
1
))
for
m
in
named_group_matcher
.
finditer
(
pattern
)
]
# Tuples of (named capture group pattern, group name).
group_pattern_and_name
=
[]
# Loop over the groups and their start and end indices.
for
start
,
end
,
group_name
in
named_group_indices
:
# Handle nested parentheses, e.g. '^(?P<a>(x|y))/b'.
unmatched_open_brackets
,
prev_char
=
1
,
None
for
idx
,
val
in
enumerate
(
list
(
pattern
[
end
:])):
# If brackets are balanced, the end of the string for the current
# named capture group pattern has been reached.
if
unmatched_open_brackets
==
0
:
group_pattern_and_name
.
append
((
pattern
[
start
:
end
+
idx
],
group_name
))
break
# Check for unescaped `(` and `)`. They mark the start and end of a
# nested group.
if
val
==
'('
and
prev_char
!=
'
\\
'
:
unmatched_open_brackets
+=
1
elif
val
==
')'
and
prev_char
!=
'
\\
'
:
unmatched_open_brackets
-=
1
prev_char
=
val
# Replace the string for named capture groups with their group names.
for
group_pattern
,
group_name
in
group_pattern_and_name
:
pattern
=
pattern
.
replace
(
group_pattern
,
group_name
)
return
pattern
def
replace_unnamed_groups
(
pattern
):
r"""
Find unnamed groups in `pattern` and replace them with '<var>'. E.g.,
1. ^(?P<a>\w+)/b/(\w+)$ ==> ^(?P<a>\w+)/b/<var>$
2. ^(?P<a>\w+)/b/((x|y)\w+)$ ==> ^(?P<a>\w+)/b/<var>$
"""
unnamed_group_indices
=
[
m
.
start
(
0
)
for
m
in
unnamed_group_matcher
.
finditer
(
pattern
)]
# Indices of the start of unnamed capture groups.
group_indices
=
[]
# Loop over the start indices of the groups.
for
start
in
unnamed_group_indices
:
# Handle nested parentheses, e.g. '^b/((x|y)\w+)$'.
unmatched_open_brackets
,
prev_char
=
1
,
None
for
idx
,
val
in
enumerate
(
list
(
pattern
[
start
+
1
:])):
if
unmatched_open_brackets
==
0
:
group_indices
.
append
((
start
,
start
+
1
+
idx
))
break
# Check for unescaped `(` and `)`. They mark the start and end of
# a nested group.
if
val
==
'('
and
prev_char
!=
'
\\
'
:
unmatched_open_brackets
+=
1
elif
val
==
')'
and
prev_char
!=
'
\\
'
:
unmatched_open_brackets
-=
1
prev_char
=
val
# Remove unnamed group matches inside other unnamed capture groups.
group_start_end_indices
=
[]
prev_end
=
None
for
start
,
end
in
group_indices
:
if
prev_end
and
start
>
prev_end
or
not
prev_end
:
group_start_end_indices
.
append
((
start
,
end
))
prev_end
=
end
if
group_start_end_indices
:
# Replace unnamed groups with <var>. Handle the fact that replacing the
# string between indices will change string length and thus indices
# will point to the wrong substring if not corrected.
final_pattern
,
prev_end
=
[],
None
for
start
,
end
in
group_start_end_indices
:
if
prev_end
:
final_pattern
.
append
(
pattern
[
prev_end
:
start
])
final_pattern
.
append
(
pattern
[:
start
]
+
'<var>'
)
prev_end
=
end
final_pattern
.
append
(
pattern
[
prev_end
:])
return
''
.
join
(
final_pattern
)
else
:
return
pattern
django/contrib/admindocs/views.py
Dosyayı görüntüle @
f0ef0c49
import
inspect
import
os
import
re
from
importlib
import
import_module
from
django.apps
import
apps
...
...
@@ -8,6 +7,9 @@ from django.conf import settings
from
django.contrib
import
admin
from
django.contrib.admin.views.decorators
import
staff_member_required
from
django.contrib.admindocs
import
utils
from
django.contrib.admindocs.utils
import
(
replace_named_groups
,
replace_unnamed_groups
,
)
from
django.core.exceptions
import
ImproperlyConfigured
,
ViewDoesNotExist
from
django.db
import
models
from
django.http
import
Http404
...
...
@@ -426,24 +428,16 @@ def extract_views_from_urlpatterns(urlpatterns, base='', namespace=None):
return
views
named_group_matcher
=
re
.
compile
(
r'\(\?P(<\w+>).+?\)'
)
non_named_group_matcher
=
re
.
compile
(
r'\(.*?\)'
)
def
simplify_regex
(
pattern
):
r"""
Clean up urlpattern regexes into something more readable by humans. For
example, turn "^(?P<sport_slug>\w+)/athletes/(?P<athlete_slug>\w+)/$"
into "/<sport_slug>/athletes/<athlete_slug>/".
"""
# handle named groups first
pattern
=
named_group_matcher
.
sub
(
lambda
m
:
m
.
group
(
1
),
pattern
)
# handle non-named groups
pattern
=
non_named_group_matcher
.
sub
(
"<var>"
,
pattern
)
pattern
=
replace_named_groups
(
pattern
)
pattern
=
replace_unnamed_groups
(
pattern
)
# clean up any outstanding regex-y characters.
pattern
=
pattern
.
replace
(
'^'
,
''
)
.
replace
(
'$'
,
''
)
.
replace
(
'?'
,
''
)
.
replace
(
'//'
,
'/'
)
.
replace
(
'
\\
'
,
''
)
pattern
=
pattern
.
replace
(
'^'
,
''
)
.
replace
(
'$'
,
''
)
if
not
pattern
.
startswith
(
'/'
):
pattern
=
'/'
+
pattern
return
pattern
tests/admin_docs/test_views.py
Dosyayı görüntüle @
f0ef0c49
...
...
@@ -335,6 +335,11 @@ class AdminDocViewFunctionsTests(SimpleTestCase):
(
r'^a'
,
'/a'
),
(
r'^(?P<a>\w+)/b/(?P<c>\w+)/$'
,
'/<a>/b/<c>/'
),
(
r'^(?P<a>\w+)/b/(?P<c>\w+)$'
,
'/<a>/b/<c>'
),
(
r'^(?P<a>\w+)/b/(\w+)$'
,
'/<a>/b/<var>'
),
(
r'^(?P<a>\w+)/b/((x|y)\w+)$'
,
'/<a>/b/<var>'
),
(
r'^(?P<a>(x|y))/b/(?P<c>\w+)$'
,
'/<a>/b/<c>'
),
(
r'^(?P<a>(x|y))/b/(?P<c>\w+)ab'
,
'/<a>/b/<c>ab'
),
(
r'^(?P<a>(x|y)(\(|\)))/b/(?P<c>\w+)ab'
,
'/<a>/b/<c>ab'
),
)
for
pattern
,
output
in
tests
:
self
.
assertEqual
(
simplify_regex
(
pattern
),
output
)
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment