Skip to content

Commit 8532602

Browse files
committed
Merge branch 'release/26.0.0'
2 parents 2b789f8 + 76205e2 commit 8532602

8 files changed

Lines changed: 57 additions & 13 deletions

File tree

CHANGELOG

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

5+
26.0.0 (2026-03-26)
6+
===================
7+
- Add newerlic support to MFR. (thanks, @antkryt!)
8+
- Fix datetime conversion issue in tabular renderer. (thanks, @antkryt!)
9+
- Fix searching/filterinf in tabular renderer. (thanks, @Vlad0n20!)
10+
- Fix ability to zoom/pan on images.
11+
- Improve error message for unrenderable spreadsheets.
12+
513
25.0.0 (2025-11-18)
614
===================
715
- Upgrade MFR and dependencies to python v3.13.

mfr/core/exceptions.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -146,12 +146,15 @@ def __init__(self, message, *args, metadata_url: str = '', response: str = '', *
146146
'response': self.response
147147
}])
148148

149-
class CorruptedError(RendererError):
150149

151-
__TYPE = 'corrupted'
150+
class UnparseableTableError(RendererError):
151+
152+
__TYPE = 'unparseable_table'
152153

153154
def __init__(self, *args, renderer_class: str = '', **kwargs):
154-
super().__init__("File is corrupted, impossible to render, please check it's integrity", *args, renderer_class, **kwargs)
155+
super().__init__("File is not loading. Please check its integrity by downloading.",
156+
*args, renderer_class, **kwargs)
157+
155158

156159
class TooBigToRenderError(ProviderError):
157160
"""If the user tries to render a file larger than a server specified maximum, throw a

mfr/extensions/image/templates/viewer.mako

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,7 @@
5252
5353
$(document).ready(function() {
5454
55-
## Reference on how mobile is detected: https://stackoverflow.com/a/10364620
56-
var isMobile = window.matchMedia("only screen and (max-width: 760px)");
55+
var isMobile = window.innerWidth <= 768;
5756
5857
## Enable the zoom feature only for desktop browsers
5958
if (!isMobile.matches) {

mfr/extensions/tabular/utilities.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import re
22
import xlrd
3+
from datetime import datetime
34

45
from http import HTTPStatus
56
from subprocess import (check_call,
@@ -8,7 +9,7 @@
89
from tempfile import NamedTemporaryFile
910

1011
from mfr.extensions.tabular import compat
11-
from mfr.core.exceptions import SubprocessError, CorruptedError
12+
from mfr.core.exceptions import SubprocessError, UnparseableTableError
1213
from mfr.extensions.tabular.settings import (PSPP_CONVERT_BIN,
1314
PSPP_CONVERT_TIMEOUT,
1415
MAX_SIZE)
@@ -114,19 +115,25 @@ def to_bytes(fp):
114115
raise TypeError("Expected binary file-like object; got text/str")
115116

116117

118+
def _convert_value(value):
119+
if isinstance(value, datetime):
120+
return value.isoformat()
121+
return value
122+
123+
117124
def _extract_rows(fields, raw_rows):
118125
rows = []
119126
for row in raw_rows:
120127
if len(rows) >= MAX_SIZE:
121128
break
122-
rows.append(dict(zip(fields, row)))
129+
rows.append(dict(zip(fields, map(_convert_value, row))))
123130
return rows
124131

125132

126133
def parse_xls(wb, sheets):
127134
for sheet in wb.sheets():
128135
if getattr(sheet, 'nrows', None) is None or getattr(sheet, 'ncols', None) is None:
129-
raise CorruptedError
136+
raise UnparseableTableError
130137

131138
ncols = sheet.ncols
132139
max_cols = min(ncols, MAX_SIZE)
@@ -145,7 +152,7 @@ def parse_xlsx(wb, sheets):
145152
ws = wb[name]
146153

147154
if getattr(ws, 'max_row', None) is None or getattr(ws, 'max_column', None) is None:
148-
raise CorruptedError
155+
raise UnparseableTableError
149156

150157
ncols = getattr(ws, "max_column", 0)
151158
max_cols = min(ncols, MAX_SIZE)

mfr/version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = '25.0.0'
1+
__version__ = '26.0.0'

poetry.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[tool.poetry]
22
name = "mfr"
3-
version = "25.0.0"
3+
version = "26.0.0"
44
description = "Modular File Renderer"
55
authors = ["Center for Open Science <contact@cos.io>"]
66
readme = "README.md"
@@ -49,6 +49,7 @@ celery = "5.5.0"
4949
black = "^25.1.0"
5050
isort = "^6.0.1"
5151
ruff = "^0.12.7"
52+
newrelic = "10.8.1"
5253

5354

5455
[tool.poetry.group.dev]

tasks.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import os
2+
import sys
23

34
from invoke import task
45

@@ -70,3 +71,28 @@ def celery(ctx, loglevel='INFO', hostname='%h', concurrency=None):
7071
if concurrency:
7172
command.extend(['--concurrency', concurrency])
7273
app.worker_main(command)
74+
75+
76+
@task
77+
def newrelic_init(ctx, key=None, verbose=False):
78+
if key is None:
79+
sys.exit('No newrelic api key given. Please generate one and rerun this command '
80+
'with `invoke newrelic-init --key=$key`')
81+
82+
cmd_tmpl = 'newrelic-admin generate-config {} newrelic.ini'
83+
cmd = cmd_tmpl.format(key)
84+
if verbose:
85+
print(cmd_tmpl.format('<redacted>'))
86+
ctx.run(cmd, pty=True)
87+
88+
89+
@task
90+
def newrelic_server(ctx, config='newrelic.ini', verbose=False):
91+
if not os.path.exists(config):
92+
sys.exit("Couldn't find config file '{}'. Check path or run `invoke newrelic_init` "
93+
"to generate it.".format(config))
94+
95+
cmd = f'poetry run env NEW_RELIC_CONFIG_FILE={config} newrelic-admin run-program invoke server'
96+
if verbose:
97+
print(cmd)
98+
ctx.run(cmd, pty=True)

0 commit comments

Comments
 (0)