Fix T56372: Properly show error messages when submission fails

This also introduces a word-wrapping function that takes variable character
widths into account.
This commit is contained in:
2018-08-14 15:05:37 +02:00
parent 9ed933760c
commit 7b88d7704c
4 changed files with 100 additions and 6 deletions

View File

@@ -348,7 +348,11 @@ class BENCHMARK_PT_main(Panel):
sub = col.row()
sub.enabled = not G.results_submitted
sub.scale_y = 2.25
sub.operator("benchmark.share", text="SHARE ONLINE")
if G.submission_exception:
text = "Retry Submission"
else:
text = "SHARE ONLINE"
sub.operator("benchmark.share", text=text)
sub = col.row()
subsub = sub.split()
@@ -631,10 +635,20 @@ class BENCHMARK_OT_share(bpy.types.Operator):
make_buttons_default()
print('Submitting benchmark')
G.submission_exception = None
try:
submission.submit_benchmark(G.result_dict)
except submission.CommunicationError as cex:
logger.ERROR(f'Error {cex.status_code} submitting benchmark: {cex.message}')
if cex.json:
logger.ERROR(f'Response JSON: {cex.json}')
else:
logger.ERROR(f'Response body: {cex.body}')
G.submission_exception = cex
return {'CANCELLED'}
except Exception as ex:
self.report({'ERROR'}, f'Error submitting results:\n{str(ex)[:100]}')
logger.ERROR(f'error submitting benchmark: {ex}')
G.submission_exception = ex
return {'CANCELLED'}
print('Submission done')
make_buttons_green()

View File

@@ -4,11 +4,12 @@ import blf
import bpy
from ..foundation import util
from ..submission.client import CommunicationError
from . import G
WELCOME_TEXT = "Run the Quick Benchmark on the selected device to\n" \
WELCOME_TEXT = "Run the Quick Benchmark on the selected device to " \
"get a fast measurement of your hardware's performance.\n" \
"Usually takes less than 30 minutes."
@@ -147,7 +148,9 @@ def _draw_introduction(image_y, ui_scale, window_width, window_height):
x = 50.0 * ui_scale
y = image_y - (image_y - 52 * ui_scale - 18 * 3 * ui_scale) * 0.5
blf.size(font_id, int(12 * ui_scale), 72)
draw_text_multiline(WELCOME_TEXT, x, y)
text = word_wrap(WELCOME_TEXT, window_width * 0.45)
draw_text_multiline(text, x, y)
def _draw_benchmark_is_running(image_y, result_platform, result_stats, ui_scale, window_width):
@@ -208,4 +211,74 @@ def _draw_benchmark_has_run(image_y, ui_scale, window_width, window_height):
x = 50.0 * ui_scale
y = image_y - (image_y - 52 * ui_scale - 18 * 3 * ui_scale) * 0.5
blf.size(font_id, int(12 * ui_scale), 72)
draw_text_multiline(BLURB_TEXT, x, y)
text = _after_submission_text()
text = word_wrap(text, window_width * 0.45)
draw_text_multiline(text, x, y)
def _after_submission_text() -> str:
ex = G.submission_exception
# Nothing wrong, just show the default text.
if not ex:
return BLURB_TEXT
# If not our own exception class, show generic message.
if not isinstance(ex, CommunicationError):
return f'Error submitting your results: {ex}'
# Return proper message based on the HTTP status code of the response.
if ex.status_code in {502, 503}:
# 502 Bad Gateway, happens when restarting uWSGI.
# 503 Service Unavailable, happens when OpenData is down.
text = f'There was a hickups with code {ex.status_code} ' \
f'in the Open Data platform, please try submitting again.'
elif ex.status_code == 422:
# 422 Unprocessable Entity, happens when the JSON doesn't pass schema validation.
text = f'We somehow submitted invalid data, see below for details.'
else:
text = f'Error {ex.status_code} submitting your results.'
if not ex.json:
return text
msg = ex.json.get('message')
if msg:
return f'{text}\nThe server said: {msg}'
return text
def word_wrap(string: str, width_in_px: int) -> str:
"""Word-wrapping with variable character width.
Newlines in the input string are kept in the output.
"""
if '\n' in string:
# If the string already consists of multiple lines, wrap each line individually.
return '\n'.join(word_wrap(line, width_in_px)
for line in string.splitlines(keepends=False))
# Do an estimate of the maximum number of characters to fit on a line.
char_width = blf.dimensions(font_id, "i")[0]
max_chars = int(width_in_px // char_width)
wrapped_lines = []
while string:
# The line won't be longer than max_chars, so start there.
candidate_line = string[:max_chars]
line_width = blf.dimensions(font_id, candidate_line)[0]
# Keep removing the last word until the line fits the width.
while line_width >= width_in_px:
marker = len(candidate_line) - 1
while not candidate_line[marker].isspace():
marker -= 1
candidate_line = candidate_line[:marker]
line_width = blf.dimensions(font_id, candidate_line)[0]
string = string[len(candidate_line):]
wrapped_lines.append(candidate_line.strip())
return '\n'.join(wrapped_lines)

View File

@@ -1,4 +1,5 @@
import threading
import typing
class G:
@@ -19,6 +20,8 @@ class G:
current_progress = 0.0
progress_lock = threading.Lock()
submission_exception: typing.Optional[Exception] = None
@classmethod
def reset(cls):
"""Reset the global state."""
@@ -29,3 +32,4 @@ class G:
cls.background_image_path = ""
cls.scene_status = {}
cls.results_submitted = False
cls.submission_exception = None

View File

@@ -1,3 +1,6 @@
from .client import CommunicationError
def submit_benchmark(benchmark_data: dict):
"""Submit benchmark data to MyData.
@@ -8,7 +11,7 @@ def submit_benchmark(benchmark_data: dict):
import logging
import os
from .client import CommunicationError, BenchmarkClient
from .client import BenchmarkClient
mydata_url = os.environ.get('MYDATA') or 'https://mydata.blender.org/'
if 'MYDATA' in os.environ: