class openSBML(SpyderPluginWidget): "Open sbml files and translate into antimony string" CONF_SECTION = 'openSBML' CONFIGWIDGET_CLASS = None def __init__(self, main): super(openSBML, self).__init__(main) self.dockwidget = SpyderDockWidget(self.get_plugin_title(), main) self.dockwidget.hide() # --- SpyderPluginWidget API ---------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Open SBML") def register_plugin(self): """Register plugin in Spyder's main window""" opensbml_act = create_action(self.main, _("Open SBML file"), triggered=self.run_opensbml) self.main.file_menu_actions.insert(5, opensbml_act) def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" pass # --- Public API ---------------------------------------------------------- def run_opensbml(self, filenames=None, goto=None, word='', editorwindow=None, processevents=True): """Prompt the user to load a SBML file, translate to antimony, and display in a new window""" editor = self.main.editor editor0 = editor.get_current_editor() if editor0 is not None: position0 = editor0.get_position('cursor') filename0 = editor.get_current_filename() else: position0, filename0 = None, None if not filenames: # Recent files action action = editor.sender() if isinstance(action, QAction): filenames = from_qvariant(action.data(), to_text_string) if not filenames: basedir = getcwd() if editor.edit_filetypes is None: editor.edit_filetypes = get_edit_filetypes() if editor.edit_filters is None: editor.edit_filters = get_edit_filters() c_fname = editor.get_current_filename() if c_fname is not None and c_fname != editor.TEMPFILE_PATH: basedir = os.path.dirname(c_fname) editor.redirect_stdio.emit(False) parent_widget = editor.get_current_editorstack() if filename0 is not None: selectedfilter = get_filter(editor.edit_filetypes, os.path.splitext(filename0)[1]) else: selectedfilter = '' if not running_under_pytest(): customfilters = 'SBML files (*.sbml *.xml);;All files (*.*)' filenames, _sf = getopenfilenames( parent_widget, _("Open SBML file"), basedir, customfilters, selectedfilter=selectedfilter, options=QFileDialog.HideNameFilterDetails) else: # Use a Qt (i.e. scriptable) dialog for pytest dialog = QFileDialog(parent_widget, _("Open SBML file"), options=QFileDialog.DontUseNativeDialog) if dialog.exec_(): filenames = dialog.selectedFiles() editor.redirect_stdio.emit(True) if filenames: filenames = [os.path.normpath(fname) for fname in filenames] else: return focus_widget = QApplication.focusWidget() if editor.dockwidget and\ (not editor.dockwidget.isAncestorOf(focus_widget)\ and not isinstance(focus_widget, CodeEditor)): editor.dockwidget.setVisible(True) editor.dockwidget.setFocus() editor.dockwidget.raise_() def _convert(fname): fname = os.path.abspath(encoding.to_unicode_from_fs(fname)) if os.name == 'nt' and len(fname) >= 2 and fname[1] == ':': fname = fname[0].upper() + fname[1:] return fname if hasattr(filenames, 'replaceInStrings'): # This is a QStringList instance (PyQt API #1), converting to list: filenames = list(filenames) if not isinstance(filenames, list): filenames = [_convert(filenames)] else: filenames = [_convert(fname) for fname in list(filenames)] if isinstance(goto, int): goto = [goto] elif goto is not None and len(goto) != len(filenames): goto = None for index, filename in enumerate(filenames): p = re.compile('(.xml$|.sbml$)') pythonfile = p.sub('_antimony.py', filename) if (pythonfile == filename): pythonfile = filename + "_antimony.py" # -- Do not open an already opened file current_editor = editor.set_current_filename( pythonfile, editorwindow) if current_editor is None: # -- Not a valid filename: if not os.path.isfile(filename): continue # -- current_es = editor.get_current_editorstack(editorwindow) # Creating the editor widget in the first editorstack (the one # that can't be destroyed), then cloning this editor widget in # all other editorstacks: finfo, newname = self.load_and_translate( filename, pythonfile, editor) finfo.path = editor.main.get_spyder_pythonpath() editor._clone_file_everywhere(finfo) current_editor = current_es.set_current_filename(newname) current_es.analyze_script() if goto is not None: # 'word' is assumed to be None as well current_editor.go_to_line(goto[index], word=word) position = current_editor.get_position('cursor') editor.cursor_moved(filename0, position0, filename, position) if (current_editor is not None): current_editor.clearFocus() current_editor.setFocus() current_editor.window().raise_() if processevents: QApplication.processEvents() def load_and_translate(self, sbmlfile, pythonfile, editor, set_current=True): """ Read filename as combine archive, unzip, translate, reconstitute in Python, and create an editor instance and return it *Warning* This is loading file, creating editor but not executing the source code analysis -- the analysis must be done by the editor plugin (in case multiple editorstack instances are handled) """ widgeteditor = editor.editorstacks[0] sbmlfile = str(sbmlfile) widgeteditor.starting_long_process.emit(_("Loading %s...") % sbmlfile) text, enc = encoding.read(sbmlfile) sbmlstr = te.readFromFile(sbmlfile) try: transtext = str(te.sbmlToAntimony(sbmlstr)) except Exception as e: transtext = """*********************WARNING********************* Failed to translate the SBML model to Antimony string. Please check that the SBML file is valid. *********************WARNING*********************""" transtext = transtext + "\n\n" + str(e) text = "import tellurium as te\n\nr = te.loada('''\n" + transtext + "''')" finfo = widgeteditor.create_new_editor(pythonfile, enc, text, set_current, new=True) index = widgeteditor.data.index(finfo) widgeteditor._refresh_outlineexplorer(index, update=True) widgeteditor.ending_long_process.emit("") if widgeteditor.isVisible() and widgeteditor.checkeolchars_enabled \ and sourcecode.has_mixed_eol_chars(text): name = os.path.basename(pythonfile) QMessageBox.warning( self, widgeteditor.title, _("<b>%s</b> contains mixed end-of-line " "characters.<br>Spyder will fix this " "automatically.") % name, QMessageBox.Ok) widgeteditor.set_os_eol_chars(index) widgeteditor.is_analysis_done = False finfo.editor.set_cursor_position('eof') finfo.editor.insert_text(os.linesep) return finfo, sbmlfile
class teImport(SpyderPluginWidget): """teImport script""" CONF_SECTION = 'teImport' CONFIGWIDGET_CLASS = None def __init__(self, main): super(teImport, self).__init__(main) self.dockwidget = SpyderDockWidget(self.get_plugin_title(), main) self.dockwidget.hide() #------ SpyderPluginWidget API -------------------------------------------- def get_plugin_title(self): """Return widget title""" return _("Import COMBINE and SED-ML") def register_plugin(self): """Register plugin in Spyder's main window""" c2p_act = create_action(self.main, _("Import COMBINE as Python"), triggered=self.run_Import) c2p_act.triggered.connect(functools.partial(self.run_Import, 'c2p')) c2pwp_act = create_action(self.main, _("Import COMBINE as PhrasedML"), triggered=self.run_Import) c2pwp_act.triggered.connect(functools.partial(self.run_Import, 'c2pwp')) s2p_act = create_action(self.main, _("Import SED-ML as Python"), triggered=self.run_Import) s2p_act.triggered.connect(functools.partial(self.run_Import, 's2p')) s2pwp_act = create_action(self.main, _("Import SED-ML as PhrasedML"), triggered=self.run_Import) s2pwp_act.triggered.connect(functools.partial(self.run_Import, 's2pwp')) for item in self.main.file_menu_actions: try: menu_title = item.title() except AttributeError: pass else: if not is_text_string(menu_title): # string is a QString menu_title = to_text_string(menu_title.toUtf8) if item.title() == str("Import"): item.addAction(c2p_act, c2pwp_act, s2p_act, s2pwp_act) all_actions = (None, c2p_act, c2pwp_act, s2p_act, s2pwp_act) import_menu = QMenu(_("Import")) add_actions(import_menu, all_actions) self.main.file_menu_actions.insert(6, import_menu) def on_first_registration(self): """Action to be performed on first plugin registration""" self.main.tabify_plugins(self.main.help, self) self.dockwidget.hide() def closing_plugin(self, cancelable=False): """Perform actions before parent main window is closed""" return True def apply_plugin_settings(self, options): """Apply configuration file's plugin settings""" pass # --- Public API ---------------------------------------------------------- def run_Import(self, action): """Prompt user to load a COMBINE archive or SED-ML file and translates it""" if action == 'c2p' or action == 'c2pwp' or action == 's2p' or action == 's2pwp': editorwindow = None #Used in editor.load processevents = True #Used in editor.load goto = None word = '' editor = self.main.editor editor0 = editor.get_current_editor() if editor0 is not None: position0 = editor0.get_position('cursor') filename0 = editor.get_current_filename() else: position0, filename0 = None, None # Recent files action raction = editor.sender() if isinstance(raction, QAction): filenames = from_qvariant(raction.data(), to_text_string) if not filenames: basedir = getcwd() if editor.edit_filetypes is None: editor.edit_filetypes = get_edit_filetypes() if editor.edit_filters is None: editor.edit_filters = get_edit_filters() c_fname = editor.get_current_filename() if c_fname is not None and c_fname != editor.TEMPFILE_PATH: basedir = os.path.dirname(c_fname) editor.redirect_stdio.emit(False) parent_widget = editor.get_current_editorstack() if filename0 is not None: selectedfilter = get_filter(editor.edit_filetypes, os.path.splitext(filename0)[1]) else: selectedfilter = '' if action == 'c2p' or action == 'c2pwp': filters = 'Combine archives (*.zip *.omex);;All files (*.*)' filenames, _selfilter = getopenfilenames( parent_widget, _("Open combine archive"), basedir, filters, selectedfilter=selectedfilter) else: filters = 'SED-ML files (*.sedml *.xml);;All files (*.*)' filenames, _selfilter = getopenfilenames( parent_widget, _("Open SED-ML file"), basedir, filters, selectedfilter=selectedfilter) editor.redirect_stdio.emit(True) if filenames: filenames = [ os.path.normpath(fname) for fname in filenames ] else: return focus_widget = QApplication.focusWidget() if editor.dockwidget and\ (not editor.dockwidget.isAncestorOf(focus_widget)\ and not isinstance(focus_widget, CodeEditor)): editor.dockwidget.setVisible(True) editor.dockwidget.setFocus() editor.dockwidget.raise_() def _convert(fname): fname = os.path.abspath(encoding.to_unicode_from_fs(fname)) if os.name == 'nt' and len(fname) >= 2 and fname[1] == ':': fname = fname[0].upper() + fname[1:] return fname if hasattr(filenames, 'replaceInStrings'): # This is a QStringList instance (PyQt API #1), converting to list: filenames = list(filenames) if not isinstance(filenames, list): filenames = [_convert(filenames)] else: filenames = [_convert(fname) for fname in list(filenames)] if isinstance(goto, int): goto = [goto] elif goto is not None and len(goto) != len(filenames): goto = None for index, filename in enumerate(filenames): if action == 'c2p' or action == 'c2pwp': p = re.compile('(.zip$|.omex$)') pythonfile = p.sub('.py', filename) if (pythonfile == filename): pythonfile = filename + ".py" else: p = re.compile('(.xml$|.sedml$)') if action == 's2p': pythonfile = p.sub('_sedml.py', filename) if (pythonfile == filename): pythonfile = filename + "_sedml.py" else: pythonfile = p.sub('_phrasedml.py', filename) if (pythonfile == filename): pythonfile = filename + "_phrasedml.py" current_editor = editor.set_current_filename( pythonfile, editorwindow) if current_editor is None: # -- Not a valid filename: if not os.path.isfile(filename): continue # -- current_es = editor.get_current_editorstack(editorwindow) # Creating the editor widget in the first editorstack (the one # that can't be destroyed), then cloning this editor widget in # all other editorstacks: finfo, newname = self.load_and_translate( filename, pythonfile, editor, action) finfo.path = editor.main.get_spyder_pythonpath() editor._clone_file_everywhere(finfo) current_editor = current_es.set_current_filename(newname) current_es.analyze_script() if goto is not None: # 'word' is assumed to be None as well current_editor.go_to_line(goto[index], word=word) position = current_editor.get_position('cursor') editor.cursor_moved(filename0, position0, filename, position) if (current_editor is not None): current_editor.clearFocus() current_editor.setFocus() current_editor.window().raise_() if processevents: QApplication.processEvents() def load_and_translate(self, inputfile, pythonfile, editor, action, set_current=True): """ If the input is COMBINE archive, read filename as combine archive, unzip, translate, reconstitute in Python or PhrasedML, and create an editor instance and return it If the input is SED-ML file, read filename as SED-ML file, translate it to Python, and create an editor instance and return it *Warning* This is loading file, creating editor but not executing the source code analysis -- the analysis must be done by the editor plugin (in case multiple editorstack instances are handled) """ inputfile = str(inputfile) text, enc = encoding.read(inputfile) if action == 'c2p': fformat = '.py' text = Translatecombine2P(inputfile) zipextloctemp, sbmlloclisttemp, sedmlloclisttemp = manifestsearch( inputfile) elif action == 'c2pwp': fformat = '_phrasedml.py' text = Translatecombine2WP(inputfile) zipextloctemp, sbmlloclisttemp, sedmlloclisttemp = manifestsearch( inputfile) elif action == 's2p': fname = os.path.basename(inputfile) temp = '"End of code generated by Import SED-ML plugin ' + time.strftime( "%m/%d/%Y") + '"\n"Extracted from ' + fname + '"\n\n' text = te.sedmlToPython(inputfile) + temp else: fname = os.path.basename(inputfile) temp = '"End of code generated by Import SED-ML with PhrasedML plugin ' + time.strftime( '%m/%d/%Y') + '"\n"Extracted from ' + fname + '"' text = "import tellurium as te\n\nphrasedmlStr = '''" + pl.convertFile( inputfile ) + "'''\n\nte.executeSEDML(te.sedml.tephrasedml.phrasedml.convertString(phrasedmlStr))\n\n" + temp if action == 'c2p' or action == 'c2pwp': for i in range(len(text)): widgeteditor = editor.editorstacks[0] widgeteditor.starting_long_process.emit( _("Loading %s...") % inputfile) sedmlfname = os.path.basename(sedmlloclisttemp[i]) finfo = widgeteditor.create_new_editor( os.path.splitext(sedmlfname)[0] + fformat, enc, text[i], set_current, new=True) index = widgeteditor.data.index(finfo) widgeteditor._refresh_outlineexplorer(index, update=True) widgeteditor.ending_long_process.emit("") if widgeteditor.isVisible() and widgeteditor.checkeolchars_enabled \ and sourcecode.has_mixed_eol_chars(text[i]): if action == 'c2p': name = os.path.basename( os.path.splitext(sedmlfname)[0] + fformat) else: name = os.path.basename(pythonfile[:-3] + fformat) QMessageBox.warning( self, widgeteditor.title, _("<b>%s</b> contains mixed end-of-line " "characters.<br>Spyder will fix this " "automatically.") % name, QMessageBox.Ok) widgeteditor.set_os_eol_chars(index) widgeteditor.is_analysis_done = False finfo.editor.set_cursor_position('eof') finfo.editor.insert_text(os.linesep) else: widgeteditor = editor.editorstacks[0] widgeteditor.starting_long_process.emit( _("Loading %s...") % inputfile) finfo = widgeteditor.create_new_editor(pythonfile, enc, text, set_current, new=True) index = widgeteditor.data.index(finfo) widgeteditor._refresh_outlineexplorer(index, update=True) widgeteditor.ending_long_process.emit("") if widgeteditor.isVisible() and widgeteditor.checkeolchars_enabled \ and sourcecode.has_mixed_eol_chars(text): name = os.path.basename(pythonfile) QMessageBox.warning( self, widgeteditor.title, _("<b>%s</b> contains mixed end-of-line " "characters.<br>Spyder will fix this " "automatically.") % name, QMessageBox.Ok) widgeteditor.set_os_eol_chars(index) widgeteditor.is_analysis_done = False finfo.editor.set_cursor_position('eof') finfo.editor.insert_text(os.linesep) return finfo, inputfile