Show messages and errors in TCL shell. Better exception handling and reporting when opening files.
This commit is contained in:
parent
ba05f832c0
commit
f9cbd78cd1
|
@ -691,16 +691,35 @@ class App(QtCore.QObject):
|
||||||
else:
|
else:
|
||||||
self.defaults['stats'][resource] = 1
|
self.defaults['stats'][resource] = 1
|
||||||
|
|
||||||
|
# TODO: This shouldn't be here.
|
||||||
class TclErrorException(Exception):
|
class TclErrorException(Exception):
|
||||||
"""
|
"""
|
||||||
this exception is deffined here, to be able catch it if we sucessfully handle all errors from shell command
|
this exception is deffined here, to be able catch it if we sucessfully handle all errors from shell command
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
def shell_message(self, msg, show=False, error=False):
|
||||||
|
"""
|
||||||
|
Shows a message on the FlatCAM Shell
|
||||||
|
|
||||||
|
:param msg: Message to display.
|
||||||
|
:param show: Opens the shell.
|
||||||
|
:param error: Shows the message as an error.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
if show:
|
||||||
|
self.ui.shell_dock.show()
|
||||||
|
|
||||||
|
if error:
|
||||||
|
self.shell.append_error(msg + "\n")
|
||||||
|
else:
|
||||||
|
self.shell.append_output(msg + "\n")
|
||||||
|
|
||||||
def raise_tcl_unknown_error(self, unknownException):
|
def raise_tcl_unknown_error(self, unknownException):
|
||||||
"""
|
"""
|
||||||
raise Exception if is different type than TclErrorException
|
Raise exception if is different type than TclErrorException
|
||||||
this is here mainly to show unknown errors inside TCL shell console
|
this is here mainly to show unknown errors inside TCL shell console.
|
||||||
|
|
||||||
:param unknownException:
|
:param unknownException:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
|
@ -727,20 +746,20 @@ class App(QtCore.QObject):
|
||||||
show_trace = int(self.defaults['verbose_error_level'])
|
show_trace = int(self.defaults['verbose_error_level'])
|
||||||
|
|
||||||
if show_trace > 0:
|
if show_trace > 0:
|
||||||
trc=traceback.format_list(traceback.extract_tb(exc_traceback))
|
trc = traceback.format_list(traceback.extract_tb(exc_traceback))
|
||||||
trc_formated=[]
|
trc_formated = []
|
||||||
for a in reversed(trc):
|
for a in reversed(trc):
|
||||||
trc_formated.append(a.replace(" ", " > ").replace("\n",""))
|
trc_formated.append(a.replace(" ", " > ").replace("\n", ""))
|
||||||
text="%s\nPython traceback: %s\n%s" % (exc_value,
|
text = "%s\nPython traceback: %s\n%s" % (exc_value,
|
||||||
exc_type,
|
exc_type,
|
||||||
"\n".join(trc_formated))
|
"\n".join(trc_formated))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
text="%s" % error
|
text = "%s" % error
|
||||||
else:
|
else:
|
||||||
text=error
|
text = error
|
||||||
|
|
||||||
text = text.replace('[', '\\[').replace('"','\\"')
|
text = text.replace('[', '\\[').replace('"', '\\"')
|
||||||
|
|
||||||
self.tcl.eval('return -code error "%s"' % text)
|
self.tcl.eval('return -code error "%s"' % text)
|
||||||
|
|
||||||
|
@ -782,7 +801,7 @@ class App(QtCore.QObject):
|
||||||
try:
|
try:
|
||||||
self.shell.open_proccessing()
|
self.shell.open_proccessing()
|
||||||
result = self.tcl.eval(str(text))
|
result = self.tcl.eval(str(text))
|
||||||
if result!='None':
|
if result != 'None':
|
||||||
self.shell.append_output(result + '\n')
|
self.shell.append_output(result + '\n')
|
||||||
except Tkinter.TclError, e:
|
except Tkinter.TclError, e:
|
||||||
#this will display more precise answer if something in TCL shell fail
|
#this will display more precise answer if something in TCL shell fail
|
||||||
|
@ -836,16 +855,27 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
def info(self, msg):
|
def info(self, msg):
|
||||||
"""
|
"""
|
||||||
Writes on the status bar.
|
Informs the user. Normally on the status bar, optionally
|
||||||
|
also on the shell.
|
||||||
|
|
||||||
:param msg: Text to write.
|
:param msg: Text to write.
|
||||||
|
:param toshell: Forward the
|
||||||
:return: None
|
:return: None
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Type of message in brackets at the begining of the message.
|
||||||
match = re.search("\[([^\]]+)\](.*)", msg)
|
match = re.search("\[([^\]]+)\](.*)", msg)
|
||||||
if match:
|
if match:
|
||||||
self.ui.fcinfo.set_status(QtCore.QString(match.group(2)), level=match.group(1))
|
level = match.group(1)
|
||||||
|
msg_ = match.group(2)
|
||||||
|
self.ui.fcinfo.set_status(QtCore.QString(msg_), level=level)
|
||||||
|
|
||||||
|
error = level == "error" or level == "warning"
|
||||||
|
self.shell_message(msg, error=error, show=True)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.ui.fcinfo.set_status(QtCore.QString(msg), level="info")
|
self.ui.fcinfo.set_status(QtCore.QString(msg), level="info")
|
||||||
|
self.shell_message(msg)
|
||||||
|
|
||||||
def load_defaults(self):
|
def load_defaults(self):
|
||||||
"""
|
"""
|
||||||
|
@ -1953,6 +1983,17 @@ class App(QtCore.QObject):
|
||||||
self.log.error(str(e))
|
self.log.error(str(e))
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
except:
|
||||||
|
msg = "[error] An internal error has ocurred. See shell.\n"
|
||||||
|
msg += traceback.format_exc()
|
||||||
|
app_obj.inform.emit(msg)
|
||||||
|
raise
|
||||||
|
|
||||||
|
if gerber_obj.is_empty():
|
||||||
|
app_obj.inform.emit("[error] No geometry found in file: " + filename)
|
||||||
|
self.collection.set_active(gerber_obj.options["name"])
|
||||||
|
self.collection.delete_active()
|
||||||
|
|
||||||
# Further parsing
|
# Further parsing
|
||||||
self.progress.emit(70) # TODO: Note the mixture of self and app_obj used here
|
self.progress.emit(70) # TODO: Note the mixture of self and app_obj used here
|
||||||
|
|
||||||
|
@ -1997,18 +2038,31 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
excellon_obj.parse_file(filename)
|
excellon_obj.parse_file(filename)
|
||||||
|
|
||||||
except IOError:
|
except IOError:
|
||||||
app_obj.inform.emit("[error] Cannot open file: " + filename)
|
app_obj.inform.emit("[error] Cannot open file: " + filename)
|
||||||
self.progress.emit(0) # TODO: self and app_bjj mixed
|
self.progress.emit(0) # TODO: self and app_bjj mixed
|
||||||
raise IOError("Cannot open file: " + filename)
|
raise IOError("Cannot open file: " + filename)
|
||||||
|
|
||||||
|
except:
|
||||||
|
msg = "[error] An internal error has ocurred. See shell.\n"
|
||||||
|
msg += traceback.format_exc()
|
||||||
|
app_obj.inform.emit(msg)
|
||||||
|
raise
|
||||||
|
|
||||||
try:
|
try:
|
||||||
excellon_obj.create_geometry()
|
excellon_obj.create_geometry()
|
||||||
except Exception as e:
|
|
||||||
app_obj.inform.emit("[error] Failed to create geometry after parsing: " + filename)
|
|
||||||
self.progress.emit(0)
|
|
||||||
raise e
|
|
||||||
|
|
||||||
|
except:
|
||||||
|
msg = "[error] An internal error has ocurred. See shell.\n"
|
||||||
|
msg += traceback.format_exc()
|
||||||
|
app_obj.inform.emit(msg)
|
||||||
|
raise
|
||||||
|
|
||||||
|
if excellon_obj.is_empty():
|
||||||
|
app_obj.inform.emit("[error] No geometry found in file: " + filename)
|
||||||
|
self.collection.set_active(excellon_obj.options["name"])
|
||||||
|
self.collection.delete_active()
|
||||||
#self.progress.emit(70)
|
#self.progress.emit(70)
|
||||||
|
|
||||||
with self.proc_container.new("Opening Excellon."):
|
with self.proc_container.new("Opening Excellon."):
|
||||||
|
@ -2479,8 +2533,8 @@ class App(QtCore.QObject):
|
||||||
return "Could not retrieve object: %s" % name
|
return "Could not retrieve object: %s" % name
|
||||||
|
|
||||||
def geo_init_me(geo_obj, app_obj):
|
def geo_init_me(geo_obj, app_obj):
|
||||||
margin = kwa['margin']+kwa['dia']/2
|
margin = kwa['margin'] + kwa['dia'] / 2
|
||||||
gap_size = kwa['dia']+kwa['gapsize']
|
gap_size = kwa['dia'] + kwa['gapsize']
|
||||||
minx, miny, maxx, maxy = obj.bounds()
|
minx, miny, maxx, maxy = obj.bounds()
|
||||||
minx -= margin
|
minx -= margin
|
||||||
maxx += margin
|
maxx += margin
|
||||||
|
@ -2519,9 +2573,8 @@ class App(QtCore.QObject):
|
||||||
|
|
||||||
return 'Ok'
|
return 'Ok'
|
||||||
|
|
||||||
|
|
||||||
def geocutout(name=None, *args):
|
def geocutout(name=None, *args):
|
||||||
'''
|
"""
|
||||||
TCL shell command - see help section
|
TCL shell command - see help section
|
||||||
|
|
||||||
Subtract gaps from geometry, this will not create new object
|
Subtract gaps from geometry, this will not create new object
|
||||||
|
@ -2529,7 +2582,7 @@ class App(QtCore.QObject):
|
||||||
:param name: name of object
|
:param name: name of object
|
||||||
:param args: array of arguments
|
:param args: array of arguments
|
||||||
:return: "Ok" if completed without errors
|
:return: "Ok" if completed without errors
|
||||||
'''
|
"""
|
||||||
|
|
||||||
try:
|
try:
|
||||||
a, kwa = h(*args)
|
a, kwa = h(*args)
|
||||||
|
@ -2569,7 +2622,7 @@ class App(QtCore.QObject):
|
||||||
lenghty = (ymax - ymin)
|
lenghty = (ymax - ymin)
|
||||||
gapsize = kwa['gapsize'] + kwa['dia'] / 2
|
gapsize = kwa['gapsize'] + kwa['dia'] / 2
|
||||||
|
|
||||||
if kwa['gaps'] == '8' or kwa['gaps']=='2lr':
|
if kwa['gaps'] == '8' or kwa['gaps'] == '2lr':
|
||||||
|
|
||||||
subtract_rectangle(name,
|
subtract_rectangle(name,
|
||||||
xmin - gapsize,
|
xmin - gapsize,
|
||||||
|
|
19
camlib.py
19
camlib.py
|
@ -158,6 +158,16 @@ class Geometry(object):
|
||||||
log.error("Failed to run union on polylines.")
|
log.error("Failed to run union on polylines.")
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
|
||||||
|
if isinstance(self.solid_geometry, BaseGeometry):
|
||||||
|
return self.solid_geometry.is_empty
|
||||||
|
|
||||||
|
if isinstance(self.solid_geometry, list):
|
||||||
|
return len(self.solid_geometry) == 0
|
||||||
|
|
||||||
|
raise Exception("self.solid_geometry is neither BaseGeometry or list.")
|
||||||
|
|
||||||
def subtract_polygon(self, points):
|
def subtract_polygon(self, points):
|
||||||
"""
|
"""
|
||||||
Subtract polygon from the given object. This only operates on the paths in the original geometry, i.e. it converts polygons into paths.
|
Subtract polygon from the given object. This only operates on the paths in the original geometry, i.e. it converts polygons into paths.
|
||||||
|
@ -390,15 +400,6 @@ class Geometry(object):
|
||||||
"""
|
"""
|
||||||
return self.solid_geometry.buffer(offset)
|
return self.solid_geometry.buffer(offset)
|
||||||
|
|
||||||
def is_empty(self):
|
|
||||||
if self.solid_geometry is None:
|
|
||||||
return True
|
|
||||||
|
|
||||||
if type(self.solid_geometry) is list and len(self.solid_geometry) == 0:
|
|
||||||
return True
|
|
||||||
|
|
||||||
return False
|
|
||||||
|
|
||||||
def import_svg(self, filename, flip=True):
|
def import_svg(self, filename, flip=True):
|
||||||
"""
|
"""
|
||||||
Imports shapes from an SVG file into the object's geometry.
|
Imports shapes from an SVG file into the object's geometry.
|
||||||
|
|
Loading…
Reference in New Issue