diff --git a/FlatCAMApp.py b/FlatCAMApp.py index 98cf5dfe..af1516b4 100644 --- a/FlatCAMApp.py +++ b/FlatCAMApp.py @@ -3636,36 +3636,36 @@ class App(QtCore.QObject): except Exception, e: return "ERROR: %s" % str(e) - def get_sys(param): - if param in self.defaults: - return self.defaults[param] + # def get_sys(param): + # if param in self.defaults: + # return self.defaults[param] + # + # return "ERROR: No such system parameter." - return "ERROR: No such system parameter." - - def set_sys(param, value): - # tcl string to python keywords: - tcl2py = { - "None": None, - "none": None, - "false": False, - "False": False, - "true": True, - "True": True - } - - if param in self.defaults: - - try: - value = tcl2py[value] - except KeyError: - pass - - self.defaults[param] = value - - self.propagate_defaults() - return "Ok" - - return "ERROR: No such system parameter." + # def set_sys(param, value): + # # tcl string to python keywords: + # tcl2py = { + # "None": None, + # "none": None, + # "false": False, + # "False": False, + # "true": True, + # "True": True + # } + # + # if param in self.defaults: + # + # try: + # value = tcl2py[value] + # except KeyError: + # pass + # + # self.defaults[param] = value + # + # self.propagate_defaults() + # return "Ok" + # + # return "ERROR: No such system parameter." ''' Howto implement TCL shell commands: @@ -4085,22 +4085,25 @@ class App(QtCore.QObject): ' name: Name of the gerber object.\n' + ' outname: Name of the output geometry object.' }, - 'get_sys': { - 'fcn': get_sys, - 'help': 'Get the value of a system parameter (FlatCAM constant)\n' + - '> get_sys \n' + - ' sysparam: Name of the parameter.' - }, - 'set_sys': { - 'fcn': set_sys, - 'help': 'Set the value of a system parameter (FlatCAM constant)\n' + - '> set_sys \n' + - ' sysparam: Name of the parameter.\n' + - ' paramvalue: Value to set.' - } + + # 'get_sys': { + # 'fcn': get_sys, + # 'help': 'Get the value of a system parameter (FlatCAM constant)\n' + + # '> get_sys \n' + + # ' sysparam: Name of the parameter.' + # }, + # --- Migrated to new architecture --- + # 'set_sys': { + # 'fcn': set_sys, + # 'help': 'Set the value of a system parameter (FlatCAM constant)\n' + + # '> set_sys \n' + + # ' sysparam: Name of the parameter.\n' + + # ' paramvalue: Value to set.' + # } } - #import/overwrite tcl commands as objects of TclCommand descendants + # Import/overwrite tcl commands as objects of TclCommand descendants + # This modifies the variable 'commands'. tclCommands.register_all_commands(self, commands) # Add commands to the tcl interpreter diff --git a/tclCommands/TclCommand.py b/tclCommands/TclCommand.py index 459a078f..22f7438f 100644 --- a/tclCommands/TclCommand.py +++ b/tclCommands/TclCommand.py @@ -12,26 +12,28 @@ class TclCommand(object): # FlatCAMApp app = None - # logger + # Logger log = None - # array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) + # List of all command aliases, to be able use old names + # for backward compatibility (add_poly, add_polygon) aliases = [] - # dictionary of types from Tcl command, needs to be ordered + # Dictionary of types from Tcl command, needs to be ordered # OrderedDict should be like collections.OrderedDict([(key,value),(key2,value2)]) arg_names = collections.OrderedDict([ ('name', str) ]) - # dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value + # dictionary of types from Tcl command, needs to be ordered. + # This is for options like -optionname value. # OrderedDict should be like collections.OrderedDict([(key,value),(key2,value2)]) option_types = collections.OrderedDict() - # array of mandatory options for current Tcl command: required = {'name','outname'} + # List of mandatory options for current Tcl command: required = {'name','outname'} required = ['name'] - # structured help for current command, args needs to be ordered + # Structured help for current command, args needs to be ordered # OrderedDict should be like collections.OrderedDict([(key,value),(key2,value2)]) help = { 'main': "undefined help.", @@ -42,21 +44,27 @@ class TclCommand(object): 'examples': [] } - # original incoming arguments into command + # Original incoming arguments into command original_args = None def __init__(self, app): self.app = app + if self.app is None: raise TypeError('Expected app to be FlatCAMApp instance.') + if not isinstance(self.app, FlatCAMApp.App): raise TypeError('Expected FlatCAMApp, got %s.' % type(app)) + self.log = self.app.log def raise_tcl_error(self, text): """ - this method pass exception from python into TCL as error, so we get stacktrace and reason - this is only redirect to self.app.raise_tcl_error + This method pass exception from python into TCL as error + so we get stacktrace and reason. + + This is only redirect to self.app.raise_tcl_error + :param text: text of error :return: none """ @@ -65,14 +73,17 @@ class TclCommand(object): def get_current_command(self): """ - get current command, we are not able to get it from TCL we have to reconstruct it + Get current command, we are not able to get it from TCL we have to reconstruct it. + :return: current command """ - command_string = [] - command_string.append(self.aliases[0]) + + command_string = [self.aliases[0]] + if self.original_args is not None: for arg in self.original_args: command_string.append(arg) + return " ".join(command_string) def get_decorated_help(self): @@ -83,22 +94,36 @@ class TclCommand(object): """ def get_decorated_command(alias_name): + command_string = [] + for arg_key, arg_type in self.help['args'].items(): command_string.append(get_decorated_argument(arg_key, arg_type, True)) + return "> " + alias_name + " " + " ".join(command_string) def get_decorated_argument(help_key, help_text, in_command=False): + """ + + :param help_key: Name of the argument. + :param help_text: + :param in_command: + :return: + """ option_symbol = '' + if help_key in self.arg_names: arg_type = self.arg_names[help_key] type_name = str(arg_type.__name__) - in_command_name = "<" + type_name + ">" + #in_command_name = help_key + "<" + type_name + ">" + in_command_name = help_key + elif help_key in self.option_types: option_symbol = '-' arg_type = self.option_types[help_key] type_name = str(arg_type.__name__) in_command_name = option_symbol + help_key + " <" + type_name + ">" + else: option_symbol = '' type_name = '?' @@ -168,7 +193,7 @@ class TclCommand(object): def check_args(self, args): """ - Check arguments and options for right types + Check arguments and options for right types :param args: arguments from tcl to check :return: named_args, unnamed_args @@ -214,29 +239,16 @@ class TclCommand(object): return named_args, unnamed_args - def raise_tcl_unknown_error(self, unknownException): + def raise_tcl_unknown_error(self, unknown_exception): """ raise Exception if is different type than TclErrorException this is here mainly to show unknown errors inside TCL shell console - :param unknownException: + + :param unknown_exception: :return: """ - #if not isinstance(unknownException, self.TclErrorException): - # self.raise_tcl_error("Unknown error: %s" % str(unknownException)) - #else: - raise unknownException - - def raise_tcl_error(self, text): - """ - this method pass exception from python into TCL as error, so we get stacktrace and reason - :param text: text of error - :return: raise exception - """ - - # becouse of signaling we cannot call error to TCL from here but when task is finished - # also nonsiglaned arwe handled here to better exception handling and diplay after command is finished - raise self.app.TclErrorException(text) + raise unknown_exception def execute_wrapper(self, *args): """ @@ -291,6 +303,10 @@ class TclCommandSignaled(TclCommand): it handles all neccessary stuff about blocking and passing exeptions """ + @abc.abstractmethod + def execute(self, args, unnamed_args): + raise NotImplementedError("Please Implement this method") + output = None def execute_call(self, args, unnamed_args): diff --git a/tclCommands/TclCommandGetSys.py b/tclCommands/TclCommandGetSys.py new file mode 100644 index 00000000..3bfeb99e --- /dev/null +++ b/tclCommands/TclCommandGetSys.py @@ -0,0 +1,50 @@ +from ObjectCollection import * +import TclCommand + + +class TclCommandGetSys(TclCommand.TclCommand): + """ + Tcl shell command to get the value of a system variable + + example: + get_sys excellon_zeros + """ + + # List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) + aliases = ['get_sys', 'getsys'] + + # Dictionary of types from Tcl command, needs to be ordered + arg_names = collections.OrderedDict([ + ('name', str) + ]) + + # Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value + option_types = collections.OrderedDict([ + + ]) + + # array of mandatory options for current Tcl command: required = {'name','outname'} + required = ['name'] + + # structured help for current command, args needs to be ordered + help = { + 'main': "Returns the value of the system variable.", + 'args': collections.OrderedDict([ + ('name', 'Name of the system variable.'), + ]), + 'examples': ['get_sys excellon_zeros'] + } + + def execute(self, args, unnamed_args): + """ + + :param args: + :param unnamed_args: + :return: + """ + + name = args['name'] + + if name in self.app.defaults: + return self.app.defaults[name] + diff --git a/tclCommands/TclCommandJoinGeometry.py b/tclCommands/TclCommandJoinGeometry.py index a45d6d4a..4da7beb1 100644 --- a/tclCommands/TclCommandJoinGeometry.py +++ b/tclCommands/TclCommandJoinGeometry.py @@ -46,7 +46,7 @@ class TclCommandJoinGeometry(TclCommand.TclCommand): :return: """ - outname = args['name'] + outname = args['outname'] obj_names = unnamed_args objs = [] diff --git a/tclCommands/TclCommandOpenExcellon.py b/tclCommands/TclCommandOpenExcellon.py index 4bfce02a..cf18bc75 100644 --- a/tclCommands/TclCommandOpenExcellon.py +++ b/tclCommands/TclCommandOpenExcellon.py @@ -8,7 +8,7 @@ class TclCommandOpenExcellon(TclCommand.TclCommandSignaled): """ # array of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) - aliases = ['open_gerber'] + aliases = ['open_excellon'] # Dictionary of types from Tcl command, needs to be ordered. # For positional arguments @@ -45,4 +45,6 @@ class TclCommandOpenExcellon(TclCommand.TclCommandSignaled): :return: None or exception """ - self.app.open_excellon(args['filename'], **args) + filename = args.pop('filename') + + self.app.open_excellon(filename, **args) diff --git a/tclCommands/TclCommandSetSys.py b/tclCommands/TclCommandSetSys.py new file mode 100644 index 00000000..327e0725 --- /dev/null +++ b/tclCommands/TclCommandSetSys.py @@ -0,0 +1,73 @@ +from ObjectCollection import * +import TclCommand + + +class TclCommandSetSys(TclCommand.TclCommand): + """ + Tcl shell command to set the value of a system variable + + example: + + """ + + # List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) + aliases = ['set_sys', 'setsys'] + + # Dictionary of types from Tcl command, needs to be ordered + arg_names = collections.OrderedDict([ + ('name', str), + ('value', str) + ]) + + # Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value + option_types = collections.OrderedDict([ + + ]) + + # array of mandatory options for current Tcl command: required = {'name','outname'} + required = ['name', 'value'] + + # structured help for current command, args needs to be ordered + help = { + 'main': "Sets the value of the system variable.", + 'args': collections.OrderedDict([ + ('name', 'Name of the system variable.'), + ('value', 'Value to set.') + ]), + 'examples': [] + } + + def execute(self, args, unnamed_args): + """ + + :param args: + :param unnamed_args: + :return: + """ + + param = args['name'] + value = args['value'] + + # TCL string to python keywords: + tcl2py = { + "None": None, + "none": None, + "false": False, + "False": False, + "true": True, + "True": True + } + + if param in self.app.defaults: + + try: + value = tcl2py[value] + except KeyError: + pass + + self.app.defaults[param] = value + + self.app.propagate_defaults() + + self.raise_tcl_error("No such system parameter \"{}\".".format(param)) + diff --git a/tclCommands/TclCommandVersion.py b/tclCommands/TclCommandVersion.py new file mode 100644 index 00000000..7d05669c --- /dev/null +++ b/tclCommands/TclCommandVersion.py @@ -0,0 +1,47 @@ +from ObjectCollection import * +import TclCommand + + +class TclCommandVersion(TclCommand.TclCommand): + """ + Tcl shell command to check the program version. + + example: + + """ + + # List of all command aliases, to be able use old names for backward compatibility (add_poly, add_polygon) + aliases = ['version'] + + # Dictionary of types from Tcl command, needs to be ordered + arg_names = collections.OrderedDict([ + + ]) + + # Dictionary of types from Tcl command, needs to be ordered , this is for options like -optionname value + option_types = collections.OrderedDict([ + + ]) + + # array of mandatory options for current Tcl command: required = {'name','outname'} + required = [] + + # structured help for current command, args needs to be ordered + help = { + 'main': "Checks the program version.", + 'args': collections.OrderedDict([ + + ]), + 'examples': [] + } + + def execute(self, args, unnamed_args): + """ + + :param args: + :param unnamed_args: + :return: + """ + + self.app.version_check() + diff --git a/tclCommands/__init__.py b/tclCommands/__init__.py index 3521a5f9..eaa2c327 100644 --- a/tclCommands/__init__.py +++ b/tclCommands/__init__.py @@ -19,6 +19,7 @@ import tclCommands.TclCommandExteriors import tclCommands.TclCommandGeoCutout import tclCommands.TclCommandGeoUnion import tclCommands.TclCommandGetNames +import tclCommands.TclCommandGetSys import tclCommands.TclCommandImportSvg import tclCommands.TclCommandInteriors import tclCommands.TclCommandIsolate @@ -40,8 +41,10 @@ import tclCommands.TclCommandPlot import tclCommands.TclCommandSaveProject import tclCommands.TclCommandScale import tclCommands.TclCommandSetActive +import tclCommands.TclCommandSetSys import tclCommands.TclCommandSubtractPoly import tclCommands.TclCommandSubtractRectangle +import tclCommands.TclCommandVersion import tclCommands.TclCommandWriteGCode @@ -65,7 +68,7 @@ def register_all_commands(app, commands): I have no enough knowledge about python's anatomy. Would be nice to include all classes which are descendant etc. :param app: FlatCAMApp - :param commands: array of commands which should be modified + :param commands: List of commands being updated :return: None """