Skip to content

Commit 4d41069

Browse files
committed
Updates from review from #9500
1 parent 8fad146 commit 4d41069

File tree

1 file changed

+36
-14
lines changed

1 file changed

+36
-14
lines changed

readthedocs/core/unresolver.py

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,24 @@ class Unresolver:
4040
# - /en/latest/
4141
# - /en/latest/file/name/
4242
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,
4648
)
4749

4850
# This pattern matches:
4951
# - /projects/subproject
5052
# - /projects/subproject/
5153
# - /projects/subproject/file/name/
5254
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,
5661
)
5762

5863
def unresolve(self, url, add_index=True):
@@ -68,17 +73,17 @@ def unresolve(self, url, add_index=True):
6873
"""
6974
parsed = urlparse(url)
7075
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(
7277
domain
7378
)
74-
if not project_slug:
79+
if not parent_project_slug:
7580
return None
7681

77-
parent_project = Project.objects.filter(slug=project_slug).first()
82+
parent_project = Project.objects.filter(slug=parent_project_slug).first()
7883
if not parent_project:
7984
return None
8085

81-
project, version, filename = self._unresolve_path(
86+
current_project, version, filename = self._unresolve_path(
8287
parent_project=parent_project,
8388
path=parsed.path,
8489
)
@@ -109,7 +114,7 @@ def unresolve(self, url, add_index=True):
109114

110115
return UnresolvedURL(
111116
parent_project=parent_project,
112-
project=project or parent_project,
117+
project=current_project or parent_project,
113118
version=version,
114119
filename=filename,
115120
parsed_url=parsed,
@@ -131,6 +136,10 @@ def _match_multiversion_project(self, parent_project, path):
131136
132137
If the translation exists, we return a result even if the version doesn't,
133138
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.
134143
"""
135144
match = self.multiversion_pattern.match(path)
136145
if not match:
@@ -162,15 +171,19 @@ def _match_subproject(self, parent_project, path):
162171
163172
If the subproject exists, we return a result even if version doesn't,
164173
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.
165178
"""
166179
match = self.subproject_pattern.match(path)
167180
if not match:
168181
return None
169182

170-
project_slug = match.group("project")
183+
subproject_alias = match.group("project")
171184
file = self._normalize_filename(match.group("file"))
172185
project_relationship = (
173-
parent_project.subprojects.filter(alias=project_slug)
186+
parent_project.subprojects.filter(alias=subproject_alias)
174187
.prefetch_related("child")
175188
.first()
176189
)
@@ -215,10 +228,19 @@ def _unresolve_path(self, parent_project, path, check_subprojects=True):
215228
If the returned version is `None`, then we weren't able to
216229
unresolve the path into a valid version of the project.
217230
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+
218239
:param parent_project: The project that owns the path.
219240
:param path: The path to unresolve.
220241
: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).
222244
223245
:returns: A tuple with: project, version, and file name.
224246
"""

0 commit comments

Comments
 (0)