Skip to content

Commit 819f88c

Browse files
authored
Select renderer based on description_content_type (#3296)
1 parent 155a25d commit 819f88c

File tree

3 files changed

+84
-24
lines changed

3 files changed

+84
-24
lines changed

tests/unit/test_filters.py

Lines changed: 67 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,9 @@ def test_camo_url():
3535

3636
class TestReadmeRender:
3737

38-
def test_can_render(self, monkeypatch):
39-
monkeypatch.setattr(
40-
readme_renderer.rst,
41-
"render",
42-
lambda raw: "rendered",
43-
)
38+
def test_can_render_rst(self, monkeypatch):
39+
renderer = pretend.call_recorder(lambda raw: "rendered")
40+
monkeypatch.setattr(readme_renderer.rst, "render", renderer)
4441

4542
ctx = {
4643
"request": pretend.stub(
@@ -53,15 +50,18 @@ def test_can_render(self, monkeypatch):
5350
),
5451
}
5552

56-
result = filters.readme(ctx, "raw thing", format="rst")
53+
result = filters.readme(
54+
ctx, "raw thing", description_content_type="text/x-rst",
55+
)
5756

5857
assert result == jinja2.Markup("rendered")
58+
assert renderer.calls == [pretend.call('raw thing')]
5959

60-
def test_cant_render(self, monkeypatch):
61-
monkeypatch.setattr(readme_renderer.rst, "render", lambda raw: None)
62-
monkeypatch.setattr(
63-
readme_renderer.txt, "render", lambda raw: "rendered<br>thing",
64-
)
60+
def test_cant_render_rst(self, monkeypatch):
61+
rst_renderer = pretend.call_recorder(lambda raw: None)
62+
txt_renderer = pretend.call_recorder(lambda raw: "rendered<br>thing")
63+
monkeypatch.setattr(readme_renderer.rst, "render", rst_renderer)
64+
monkeypatch.setattr(readme_renderer.txt, "render", txt_renderer)
6565

6666
ctx = {
6767
"request": pretend.stub(
@@ -74,9 +74,57 @@ def test_cant_render(self, monkeypatch):
7474
),
7575
}
7676

77-
result = filters.readme(ctx, "raw thing", format="rst")
77+
result = filters.readme(
78+
ctx, "raw thing", description_content_type="text/x-rst",
79+
)
7880

7981
assert result == jinja2.Markup("rendered<br>thing")
82+
assert rst_renderer.calls == [pretend.call('raw thing')]
83+
assert txt_renderer.calls == [pretend.call('raw thing')]
84+
85+
def test_can_render_plaintext(self, monkeypatch):
86+
renderer = pretend.call_recorder(lambda raw: "rendered")
87+
monkeypatch.setattr(readme_renderer.txt, "render", renderer)
88+
89+
ctx = {
90+
"request": pretend.stub(
91+
registry=pretend.stub(
92+
settings={
93+
"camo.url": "https://camo.example.net/",
94+
"camo.key": "fake key",
95+
},
96+
),
97+
),
98+
}
99+
100+
result = filters.readme(
101+
ctx, "raw thing", description_content_type="text/plain",
102+
)
103+
104+
assert result == jinja2.Markup("rendered")
105+
assert renderer.calls == [pretend.call('raw thing')]
106+
107+
def test_can_render_markdown(self, monkeypatch):
108+
renderer = pretend.call_recorder(lambda raw: "rendered")
109+
monkeypatch.setattr(readme_renderer.markdown, "render", renderer)
110+
111+
ctx = {
112+
"request": pretend.stub(
113+
registry=pretend.stub(
114+
settings={
115+
"camo.url": "https://camo.example.net/",
116+
"camo.key": "fake key",
117+
},
118+
),
119+
),
120+
}
121+
122+
result = filters.readme(
123+
ctx, "raw thing", description_content_type="text/markdown",
124+
)
125+
126+
assert result == jinja2.Markup("rendered")
127+
assert renderer.calls == [pretend.call('raw thing')]
80128

81129
def test_renders_camo(self, monkeypatch):
82130
html = "<img src=http://example.com/image.jpg>"
@@ -98,7 +146,9 @@ def test_renders_camo(self, monkeypatch):
98146
),
99147
}
100148

101-
result = filters.readme(ctx, "raw thing", format="rst")
149+
result = filters.readme(
150+
ctx, "raw thing", description_content_type="text/x-rst",
151+
)
102152

103153
assert result == jinja2.Markup(
104154
'<img src="https://camo.example.net/image.jpg">'
@@ -131,7 +181,9 @@ def test_renders_camo_no_src(self, monkeypatch):
131181
),
132182
}
133183

134-
result = filters.readme(ctx, "raw thing", format="rst")
184+
result = filters.readme(
185+
ctx, "raw thing", description_content_type="text/x-rst",
186+
)
135187

136188
assert result == jinja2.Markup("<img>")
137189
assert gen_camo_url.calls == []

warehouse/filters.py

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
# limitations under the License.
1212

1313
import binascii
14+
import cgi
1415
import collections
1516
import enum
1617
import hmac
@@ -24,13 +25,21 @@
2425
import jinja2
2526

2627
import packaging.version
28+
import readme_renderer.markdown
2729
import readme_renderer.rst
2830
import readme_renderer.txt
2931

3032
from pyramid.threadlocal import get_current_request
3133

3234
from warehouse.utils.http import is_valid_uri
3335

36+
_renderers = {
37+
'': readme_renderer.rst, # Default if description_content_type is None
38+
'text/plain': readme_renderer.txt,
39+
'text/x-rst': readme_renderer.rst,
40+
'text/markdown': readme_renderer.markdown,
41+
}
42+
3443

3544
class PackageType(enum.Enum):
3645
bdist_dmg = "OSX Disk Image"
@@ -63,23 +72,22 @@ def _camo_url(camo_url, camo_key, url):
6372

6473

6574
@jinja2.contextfilter
66-
def readme(ctx, value, *, format):
75+
def readme(ctx, value, *, description_content_type):
6776
request = ctx.get("request") or get_current_request()
6877

6978
camo_url = request.registry.settings["camo.url"].format(request=request)
7079
camo_key = request.registry.settings["camo.key"]
7180

72-
# The format parameter is here so we can more easily expand this to cover
73-
# READMEs which do not use restructuredtext, but for now rst is the only
74-
# format we support.
75-
assert format == "rst", "We currently only support rst rendering."
81+
content_type, parameters = cgi.parse_header(description_content_type)
82+
83+
# Get the appropriate renderer
84+
renderer = _renderers[content_type]
7685

7786
# Actually render the given value, this will not only render the value, but
7887
# also ensure that it's had any disallowed markup removed.
79-
rendered = readme_renderer.rst.render(value)
88+
rendered = renderer.render(value, **parameters)
8089

81-
# If the content was not rendered, we'll replace the newlines with breaks
82-
# so that it shows up nicer when rendered.
90+
# If the content was not rendered, we'll render as plaintext instead
8391
if rendered is None:
8492
rendered = readme_renderer.txt.render(value)
8593

warehouse/templates/packaging/detail.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,7 +234,7 @@ <h3>Classifiers</h3>
234234
<h2 class="page-title">Project Description</h2>
235235
{% if release.description %}
236236
<div class="project-description">
237-
{{ release.description|readme(format="rst") }}
237+
{{ release.description|readme(description_content_type=release.description_content_type) }}
238238
</div>
239239
{% else %}
240240
<div class="callout-block">

0 commit comments

Comments
 (0)