@@ -40,19 +40,24 @@ class Unresolver:
40
40
# - /en/latest/
41
41
# - /en/latest/file/name/
42
42
multiversion_pattern = re .compile (
43
- r"^/(?P<language>{lang_slug})(/((?P<version>{version_slug})(/(?P<file>{filename_slug}))?)?)?$" .format ( # noqa
44
- ** pattern_opts
45
- )
43
+ r"""
44
+ ^/(?P<language>{lang_slug}) # Must have the language slug.
45
+ (/((?P<version>{version_slug})(/(?P<file>{filename_slug}))?)?)?$ # Optionally a version followed by a file. # noqa
46
+ """ .format (** pattern_opts ),
47
+ re .VERBOSE ,
46
48
)
47
49
48
50
# This pattern matches:
49
51
# - /projects/subproject
50
52
# - /projects/subproject/
51
53
# - /projects/subproject/file/name/
52
54
subproject_pattern = re .compile (
53
- r"^/projects/(?P<project>{project_slug}+)(/(?P<file>{filename_slug}))?$" .format (
54
- ** pattern_opts
55
- )
55
+ r"""
56
+ ^/projects/ # Must have the `projects` prefix.
57
+ (?P<project>{project_slug}+) # Followed by the subproject alias.
58
+ (/(?P<file>{filename_slug}))?$ # Optionally a filename, which will be recursively resolved.
59
+ """ .format (** pattern_opts ),
60
+ re .VERBOSE ,
56
61
)
57
62
58
63
def unresolve (self , url , add_index = True ):
@@ -68,17 +73,17 @@ def unresolve(self, url, add_index=True):
68
73
"""
69
74
parsed = urlparse (url )
70
75
domain = self .get_domain_from_host (parsed .netloc )
71
- project_slug , domain_object , external_version_slug = self .unresolve_domain (
76
+ parent_project_slug , domain_object , external_version_slug = self .unresolve_domain (
72
77
domain
73
78
)
74
- if not project_slug :
79
+ if not parent_project_slug :
75
80
return None
76
81
77
- parent_project = Project .objects .filter (slug = project_slug ).first ()
82
+ parent_project = Project .objects .filter (slug = parent_project_slug ).first ()
78
83
if not parent_project :
79
84
return None
80
85
81
- project , version , filename = self ._unresolve_path (
86
+ current_project , version , filename = self ._unresolve_path (
82
87
parent_project = parent_project ,
83
88
path = parsed .path ,
84
89
)
@@ -109,7 +114,7 @@ def unresolve(self, url, add_index=True):
109
114
110
115
return UnresolvedURL (
111
116
parent_project = parent_project ,
112
- project = project or parent_project ,
117
+ project = current_project or parent_project ,
113
118
version = version ,
114
119
filename = filename ,
115
120
parsed_url = parsed ,
@@ -131,6 +136,10 @@ def _match_multiversion_project(self, parent_project, path):
131
136
132
137
If the translation exists, we return a result even if the version doesn't,
133
138
so the translation is taken as the current project (useful for 404 pages).
139
+
140
+ :returns: None or a tuple with the current project, version and file.
141
+ A tuple with only the project means we weren't able to find a version,
142
+ but the translation was correct.
134
143
"""
135
144
match = self .multiversion_pattern .match (path )
136
145
if not match :
@@ -162,15 +171,19 @@ def _match_subproject(self, parent_project, path):
162
171
163
172
If the subproject exists, we return a result even if version doesn't,
164
173
so the subproject is taken as the current project (useful for 404 pages).
174
+
175
+ :returns: None or a tuple with the current project, version and file.
176
+ A tuple with only the project means we were able to find the subproject,
177
+ but we weren't able to resolve the rest of the path.
165
178
"""
166
179
match = self .subproject_pattern .match (path )
167
180
if not match :
168
181
return None
169
182
170
- project_slug = match .group ("project" )
183
+ subproject_alias = match .group ("project" )
171
184
file = self ._normalize_filename (match .group ("file" ))
172
185
project_relationship = (
173
- parent_project .subprojects .filter (alias = project_slug )
186
+ parent_project .subprojects .filter (alias = subproject_alias )
174
187
.prefetch_related ("child" )
175
188
.first ()
176
189
)
@@ -215,10 +228,19 @@ def _unresolve_path(self, parent_project, path, check_subprojects=True):
215
228
If the returned version is `None`, then we weren't able to
216
229
unresolve the path into a valid version of the project.
217
230
231
+ The checks are done in the following order:
232
+
233
+ - Check for multiple versions if the parent project
234
+ isn't a single version project.
235
+ - Check for subprojects.
236
+ - Check for single versions if the parent project isn’t
237
+ a multi version project.
238
+
218
239
:param parent_project: The project that owns the path.
219
240
:param path: The path to unresolve.
220
241
:param check_subprojects: If we should check for subprojects,
221
- this is used to call this function recursively.
242
+ this is used to call this function recursively when
243
+ resolving the path from a subproject (we don't support subprojects of subprojects).
222
244
223
245
:returns: A tuple with: project, version, and file name.
224
246
"""
0 commit comments