From b2120aba10c90aa393806fe9e7074c0173dd6b25 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 7 Jan 2019 00:47:14 -0500 Subject: [PATCH] Add new "nonfatal error" handling for exporter There are some cases where errors, while bad, are not the end of the world. I'm thinking namely about compyling the age python. The age still exports just fine, but the ancillary data is flawed. This new system collects nonfatal errors until the export is done, then raises them all at once. --- korman/exporter/convert.py | 5 +++++ korman/exporter/explosions.py | 9 +++++++++ korman/exporter/logger.py | 31 ++++++++++++++++++++++++++++--- korman/operators/op_export.py | 3 +++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/korman/exporter/convert.py b/korman/exporter/convert.py index 81ffc08..36d424f 100644 --- a/korman/exporter/convert.py +++ b/korman/exporter/convert.py @@ -107,6 +107,11 @@ class Exporter: self.report.progress_end() self.report.save() + # Step 5.2: If any nonfatal errors were encountered during the export, we will + # raise them here, now that everything is finished, to draw attention + # to whatever the problem might be. + self.report.raise_errors() + def _bake_static_lighting(self): lighting_method = self._op.lighting_method if lighting_method != "skip": diff --git a/korman/exporter/explosions.py b/korman/exporter/explosions.py index 331c173..48151e3 100644 --- a/korman/exporter/explosions.py +++ b/korman/exporter/explosions.py @@ -13,6 +13,15 @@ # You should have received a copy of the GNU General Public License # along with Korman. If not, see . +class NonfatalExportError(Exception): + def __init__(self, *args, **kwargs): + assert args + if len(args) > 1: + super(Exception, self).__init__(args[0].format(*args[1:], **kwargs)) + else: + super(Exception, self).__init__(args[0]) + + class ExportError(Exception): def __init__(self, value="Undefined Export Error"): super(Exception, self).__init__(value) diff --git a/korman/exporter/logger.py b/korman/exporter/logger.py index 7d4e232..98f96ec 100644 --- a/korman/exporter/logger.py +++ b/korman/exporter/logger.py @@ -14,6 +14,7 @@ # along with Korman. If not, see . from ..korlib import ConsoleToggler +from .explosions import NonfatalExportError from pathlib import Path import threading import time @@ -24,6 +25,7 @@ _MAX_TIME_UNTIL_ELIPSES = 2.0 class _ExportLogger: def __init__(self, print_logs, age_path=None): + self._errors = [] self._porting = [] self._warnings = [] self._age_path = Path(age_path) if age_path is not None else None @@ -42,10 +44,23 @@ class _ExportLogger: def __exit__(self, type, value, traceback): if value is not None: - ConsoleToggler().keep_console = True + ConsoleToggler().keep_console = not isinstance(value, NonfatalExportError) self._file.close() return False + def error(self, *args, **kwargs): + assert args + indent = kwargs.get("indent", 0) + msg = "{}ERROR: {}".format(" " * indent, args[0]) + if len(args) > 1: + msg = msg.format(*args[1:], **kwargs) + if self._file is not None: + self._file.writelines((msg, "\n")) + if self._print_logs: + print(msg) + cache = args[0] if len(args) == 1 else args[0].format(*args[1:]) + self._errors.append(cache) + def msg(self, *args, **kwargs): assert args indent = kwargs.get("indent", 0) @@ -67,7 +82,8 @@ class _ExportLogger: self._file.writelines((msg, "\n")) if self._print_logs: print(msg) - self._porting.append(args[0]) + cache = args[0] if len(args) == 1 else args[0].format(*args[1:]) + self._porting.append(cache) def progress_add_step(self, name): @@ -92,6 +108,14 @@ class _ExportLogger: self.msg("Exporting '{}'", self._age_path.name) self._time_start_overall = time.perf_counter() + def raise_errors(self): + num_errors = len(self._errors) + if num_errors == 1: + raise NonfatalExportError(self._errors[0]) + elif num_errors: + raise NonfatalExportError("""{} errors were encountered during export. Check the export log for more details: + {}""", num_errors, self._file.name) + def save(self): # TODO pass @@ -106,7 +130,8 @@ class _ExportLogger: self._file.writelines((msg, "\n")) if self._print_logs: print(msg) - self._warnings.append(args[0]) + cache = args[0] if len(args) == 1 else args[0].format(*args[1:]) + self._warnings.append(cache) class ExportProgressLogger(_ExportLogger): diff --git a/korman/operators/op_export.py b/korman/operators/op_export.py index a1944d0..fa8040b 100644 --- a/korman/operators/op_export.py +++ b/korman/operators/op_export.py @@ -177,6 +177,9 @@ class PlasmaAgeExportOperator(ExportOperator, bpy.types.Operator): except exporter.ExportError as error: self.report({"ERROR"}, str(error)) return {"CANCELLED"} + except exporter.NonfatalExportError as error: + self.report({"ERROR"}, str(error)) + return {"FINISHED"} else: if self.profile_export: stats_out = path.with_name("{}_profile.log".format(ageName))