Skip to content

Commit 6474e91

Browse files
committed
Merge branch 'release/0.18.0'
2 parents 43d59f2 + b821f26 commit 6474e91

File tree

8 files changed

+76
-2
lines changed

8 files changed

+76
-2
lines changed

CHANGELOG

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@
22
ChangeLog
33
*********
44

5+
0.18.0 (2016-10-31)
6+
===================
7+
- HALLOWEEN RELEASE!
8+
- Feature: Add configurable size limit to text renderer to avoid dumping 100s of MB of text into
9+
the user's browser. (thanks, @TomBaxter!)
10+
- Fix: Pad MFR 404 errors to >512 bytes. IE discards 404 messages smaller than that and
11+
substitutes its own 404 page. (thanks, @alexschiller!)
12+
513
0.17.0 (2016-10-11)
614
===================
715
- Feature: WaterButler accepts configuration from the environment, overriding any file-based

mfr/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
__version__ = '0.17.1'
1+
__version__ = '0.18.0'
22
__import__('pkg_resources').declare_namespace(__name__)

mfr/core/exceptions.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ def as_html(self):
1010
return '''
1111
<link rel="stylesheet" href="/static/css/bootstrap.min.css">
1212
<div class="alert alert-warning" role="alert">{}</div>
13+
<div style="display: none;">This text and the text below is only presented because IE consumes error messages below 512 bytes</div>
14+
<div style="display: none;">Want to help save science? Want to get paid to develop free, open source software? Check out our openings!</div>
1315
'''.format(self.message)
1416

1517

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
from mfr.core.exceptions import RendererError
2+
3+
4+
class FileTooLargeException(RendererError):
5+
def __init__(self, *args, **kwargs):
6+
super().__init__(code=400, *args, **kwargs)

mfr/extensions/codepygments/render.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import os
22

33
import chardet
4+
from humanfriendly import format_size
45
import pygments
56
import pygments.lexers
67
import pygments.lexers.special
@@ -9,6 +10,8 @@
910
from mako.lookup import TemplateLookup
1011

1112
from mfr.core import extension, exceptions
13+
from mfr.extensions.codepygments import settings
14+
from mfr.extensions.codepygments import exceptions as cp_exceptions
1215

1316

1417
class CodePygmentsRenderer(extension.BaseRenderer):
@@ -25,6 +28,13 @@ def __init__(self, *args, **kwargs):
2528
self.metrics.add('pygments_version', pygments.__version__)
2629

2730
def render(self):
31+
file_size = os.path.getsize(self.file_path)
32+
if file_size > settings.MAX_SIZE:
33+
raise cp_exceptions.FileTooLargeException(
34+
'Text files larger than {} are not rendered. Please download the file to '
35+
'view.'.format(format_size(settings.MAX_SIZE, binary=True))
36+
)
37+
2838
with open(self.file_path, 'rb') as fp:
2939
body = self._render_html(fp, self.metadata.ext)
3040
return self.TEMPLATE.render(base=self.assets_url, body=body)
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from mfr import settings
2+
3+
config = settings.child('CODEPYGMENTS_EXTENSION_CONFIG')
4+
5+
MAX_SIZE = int(config.get('MAX_SIZE', 65536))

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
aiohttp==0.18.4
22
chardet==2.3.0
33
furl==0.4.2
4+
humanfriendly==2.1
45
invoke==0.11.1
56
mako==1.0.1
67
raven==5.27.0

tests/extensions/codepygments/test_renderer.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import os
22
import pytest
3+
from tempfile import NamedTemporaryFile
34

45
from mfr.core.exceptions import RendererError
56
from mfr.core.provider import ProviderMetadata
67

7-
from mfr.extensions.codepygments import CodePygmentsRenderer
8+
from mfr.extensions.codepygments import settings, CodePygmentsRenderer
9+
from mfr.extensions.codepygments.exceptions import FileTooLargeException
810

911

1012
@pytest.fixture
@@ -16,6 +18,29 @@ def metadata():
1618
def test_file_path():
1719
return os.path.join(os.path.dirname(os.path.abspath(__file__)), 'files', 'test.xml')
1820

21+
@pytest.fixture
22+
def max_size_file_path():
23+
dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
24+
'files')
25+
with NamedTemporaryFile(mode='w+b', suffix='.txt', dir=dir_path,
26+
delete=False) as temp_file:
27+
temp_file_path = temp_file.name
28+
file_size = settings.MAX_SIZE
29+
temp_file.seek(file_size -1)
30+
temp_file.write(b'0')
31+
return temp_file_path
32+
33+
@pytest.fixture
34+
def over_size_file_path():
35+
dir_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),
36+
'files')
37+
with NamedTemporaryFile(mode='w+b', suffix='.txt', dir=dir_path,
38+
delete=False) as temp_file:
39+
temp_file_path = temp_file.name
40+
file_size = settings.MAX_SIZE
41+
temp_file.seek(file_size)
42+
temp_file.write(b'0')
43+
return temp_file_path
1944

2045
@pytest.fixture
2146
def invalid_file_path():
@@ -58,6 +83,23 @@ def test_render_codepygments_invalid(self, metadata, invalid_file_path, url, ass
5883
with pytest.raises(RendererError):
5984
renderer.render()
6085

86+
def test_render_codepygments_max_size(self, metadata, max_size_file_path, url, assets_url, export_url):
87+
try:
88+
renderer = CodePygmentsRenderer(metadata, max_size_file_path, url, assets_url, export_url)
89+
body = renderer.render()
90+
assert '<div style="word-wrap: break-word;" class="mfrViewer">' in body
91+
finally:
92+
os.remove(max_size_file_path)
93+
94+
def test_render_codepygments_over_size(self, metadata, over_size_file_path, url, assets_url, export_url):
95+
with pytest.raises(FileTooLargeException):
96+
try:
97+
renderer = CodePygmentsRenderer(metadata, over_size_file_path,
98+
url, assets_url, export_url)
99+
renderer.render()
100+
finally:
101+
os.remove(over_size_file_path)
102+
61103
def test_render_codepygments_file_required(self, renderer):
62104
assert renderer.file_required is True
63105

0 commit comments

Comments
 (0)