Skip to content

Commit 8c00faa

Browse files
committed
Merge branch 'feature/tabular-size-limit' into develop
[SVCS-675] Closes: #325
2 parents 4cf6112 + 90baefb commit 8c00faa

File tree

4 files changed

+60
-14
lines changed

4 files changed

+60
-14
lines changed

mfr/extensions/tabular/exceptions.py

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,14 @@ class TableTooBigError(TabularRendererError):
2929

3030
__TYPE = 'tabular_table_too_big'
3131

32-
def __init__(self, message, *args, code: int=400, **kwargs):
32+
def __init__(self, message, *args, code: int=400, nbr_cols: int=0, nbr_rows: int=0, **kwargs):
3333
super().__init__(message, *args, code=code, **kwargs)
34-
self.attr_stack.append([self.__TYPE, {}])
34+
self.nbr_cols = nbr_cols
35+
self.nbr_rows = nbr_rows
36+
self.attr_stack.append([self.__TYPE, {
37+
'nbr_cols': self.nbr_cols,
38+
'nbr_rows': self.nbr_rows
39+
}])
3540

3641

3742
class UnexpectedFormattingError(TabularRendererError):
@@ -42,3 +47,20 @@ def __init__(self, message, *args, code: int=500, formatting_function: str='', *
4247
super().__init__(message, *args, code=code, **kwargs)
4348
self.formatting_function = formatting_function
4449
self.attr_stack.append([self.__TYPE, {'formatting_function': self.formatting_function}])
50+
51+
52+
class FileTooLargeError(TabularRendererError):
53+
54+
__TYPE = 'tabular_file_too_large'
55+
56+
def __init__(self, message, *args, code: int=400, file_size: int=None, max_size: int=None,
57+
**kwargs):
58+
super().__init__(message, *args, code=code, **kwargs)
59+
60+
self.file_size = file_size
61+
self.max_size = max_size
62+
63+
self.attr_stack.append([self.__TYPE, {
64+
'file_size': self.file_size,
65+
'max_size': self.max_size
66+
}])

mfr/extensions/tabular/libs/xlrd_tools.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,8 @@ def xlsx_xlrd(fp):
1919

2020
for sheet in wb.sheets():
2121
if sheet.ncols > max_size or sheet.nrows > max_size:
22-
raise TableTooBigError('Table is too large to render.', '.xlsx')
22+
raise TableTooBigError('Table is too large to render.', '.xlsx',
23+
nbr_cols=sheet.ncols, nbr_rows=sheet.nrows)
2324

2425
if sheet.ncols < 1 or sheet.nrows < 1:
2526
sheets[sheet.name] = ([], [])

mfr/extensions/tabular/render.py

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,14 @@
1-
import os
21
import json
2+
import logging
3+
import os
34

5+
from humanfriendly import format_size
46
from mako.lookup import TemplateLookup
7+
58
from mfr.core import extension
9+
from mfr.extensions.tabular import settings, exceptions
610

7-
from mfr.extensions.tabular import settings
8-
from mfr.extensions.tabular import exceptions
11+
logger = logging.getLogger(__name__)
912

1013

1114
class TabularRenderer(extension.BaseRenderer):
@@ -16,6 +19,16 @@ class TabularRenderer(extension.BaseRenderer):
1619
]).get_template('viewer.mako')
1720

1821
def render(self):
22+
file_size = os.path.getsize(self.file_path)
23+
if file_size > settings.MAX_FILE_SIZE:
24+
raise exceptions.FileTooLargeError(
25+
'Tabular files larger than {} are not rendered. Please download '
26+
'the file to view.'.format(format_size(settings.MAX_FILE_SIZE, binary=True)),
27+
file_size=file_size,
28+
max_size=settings.MAX_FILE_SIZE,
29+
extension=self.metadata.ext,
30+
)
31+
1932
with open(self.file_path, errors='replace') as fp:
2033
sheets, size = self._render_grid(fp, self.metadata.ext)
2134
return self.TEMPLATE.render(
@@ -34,7 +47,7 @@ def file_required(self):
3447
def cache_result(self):
3548
return True
3649

37-
def _render_grid(self, fp, ext, *args, **kwargs): # assets_path, ext):
50+
def _render_grid(self, fp, ext, *args, **kwargs):
3851
"""Render a tabular file to html
3952
:param fp: file pointer object
4053
:return: RenderResult object containing html and assets
@@ -46,22 +59,31 @@ def _render_grid(self, fp, ext, *args, **kwargs): # assets_path, ext):
4659
size = settings.SMALL_TABLE
4760
self._renderer_tabular_metrics['size'] = 'small'
4861
self._renderer_tabular_metrics['nbr_sheets'] = len(sheets)
49-
for sheet in sheets:
50-
sheet = sheets[sheet] # Sheets are stored in key-value pairs of the form {sheet: (col, row)}
51-
if len(sheet[0]) > 9: # Check the number of columns
62+
for sheet_title in sheets:
63+
sheet = sheets[sheet_title]
64+
65+
# sheet is a two-element list. sheet[0] is a list of dicts containing metadata about
66+
# the column headers. Each dict contains four keys: `field`, `name`, `sortable`, `id`.
67+
# sheet[1] is a list of dicts where each dict contains the row data. The keys are the
68+
# fields the data belongs to and the values are the data values.
69+
70+
nbr_cols = len(sheet[0])
71+
if nbr_cols > 9:
5272
size = settings.BIG_TABLE
5373
self._renderer_tabular_metrics['size'] = 'big'
5474

55-
if len(sheet[0]) > settings.MAX_SIZE or len(sheet[1]) > settings.MAX_SIZE:
56-
raise exceptions.TableTooBigError('Table is too large to render.', extension=ext)
75+
nbr_rows = len(sheet[1])
76+
if nbr_cols > settings.MAX_SIZE or nbr_rows > settings.MAX_SIZE:
77+
raise exceptions.TableTooBigError('Table is too large to render.', extension=ext,
78+
nbr_cols=nbr_cols, nbr_rows=nbr_rows)
5779

5880
return sheets, size
5981

6082
def _populate_data(self, fp, ext):
6183
"""Determine the appropriate library and use it to populate rows and columns
6284
:param fp: file pointer
6385
:param ext: file extension
64-
:return: tuple of column headers and row data
86+
:return: a dict mapping sheet titles to tuples of column headers and row data
6587
"""
6688
function_preference = settings.LIBS.get(ext.lower())
6789

mfr/extensions/tabular/settings.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55
config = settings.child('TABULAR_EXTENSION_CONFIG')
66

7-
MAX_SIZE = int(config.get('MAX_SIZE', 10000))
7+
MAX_FILE_SIZE = int(config.get('MAX_FILE_SIZE', 10 * 1024 * 1024)) # 10Mb
8+
MAX_SIZE = int(config.get('MAX_SIZE', 10000)) # max number of rows or columns allowed.
89
TABLE_WIDTH = int(config.get('TABLE_WIDTH', 700))
910
TABLE_HEIGHT = int(config.get('TABLE_HEIGHT', 600))
1011

0 commit comments

Comments
 (0)