def _on_extras_error(message): """ Log an Author's error in source, in the Params Don't use proceed(), don't need its stack trace. But GimpFu did not fixup user's code so this should be more severe than a warning? """ Deprecation.say("Error in plugin author's source: " + message)
def substitute_empty_string_for_none(self, arg, argname): if arg is None: Deprecation.say( f"Deprecated: Registered {argname} should be empty string, not None" ) result = "" else: result = arg return result
def canonicalize_prefix(cls, proc_name): if (not proc_name.startswith("python-") and not proc_name.startswith("extension-") and not proc_name.startswith("plug-in-") and not proc_name.startswith("file-")): result = "python-fu-" + proc_name message = f"Procedure name canonicalized to {result}" Deprecation.say(message) else: result = proc_name return result
def __getitem__(self, key): ''' CRUX: If the key is not in the wrapped dictionary, return unmapped key If key is in dictionary, return mapped and tell author of deprecated. ''' # TODO implement with except KeyError: would be faster? if key in self.__dict__.keys(): Deprecation.say(f"Deprecated name: {key}") return self.__dict__[key] else: return key
def deriveMissingImageParams(self, metadata): ''' Some plugins declare they are <Image> plugins, but don't have first two params equal to (image, drawable), and have imagetype == "" (menu item enabled even if no image is open). And then Gimp refuses to create procedure (but does create an item in pluginrc!) E.G. sphere.py So we diverge the signature of the plugin from the signature of the run_func. The author might be unaware, unless they explore, or try to call the PDB procedure from another PDB procedure. TODO after we are done, the count of args to run_func and the count of formal parameters (PARAMS) should be the same. Can we count the formal parameters of run_func? ''' result = False # if missing params (never there, or not fixed by earlier patch) # TODO if params are missing altogether if ( metadata.type == FuProcedureType.Image ) : # fix missing image declaration if ( (len(self.PARAMS) > 0) and self.PARAMS[0].PF_TYPE != PF_IMAGE ) : # FuFormalParams.logger Deprecation.say(f"Missing image param for Image type plugin {self.owner_name}") self.PARAMS.insert(0, FuFormalParams.image_param) result = True if ( (len(self.PARAMS) > 1) and self.PARAMS[1].PF_TYPE != PF_DRAWABLE ) : Deprecation.say("Missing drawable param for Image plugin") self.PARAMS.insert(1, FuFormalParams.drawable_param) result = True return result
def _deriveMissingMenu(self): ''' if menu is not given, derive it from label Ability to omit menu is deprecated, so this is FBC. ''' result = False if not self.MENUPATH: if self.MENUITEMLABEL: # label but no menu. Possible menu path in the label. fields = self.MENUITEMLABEL.split("/") if fields: self.MENUITEMLABEL = fields.pop() self.MENUPATH = "/".join(fields) result = True Deprecation.say( f"Use the 'menu' parameter instead of passing a full menu path in 'label'." ) else: # 'label' is not a path, can't derive menu path # TODO will GIMP show it in the GUI in a fallback place? Deprecation.say( f"Simple menu item 'label' without 'menu' path.") else: # no menu and no label # Normal, not a deprecation. Plugin only callable by other plugins self.logger.debug( f"No 'menu' and no 'label'. Plugin {self._name} will not appear in Gimp GUI." ) else: if self.MENUITEMLABEL: # menu and label given # Normal, user intends plugin appear in GUI pass else: # menu but no label # TODO Gimp will use suffix of 'menu' as 'label' ??? message = (f" Use the 'label' parameter instead" f"of passing menu item at end of 'menu'.") Deprecation.say(message) return result
def _fix_deprecated_menu(self): """ Fix menu paths deprecated. """ # require _deriveMissingMenu() called prior # Deprecated Since 2.8. # No longer the case that they should be in <File>/New as some docs say??? if self.MENUPATH.startswith("<Toolbox>/Xtns/Languages/Python-Fu"): self.MENUPATH = self.MENUPATH.replace( "<Toolbox>/Xtns/Languages/Python-Fu", "<Image>/Filters/Extensions") Deprecation.say( "Replaced menu path <Toolbox>/Xtns/Languages/Python-Fu with: <Image>/Filters/Extensions" ) elif self.MENUPATH.startswith("<Toolbox>/Xtns"): self.MENUPATH = self.MENUPATH.replace( "<Toolbox>/Xtns", "<Image>/Filters/Extensions") Deprecation.say( "Replaced menu path <Toolbox>/Xtns with: <Image>/Filters/Extensions" ) elif self.MENUPATH.startswith("<Toolbox>"): self.MENUPATH = self.MENUPATH.replace("<Toolbox>", "<Image>") Deprecation.say("Replaced menu path <Toolbox> with: <Image>")
def deriveMissingParams(self, metadata): """ FBC Add missing params according to plugin type. Returns True when insert params. """ ''' FBC. In the distant past, an author could specify menu like <Load> and not provide a label and not provide the first two params, in which case GimpFu inserts two params. Similarly for other cases. ''' result = False # v2 if self.did_fix_menu and plugin_type == PLUGIN: # require _deriveMissingMenu called earlier if metadata.is_new_style_registration: # specified params are explict, requires no fix pass elif metadata.type == FuProcedureType.Load : # insert into slice self.PARAMS[0:0] = FuFormalParams.file_params Deprecation.say(" Fixing two file params for Load plugin") result = True elif ( metadata.type == FuProcedureType.Image or metadata.type == FuProcedureType.Save) : self.PARAMS.insert(0, FuFormalParams.image_param) self.PARAMS.insert(1, FuFormalParams.drawable_param) Deprecation.say(" Fixing two image params for Image or Save plugin") if metadata.type == FuProcedureType.Save: self.PARAMS[2:2] = file_params Deprecation.say(" Fixing two file params for Save plugin") result = True #print(self.PARAMS) return result
def fix_underbar(cls, proc_name): new_proc_name = proc_name.replace('_', '-') if (new_proc_name != proc_name): Deprecation.say("Underbar in procedure name.") return new_proc_name
def _run_procedure_in_mode(procedure, run_mode, image, list_all_args, original_args, data): ''' Understands run_mode. Different ways to invoke procedure batch, or interactive. Hides run_mode from Authors. I.E. their run_func signature does not have run_mode. require procedure is-a Gimp.Procedure. require original_args is-a Gimp.ValueArray. require list_all_args is a list of GValues ''' list_wrapped_args = Marshal.wrap_args(list_all_args) # To know the Python name of a Gimp.Procedure method (e.g. gimp_procedure_get_name) # see gimp/libgimp/gimpprocedure.h, and then remove the prefix gimp_procedure_ name = procedure.get_name() FuRunner.logger.info( f"_run_procedure_in_mode: {name}, {run_mode}, {list_wrapped_args}") ''' list_wrapped_args are one-to-one with formal params. list_wrapped_args may include some args that are not guiable (i.e. image, drawable) ''' fuProcedure = FuProcedures.get_by_name(name) isBatch = (run_mode == Gimp.RunMode.NONINTERACTIVE) ''' Else so-called interactive mode, with GUI dialog of params. Note that the v2 mode RUN_WITH_LAST_VALS is obsolete since Gimp 3 persists settings, i.e. actual arg values can be from last invocation. If not from last invocation, they are the formal parameter defaults. ''' func = fuProcedure.get_authors_function() """ The ProcedureConfig should have length equal to ???? original_args is-a GimpValueArray """ # config = FuProcedureConfig(procedure, len(list_wrapped_args)-2 ) config = FuProcedureConfig(fuProcedure, procedure, original_args.length()) config.begin_run(image, run_mode, original_args) if isBatch: try: # invoke func with unpacked args. Since Python3, apply() gone. # TODO is this the correct set of args? E.G. Gimp is handling RUN_WITH_LAST_VALS, etc. ??? runfunc_result = func(*list_wrapped_args) final_result = FuResult.makeSuccess(procedure, runfunc_result) except Exception as err: # TODO print the Exception type err_message = f"In plugin: {name}, function: {func}, Exception: {err}" FuRunner.logger.warning(err_message) final_result = FuResult.makeException(procedure, err_message) else: ''' Not enclosed in try:except: since then you don't get a good traceback. Any exceptions in showing a dialog are hard programming errors. Any exception in executing the run_func should be shown to user, either by calling our own dialog or by calling a Gimp.ErrorDialog (not exist) or by passing the exception string back to Gimp. ''' was_canceled, runfunc_result = FuRunner._interact( procedure, list_wrapped_args, config) if was_canceled: final_result = FuResult.makeCancel(procedure) config.end_run(Gimp.PDBStatusType.CANCEL) else: final_result = FuResult.makeSuccess(procedure, runfunc_result) config.end_run(Gimp.PDBStatusType.SUCCESS) """ OLD above was enclosed in try try: except Exception as err: ''' Probably GimpFu module programming error (e.g. bad calls to GTK) According to GLib docs, should be a warning, since this is not recoverable. But it might be author programming code (e.g. invalid PARAMS) ''' proceed(f"Exception opening plugin dialog: {err}") final_result = FuResult.make(Gimp.PDBStatusType.EXECUTION_ERROR, GLib.Error()) """ ''' Make visible any alterations to user created images. GimpFu promises to hide the need for this. ''' Gimp.displays_flush() # !!! Gimp, not gimp did_suggest_or_deprecate = Suggest.summarize() did_suggest_or_deprecate = did_suggest_or_deprecate or Deprecation.summarize( ) if did_suggest_or_deprecate: # TODO make this go to the status bar, not a dialog # Gimp.message("See console for suggestions and deprecations.") pass if summarize_proceed_errors(): # side effect is writing to console """ Gimpfu proceeded past earlier exceptions. Display GIMP dialog. """ msg = "GimpFu detected errors. See console for a summary." Gimp.message(msg) final_result = FuResult.makeException(procedure, msg) # Alternatively: raise Exception(msg) but that is confusing to Author FuRunner.logger.debug( f"Returning from: {name} with result:{final_result}") # ensure final_result is type GimpValueArray assert isinstance(final_result, Gimp.ValueArray) return final_result