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:
@@ -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()
|
||||
|
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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:
|
||||
|
Reference in New Issue
Block a user