# # Gramps - a GTK+/GNOME based genealogy program # # Copyright (C) 2000-2005 Donald N. Allingham # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # $Id$ # Written by Alex Roitman """ Module responsible for handling the command line arguments for GRAMPS. """ #------------------------------------------------------------------------- # # Standard python modules # #------------------------------------------------------------------------- import os import getopt import time from gettext import gettext as _ #------------------------------------------------------------------------- # # gramps modules # #------------------------------------------------------------------------- import const import ReadXML import GrampsMime import DbPrompter import QuestionDialog import GrampsKeys import RecentFiles import PluginMgr import Report import Tool #------------------------------------------------------------------------- # # ArgHandler # #------------------------------------------------------------------------- class ArgHandler: """ This class is responsible for handling command line arguments (if any) given to gramps. The valid arguments are: FILE : filename to open. All following arguments will be ignored. -i, --import=FILE : filename to import. -O, --open=FILE : filename to open. -o, --output=FILE : filename to export. -f, --format=FORMAT : format of the file preceding this option. If the filename (no flags) is specified, the interactive session is launched using data from filename. If the filename is not in a natvive (grdb) format, dialog will be presented to set up a grdb database. In this mode (filename, no flags), the rest of the arguments is ignored. This is a mode suitable by default for GUI launchers, mime type handlers, and the like If no filename or -i option is given, a new interactive session (empty database) is launched, since no data is given anyway. If -O or -i option is given, but no -o or -a options are given, an interactive session is launched with the FILE (specified with -i). If both input (-O or -i) and processing (-o or -a) options are given, interactive session will not be launched. """ def __init__(self,parent,args): self.parent = parent self.args = args self.open_gui = None self.open = None self.exports = [] self.actions = [] self.imports = [] self.parse_args() self.handle_args() #------------------------------------------------------------------------- # # Argument parser: sorts out given arguments # #------------------------------------------------------------------------- def parse_args(self): """ Fill in lists with open, exports, imports, and actions options. """ try: options,leftargs = getopt.getopt(self.args[1:], const.shortopts,const.longopts) except getopt.GetoptError: # return without filling anything if we could not parse the args print "Error parsing arguments: %s " % self.args[1:] return if leftargs: # if there were an argument without option, use it as a file to # open and return self.open_gui = leftargs[0] print "Trying to open: %s ..." % leftargs[0] return for opt_ix in range(len(options)): o,v = options[opt_ix] if o in ( '-O', '--open'): fname = v ftype = GrampsMime.get_type( os.path.abspath(os.path.expanduser(fname))) if opt_ix 1 and not self.open: print "No data was given -- will launch interactive session." print "To use in the command-line mode,", \ "supply at least one input file to process." print "Launching interactive session..." if self.parent.cl: for expt in self.exports: print "Exporting: file %s, format %s." % expt self.cl_export(expt[0],expt[1]) for (action,options_str) in self.actions: print "Performing action: %s." % action if options_str: print "Using options string: %s" % options_str self.cl_action(action,options_str) print "Cleaning up." # remove import db after use self.parent.db.close() if self.imports: os.remove(self.imp_db_path) print "Exiting." os._exit(0) if self.imports: self.parent.import_tool_callback() elif GrampsKeys.get_lastfile() and GrampsKeys.get_autoload(): if self.auto_save_load(GrampsKeys.get_lastfile()) == 0: DbPrompter.DbPrompter(self.parent,0) else: DbPrompter.DbPrompter(self.parent,0) #------------------------------------------------------------------------- # # Import handler # #------------------------------------------------------------------------- def cl_import(self,filename,format): """ Command-line import routine. Try to import filename using the format. Any errors will cause the os._exit(1) call. """ if format == 'grdb': import ReadGrdb filename = os.path.normpath(os.path.abspath(filename)) try: ReadGrdb.importData(self.parent.db,filename,None) except: print "Error importing %s" % filename os._exit(1) elif format == 'gedcom': import ReadGedcom filename = os.path.normpath(os.path.abspath(filename)) try: g = ReadGedcom.GedcomParser(self.parent.db,filename,None) g.parse_gedcom_file() g.resolve_refns() del g except: print "Error importing %s" % filename os._exit(1) elif format == 'gramps-xml': try: ReadXML.importData(self.parent.db,filename,None,self.parent.cl) except: print "Error importing %s" % filename os._exit(1) elif format == 'geneweb': import ImportGeneWeb filename = os.path.normpath(os.path.abspath(filename)) try: ImportGeneWeb.importData(self.parent.db,filename,None) except: print "Error importing %s" % filename os._exit(1) elif format == 'gramps-pkg': # Create tempdir, if it does not exist, then check for writability tmpdir_path = os.path.expanduser("~/.gramps/tmp" ) if not os.path.isdir(tmpdir_path): try: os.mkdir(tmpdir_path,0700) except: print "Could not create temporary directory %s" \ % tmpdir_path os._exit(1) elif not os.access(tmpdir_path,os.W_OK): print "Temporary directory %s is not writable" % tmpdir_path os._exit(1) else: # tempdir exists and writable -- clean it up if not empty files = os.listdir(tmpdir_path) ; for fn in files: os.remove( os.path.join(tmpdir_path,fn) ) try: import TarFile t = TarFile.ReadTarFile(filename,tmpdir_path) t.extract() t.close() except: print "Error extracting into %s" % tmpdir_path os._exit(1) dbname = os.path.join(tmpdir_path,const.xmlFile) try: ReadXML.importData(self.parent.db,dbname,None) except: print "Error importing %s" % filename os._exit(1) # Clean up tempdir after ourselves files = os.listdir(tmpdir_path) for fn in files: os.remove(os.path.join(tmpdir_path,fn)) os.rmdir(tmpdir_path) else: print "Invalid format: %s" % format os._exit(1) if not self.parent.cl: return self.parent.post_load(self.imp_db_path) #------------------------------------------------------------------------- # # Export handler # #------------------------------------------------------------------------- def cl_export(self,filename,format): """ Command-line export routine. Try to write into filename using the format. Any errors will cause the os._exit(1) call. """ if format == 'gedcom': import WriteGedcom try: gw = WriteGedcom.GedcomWriter(self.parent.db,None,1,filename) ret = gw.export_data(filename) except: print "Error exporting %s" % filename os._exit(1) elif format == 'gramps-xml': filename = os.path.normpath(os.path.abspath(filename)) if filename: try: import WriteXML g = WriteXML.XmlWriter(self.parent.db,None,1,1) ret = g.write(filename) except: print "Error exporting %s" % filename os._exit(1) elif format == 'gramps-pkg': try: import WritePkg writer = WritePkg.PackageWriter(self.parent.db,filename) ret = writer.export() except: print "Error creating %s" % filename os._exit(1) elif format == 'iso': import WriteCD try: writer = WriteCD.PackageWriter(self.parent.db,filename,1) ret = writer.export() except: print "Error exporting %s" % filename os._exit(1) elif format == 'wft': import WriteFtree try: writer = WriteFtree.FtreeWriter(self.parent.db,None,1,filename) ret = writer.export_data() except: print "Error exporting %s" % filename os._exit(1) elif format == 'geneweb': import WriteGeneWeb try: writer = WriteGeneWeb.GeneWebWriter(self.parent.db, None,1,filename) ret = writer.export_data() except: print "Error exporting %s" % filename os._exit(1) else: print "Invalid format: %s" % format os._exit(1) #------------------------------------------------------------------------- # # Action handler # #------------------------------------------------------------------------- def cl_action(self,action,options_str): """ Command-line action routine. Try to perform specified action. Any errors will cause the os._exit(1) call. """ if action == 'check': import Check checker = Check.CheckIntegrity(self.parent.db,None,None) checker.check_for_broken_family_links() checker.cleanup_missing_photos(1) checker.check_parent_relationships() checker.cleanup_empty_families(0) errs = checker.build_report(1) if errs: checker.report(1) elif action == 'summary': import Summary text = Summary.build_report(self.parent.db,None) print text elif action == "report": try: options_str_dict = dict( [ tuple(chunk.split('=')) for chunk in options_str.split(',') ] ) except: options_str_dict = {} print "Ignoring invalid options string." name = options_str_dict.pop('name',None) if not name: print "Report name not given. Please use name=reportname" os._exit(1) for item in PluginMgr.cl_list: if name == item[0]: category = item[1] report_class = item[2] options_class = item[3] if category in (Report.CATEGORY_BOOK,Report.CATEGORY_CODE, Report.CATEGORY_WEB): options_class(self.parent.db,name, category,options_str_dict) else: Report.cl_report(self.parent.db,name,category, report_class,options_class,options_str_dict) return print "Unknown report name. Available names are:" for item in PluginMgr.cl_list: print " %s" % item[0] elif action == "tool": try: options_str_dict = dict( [ tuple(chunk.split('=')) for chunk in options_str.split(',') ] ) except: options_str_dict = {} print "Ignoring invalid options string." name = options_str_dict.pop('name',None) if not name: print "Tool name not given. Please use name=toolname" os._exit(1) for item in PluginMgr.cli_tool_list: if name == item[0]: category = item[1] tool_class = item[2] options_class = item[3] Tool.cli_tool(self.parent.db,name,category, tool_class,options_class,options_str_dict) return print "Unknown tool name. Available names are:" for item in PluginMgr.cli_tool_list: print " %s" % item[0] else: print "Unknown action: %s." % action os._exit(1)