#!/usr/bin/env python # -*- coding: utf-8 -*- """ jpilot2google.py ~~~~~~~~~~~~~~~~ This script converts CSV-files exported from (german) jPilot to the import format of Google Contacts :copyright: (c) 2009 by Karl Voit :license: GPL v2 or any later version :bugreports: """ import os, csv, logging, sys, re from optparse import OptionParser import ConfigParser ## http://docs.python.org/library/configparser.html # global variables ## Version history: ## v0.0.1@2009-12-01: initial version with basic functionality for contact import ## v0.2@2009-12-01: omit-if-no-email-and-phone ## v0.3@2009-12-02: ## omit-company-if-name-is-given ## version independent parsing of category column ## removed old testcode ## v0.4@2009-12-08: ## suppress-fax-warnings ## configuration file $HOME/.config/jpilot2google.cfg ## a lot more/verbose debug messages ## detection and adequate output if wrong file format is found ## overwrite-config-file ## added email3 and phone4 ## detection and assignment of phone categories ## some kind of intelligent assignment of private email category depending on known free mail services ## check (and warn): double email addresses or phone numbers ## v0.5@FIXXME PROG_VERSION_NUMBER = "0.4" PROG_VERSION_DATE = "2009-12-08" CONFIGFILENAME = os.path.expanduser('~')+'/.config/jpilot2google.cfg' ## prefix for categories in contacts CONTACT_PREFIX_STRING="Palm_" DEFAULT_PHONE_TYPE='Other' DEFAULT_EMAIL_TYPE='Other' DEFAULT_ADDRESS_TYPE='Other' CONFIG_GENERAL_OVERWRITE_CONFIGFILE_IF_OPTIONS_ARE_MISSING="not_set" CONFIG_CONTACTS_TRUNCATE_FIRSTNAME="not_set" CONFIG_CONTACTS_TRUNCATE_LASTNAME="not_set" CONFIG_CONTACTS_CATEGORY_PREFIX="not_set" CONFIG_CONTACTS_OMIT_PHONES="not_set" CONFIG_CONTACTS_OMIT_EMAILADDRESSES="not_set" CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE="not_set" CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN="not_set" CONFIG_CONTACTS_OMIT_ADDRESSES="not_set" CONFIG_CONTACTS_OMIT_ORGANIZATION="not_set" CONFIG_CONTACTS_OMIT_TITLE="not_set" CONFIG_CONTACTS_OMIT_NOTES="not_set" CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS="not_set" CONFIG_GENERAL_OVERWRITE_CONFIGFILE_IF_OPTIONS_ARE_MISSING="not_set" ## only for internal data representation of google import addresses SEE_FORMATTED_ADDRESS_STRING=' ::: ' # cmdline parsing USAGE = "\n\ %prog [options] inputfile outputfile\n\ \n\ This script converts CSV-files exported from (german) jPilot to \n\ the import format of Google Contacts\n\ \n\ :copyright: (c) 2009 by Karl Voit \n\ :license: GPL v2 or any later version\n\ :bugreports: \n\ :version: "+PROG_VERSION_NUMBER+" from "+PROG_VERSION_DATE+"\n\ \n\ Not yet implemented:\n\ Contacts:\n\ * English CSV file format\n\ * categories/types/labels of postal addresses\n\ Calendar:\n\ * insert e.g. \"TZID=Europe/Vienna\" to correct import time of Google\n\ * limit only to events X days in the past and Y days in the future\n\ \n\ Probably never implemented due to missing fields:\n\ Contacts:\n\ * the four user defined JPilot/Palm-fields\n\ * private-flag\n\ * tasks, calendar/events, memos, ...\n\ \n\ WARNING: please do check output file manually before importing to Google!\n\ \n\ Run %prog --help for usage hints\n" class vk_FileNotFoundException(Exception): def __init__(self, value): self.value = value def __str__(self): return repr(self.value) # pylint: disable-msg=C0103 parser = OptionParser(usage=USAGE) parser.add_option("--contacts", dest="convertcontacts", action="store_true", help="convert contact CSV format") parser.add_option("--calendar", dest="convertcalendar", action="store_true", help="convert calendar CSV format") parser.add_option("--truncate-firstname", dest="truncate_firstname", action="store_true", help="contacts: truncate the firstnames to first character and a dot") parser.add_option("--truncate-lastname", dest="truncate_lastname", action="store_true", help="contacts: truncate the lastnames to first character and a dot") parser.add_option("--category-prefix", dest="category_prefix", action="store_true", help="contacts: add a prefix to category fields") parser.add_option("--omit-phones", dest="omit_phones", action="store_true", help="contacts: ignore all phone numbers") parser.add_option("--suppress-fax-warnings", dest="suppress_fax_warnings", action="store_true", help="contacts: do not show warning when fax numbers are not processed") parser.add_option("--omit-emailaddresses", dest="omit_emailaddresses", action="store_true", help="contacts: ignore all email addresses") parser.add_option("--omit-if-no-email-and-phone", dest="omit_if_no_email_and_phone", action="store_true", help="contacts: ignore all contacts that got no email and no phone") parser.add_option("--omit-company-if-name-is-given", dest="omit_company_if_name_is_given", action="store_true", help="contacts: do not include company information if a contact has a full name") parser.add_option("--omit-addresses", dest="omit_addresses", action="store_true", help="contacts: ignore all postal addresses") parser.add_option("--omit-organization", dest="omit_organization", action="store_true", help="contacts: ignore the organization/company field") parser.add_option("--omit-title", dest="omit_title", action="store_true", help="contacts: ignore the title field") parser.add_option("--omit-notes", dest="omit_notes", action="store_true", help="ignore the notes field") parser.add_option("--overwrite-config-file", dest="overwrite_config_file_if_options_are_missing", action="store_true", help="overwrite the config file with a version that includes all currently set options") parser.add_option("--version", dest="version", action="store_true", help="display version and exit") parser.add_option("-v", "--verbose", dest="verbose", action="store_true", help="enable verbose mode") parser.add_option("-q", "--quiet", dest="quiet", action="store_true", help="do not output anything but just errors on console") (options, args) = parser.parse_args() def handle_logging(): """Log handling and configuration""" if options.verbose: FORMAT = "%(levelname)-8s %(asctime)-15s %(message)s" logging.basicConfig(level=logging.DEBUG, format=FORMAT) elif options.quiet: FORMAT = "%(levelname)-8s %(message)s" logging.basicConfig(level=logging.CRITICAL, format=FORMAT) else: FORMAT = "%(message)s" logging.basicConfig(level=logging.INFO, format=FORMAT) def writeGoogleHeader(writer): writer.writerow(['Given Name', 'Additional Name','Family Name' ,'Yomi Name' , 'Given Name Yomi' ,'Additional Name Yomi' ,'Family Name Yomi' , 'Name Prefix' ,'Name Suffix' ,'Initials' ,'Nickname' ,'Short Name' , 'Maiden Name' ,'Birthday' ,'Gender' ,'Location' ,'Billing Information' , 'Directory Server' ,'Mileage' ,'Occupation' ,'Hobby' ,'Sensitivity' , 'Priority' ,'Subject' ,'Notes' ,'Group Membership' ,'E-mail 1 - Type' , 'E-mail 1 - Value' ,'E-mail 2 - Type' ,'E-mail 2 - Value' ,'E-mail 3 - Type' ,'E-mail 3 - Value' ,'IM 1 - Type' , 'IM 1 - Service' ,'IM 1 - Value' ,'Phone 1 - Type' ,'Phone 1 - Value' , 'Phone 2 - Type' ,'Phone 2 - Value' ,'Phone 3 - Type' ,'Phone 3 - Value' ,'Phone 4 - Type' ,'Phone 4 - Value' , 'Address 1 - Type' ,'Address 1 - Formatted' ,'Address 1 - Street' , 'Address 1 - City' ,'Address 1 - PO Box' ,'Address 1 - Region' , 'Address 1 - Postal Code' ,'Address 1 - Country' ,'Address 1 - Extended Address' , 'Address 2 - Type' ,'Address 2 - Formatted' ,'Address 2 - Street' , 'Address 2 - City' ,'Address 2 - PO Box' ,'Address 2 - Region' , 'Address 2 - Postal Code' ,'Address 2 - Country' ,'Address 2 - Extended Address' , 'Organization 1 - Type' ,'Organization 1 - Name' ,'Organization 1 - Yomi Name' , 'Organization 1 - Title' ,'Organization 1 - Department' , 'Organization 1 - Symbol' ,'Organization 1 - Location' , 'Organization 1 - Job Description' ,'Website 1 - Type' , 'Website 1 - Value' ,'Website 2 - Type' ,'Website 2 - Value' , 'Custom Field 1 - Type' ,'Custom Field 1 - Value']) def addPhoneNumberToContact(phonenumber, contact, debugidentifier, labelstring): phone_stored=False for phoneindex in range(1,5): if not contact['phone'+str(phoneindex)]: contact['phone'+str(phoneindex)]=str(phonenumber) ## Google offers me for phone number categories: ## Home, Work, Mobile, Home Fax, Work Fax, Pager, Other if labelstring=='Haupt': contact['phonetype'+str(phoneindex)] = 'Home' elif labelstring=='Handy': contact['phonetype'+str(phoneindex)] = 'Mobile' elif labelstring=='Privat': contact['phonetype'+str(phoneindex)] = 'Home' elif labelstring=='Andere': contact['phonetype'+str(phoneindex)] = 'Other' elif labelstring=='Pager': contact['phonetype'+str(phoneindex)] = 'Pager' elif re.match("B.ro", labelstring): contact['phonetype'+str(phoneindex)] = 'Work' elif labelstring=='E-Mail': logging.warning('found probably a phone number [%s] labeled with \"E-Mail\" in your palm data of contact [%s]. I use category \"Other\" for now.' % (phonenumber, debugidentifier )) contact['phonetype'+str(phoneindex)] = 'Other' else: logging.warning('found no known label [%s] to phone number [%s] for [%s], using default value \"\"' % (labelstring, phonenumber, debugidentifier, DEFAULT_PHONE_TYPE) ) contact['phonetype'+str(phoneindex)] = DEFAULT_PHONE_TYPE phone_stored=True break else: ## contact entry is already in use. try to search for double entries if contact['phone'+str(phoneindex)] == phonenumber: logging.warning('found double phone number \"%s\" for contact \"%s\". I ignore this number.' % (phonenumber, debugidentifier)) if not phone_stored: logging.warning("Phonenumber %s of contact %s could not be added because there are already four numbers found and there is no empty field left" % ( phonenumber, debugidentifier)) def addEmailToContact(emailaddress, contact, debugidentifier, labelstring): email_stored=False ## Google offers me for email categories: ## Home, Work, Other ## but JPilot export only offers "E-Mail" so no assignment is possible :-( for emailindex in range(1,4): if not contact['email'+str(emailindex)]: contact['email'+str(emailindex)]=emailaddress ## try to guess the category of the email address by searching for known substrings in the address: if re.match(".*@(gmx|gmail|hotmail|aon|msn|sbox|student|yahoo|eircom|aol|chello|gentoo|debian|karl-voit|utanet)\..*", emailaddress.lower()): logging.debug('I am guessing, that this is a private address [%s]', emailaddress) contact['emailtype'+str(emailindex)] = 'Home' elif re.match(".*@(tugraz|virtuellesfahrzeug|v2c2|accgraz|siemens|campus02|ist|iicm|iti|magnasteyr|klinikum-graz|uni-graz|univie|isi-graz)\..*", emailaddress.lower()): logging.debug('I am guessing (because of provider), that this is a work address [%s]', emailaddress) contact['emailtype'+str(emailindex)] = 'Work' elif re.match(".*@.*\.(edu|gov|com|mil|co\.at|tu-graz\.ac\.at)(\..*)?", emailaddress.lower()): logging.debug('I am guessing (because of domain ending), that this is a work address [%s]', emailaddress) contact['emailtype'+str(emailindex)] = 'Work' else: logging.debug('could not guess, wether emailaddress [%s] is private or not; using default category \"%s\"' % (emailaddress, DEFAULT_EMAIL_TYPE)) contact['emailtype'+str(emailindex)] = DEFAULT_EMAIL_TYPE email_stored=True break else: ## contact entry is already in use. try to search for double entries if contact['email'+str(emailindex)] == emailaddress: logging.warning('found double email address \"%s\" for contact \"%s\". I ignore this address.' % (emailaddress, debugidentifier)) if not email_stored: logging.warning("Emailaddress %s of contact %s could not be added because there are already three e-mail addresses found and there is no empty field left" % ( emailaddress, debugidentifier)) def writeSingleContact(outputWriter, contact): outputWriter.writerow([contact['firstname'], '',contact['lastname'] ,'' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , contact['notes'] , '* My Contacts ::: '+contact['category'] , contact['emailtype1'] , contact['email1'] , contact['emailtype2'] , contact['email2'] , contact['emailtype3'] , contact['email3'] , '' , '' , '' , contact['phonetype1'] , contact['phone1'] , contact['phonetype2'] , contact['phone2'] , contact['phonetype3'] , contact['phone3'] , contact['phonetype4'] , contact['phone4'] , DEFAULT_ADDRESS_TYPE , contact['address1'] , SEE_FORMATTED_ADDRESS_STRING , SEE_FORMATTED_ADDRESS_STRING , SEE_FORMATTED_ADDRESS_STRING , SEE_FORMATTED_ADDRESS_STRING , SEE_FORMATTED_ADDRESS_STRING , SEE_FORMATTED_ADDRESS_STRING , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , '' , contact['company'], '' , contact['title'] , '' , '' , '' , '' , '' , '' , '' , '' , '' , '']) def parseContactRow(row, contact): ## search for category column like 'CSV address version 1.6.2.7: Category' for key, value in row.items(): if re.match("CSV address version.*Category", key): contact['category']=value logging.debug("found category %s for %s" % ( value, row[' Nachname'] ) ) try: if not contact['category']: logging.critical("found no category for entry %s %s %s" % ( row[' Vorname'], row[' Nachname'], row[' Firma'] ) ) except KeyError: logging.critical("Found no category field. Probably wrong input file format (did you export to text instead of the expected CSV)?") sys.exit(7) if CONFIG_CONTACTS_CATEGORY_PREFIX: contact['category'] = CONTACT_PREFIX_STRING + contact['category'] if row[' Nachname'] and CONFIG_CONTACTS_TRUNCATE_LASTNAME: contact['lastname']=row[' Nachname'][0:1] + '.' else: contact['lastname']=row[' Nachname'] if row[' Vorname'] and CONFIG_CONTACTS_TRUNCATE_FIRSTNAME: contact['firstname']=row[' Vorname'][0:1] + '.' else: contact['firstname']=row[' Vorname'] if not CONFIG_CONTACTS_OMIT_TITLE: contact['title']=row[' Titel'] else: contact['title']='' if not CONFIG_CONTACTS_OMIT_ORGANIZATION: contact['company']=row[' Firma'] else: contact['company']='' if CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN and contact['lastname'] and contact['firstname']: logging.debug('omitting company info %s of %s %s due to CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN' % ( contact['company'], contact['firstname'], contact['lastname'] ) ) contact['company']='' if not CONFIG_CONTACTS_OMIT_NOTES: contact['notes']=row[' Notiz'] else: contact['notes']='' ## collect address data depending on given fields: if not CONFIG_CONTACTS_OMIT_ADDRESSES and row[' Adr. (B)']: logging.debug('Found Addr. B, checking other data ...') if row[' Postleitzahl'] and row[' Ort'] and not row[' Land']: logging.debug('found PLZ, Ort and no Land') contact['address1'] = row[' Adr. (B)'] + '\n' + row[' Postleitzahl'] + ' ' + row[' Ort'] elif row[' Postleitzahl'] and row[' Ort'] and row[' Land']: logging.debug('found PLZ, Ort and Land - full address') contact['address1'] = \ row[' Adr. (B)'] + '\n' + \ row[' Postleitzahl'] + ' ' + row[' Ort'] + '\n' + \ row[' Land'] else: logging.debug('found AdrB only') contact['address1'] = row[' Adr. (B)'] else: logging.debug('found no AdrB (or omitting by user choice)') contact['address1'] = '' debugidentifier=str(contact['firstname']) + '|' + str(contact['lastname']) + '|' + str(contact['company']) for phoneindex in range(0,5): currentphoneline=row[' Phone '+str(phoneindex)] ## handle fax (not yet supported), email, and phonenumbers if currentphoneline: logging.debug('Debugidentifier [%s], Phoneline [%s]' % ( debugidentifier, currentphoneline )) if row[' Phone '+str(phoneindex)+' label'] == 'Fax': if not CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS: logging.warning("Faxnumber %s of Surname %s omitted: google offers no contact field for that. I ignore this number." % (currentphoneline , contact['lastname'])) break elif '@' in currentphoneline: if not CONFIG_CONTACTS_OMIT_EMAILADDRESSES: addEmailToContact(currentphoneline, contact, debugidentifier, row[' Phone '+str(phoneindex)+' label']) else: if not CONFIG_CONTACTS_OMIT_PHONES: modified_phone_number = currentphoneline ## hidden feature: adding austrian international number to austrian numbers: if re.match("^0(316|664|699|650|676|660|6888)", currentphoneline): ## a dirty trick to make sure, that this is only happening on *my* computer ;-) if str(os.environ['LOGNAME']) == 'vk': logging.debug('found austrian number [%s], adding \"+43\" upfront', currentphoneline) modified_phone_number = '+43/'+currentphoneline[1:] addPhoneNumberToContact(modified_phone_number, contact, debugidentifier, row[' Phone '+str(phoneindex)+' label']) def generateContactFile(inputfilename, google_csv_file_name): jpilotReader = csv.DictReader(open(inputfilename), delimiter=',') outputWriter = csv.writer(open(google_csv_file_name, 'w'), delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL) writeGoogleHeader(outputWriter) row_counter=0 omitted_because_no_email_phone_counter=0 for row in jpilotReader: ## resetting contact dictionary contact = {'email1':'', 'emailtype1':'', 'email2':'', 'emailtype2':'', 'email3':'', 'emailtype3':'', 'phone1':'', 'phonetype1':'', 'phone2':'', 'phonetype2':'', 'phone3':'', 'phonetype3':'', 'phone4':'', 'phonetype4':'' } row_counter+=1 parseContactRow(row, contact) if CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE and not contact['phone1'] and not contact['phone2'] and \ not contact['phone3'] and not contact['phone4'] and \ not contact['email1'] and not contact['email2'] and not contact['email3']: logging.debug('omiting contact %s %s %s because there is no email nor phone and CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE was true' % ( contact['lastname'], contact['firstname'],contact['company']) ) omitted_because_no_email_phone_counter+=1 else: writeSingleContact(outputWriter, contact) logging.info('%i contacts parsed' % row_counter) if CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE: logging.info('%i contacts omitted because they got no email and no phone' % omitted_because_no_email_phone_counter) def handleSingleConfigFileSetting(config, section_name, config_name, default_value): global CONFIG_FILE_IS_COMPLETE global_config_variable = default_value try: logging.debug('configfile: option [%s] in section [%s] found and set to \"%s\"' % (config_name, section_name, config.getboolean(section_name, config_name)) ) return config.getboolean(section_name, config_name) except ConfigParser.NoOptionError: CONFIG_FILE_IS_COMPLETE = False config.set(section_name, config_name, str(default_value)) logging.debug('configfile: option [%s] in section [%s] NOT found, using default value of \"%s\"' % (config_name, section_name, str(default_value)) ) return default_value except ConfigParser.NoSectionError: CONFIG_FILE_IS_COMPLETE = False config.add_section(section_name) config.set(section_name, config_name, str(default_value)) logging.debug('configfile: section [%s] (for option \"%s\") NOT found. Generated one.' % (section_name, config_name) ) return default_value def parseConfigFile(CONFIGFILENAME): config = ConfigParser.SafeConfigParser() config.readfp(open(CONFIGFILENAME)) logging.debug("setting options from configuration file") global CONFIG_FILE_IS_COMPLETE ## positive assumption which has to be falsified by handleSingleConfigFileSetting() CONFIG_FILE_IS_COMPLETE = True logging.debug("before parsing the config file: CONFIG_FILE_IS_COMPLETE is set to %s" % CONFIG_FILE_IS_COMPLETE) global CONFIG_CONTACTS_TRUNCATE_FIRSTNAME CONFIG_CONTACTS_TRUNCATE_FIRSTNAME = handleSingleConfigFileSetting(config, 'Contacts', 'truncate-firstname', False) global CONFIG_CONTACTS_TRUNCATE_LASTNAME CONFIG_CONTACTS_TRUNCATE_LASTNAME = handleSingleConfigFileSetting(config, 'Contacts', 'truncate-lastname', True) global CONFIG_CONTACTS_CATEGORY_PREFIX CONFIG_CONTACTS_CATEGORY_PREFIX = handleSingleConfigFileSetting(config, 'Contacts', 'category-prefix', True) global CONFIG_CONTACTS_OMIT_PHONES CONFIG_CONTACTS_OMIT_PHONES = handleSingleConfigFileSetting(config, 'Contacts', 'omit-phones', False) global CONFIG_CONTACTS_OMIT_EMAILADDRESSES CONFIG_CONTACTS_OMIT_EMAILADDRESSES = handleSingleConfigFileSetting(config, 'Contacts', 'omit-emailaddresses', False) global CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE = handleSingleConfigFileSetting(config, 'Contacts', 'omit-if-no-email-and-phone', False) global CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN = handleSingleConfigFileSetting(config, 'Contacts', 'omit-company-if-name-is-given', False) global CONFIG_CONTACTS_OMIT_ADDRESSES CONFIG_CONTACTS_OMIT_ADDRESSES = handleSingleConfigFileSetting(config, 'Contacts', 'omit-addresses', False) global CONFIG_CONTACTS_OMIT_ORGANIZATION CONFIG_CONTACTS_OMIT_ORGANIZATION = handleSingleConfigFileSetting(config, 'Contacts', 'omit-organization', False) global CONFIG_CONTACTS_OMIT_TITLE CONFIG_CONTACTS_OMIT_TITLE = handleSingleConfigFileSetting(config, 'Contacts', 'omit-title', False) global CONFIG_CONTACTS_OMIT_NOTES CONFIG_CONTACTS_OMIT_NOTES = handleSingleConfigFileSetting(config, 'Contacts', 'omit-notes', False) global CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS = handleSingleConfigFileSetting(config, 'Contacts', 'suppress-fax-warnings', False) logging.debug("after parsing the config file: CONFIG_FILE_IS_COMPLETE is set to %s" % CONFIG_FILE_IS_COMPLETE) def overwriteConfigFileWithCurrentSettings(): currentconfig = ConfigParser.SafeConfigParser() ## NOTE: cool Python v5 version that did not work on my system: ##with open(CONFIGFILENAME, 'wb') as newconfigfile: ## config.write(newconfigfile) logging.info("config file \"%s\" was missing some options, will write a new one using current settings ..." % CONFIGFILENAME) currentconfig.add_section('General') currentconfig.add_section('Contacts') currentconfig.set('Contacts','truncate-firstname', str(CONFIG_CONTACTS_TRUNCATE_FIRSTNAME)) currentconfig.set('Contacts','truncate-lastname', str(CONFIG_CONTACTS_TRUNCATE_LASTNAME)) currentconfig.set('Contacts','category-prefix', str(CONFIG_CONTACTS_CATEGORY_PREFIX)) currentconfig.set('Contacts','omit-phones', str(CONFIG_CONTACTS_OMIT_PHONES)) currentconfig.set('Contacts','omit-emailaddresses',str(CONFIG_CONTACTS_OMIT_EMAILADDRESSES)) currentconfig.set('Contacts','omit-if-no-email-and-phone',str(CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE)) currentconfig.set('Contacts','omit-company-if-name-is-given',str(CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN)) currentconfig.set('Contacts','omit-addresses', str(CONFIG_CONTACTS_OMIT_ADDRESSES)) currentconfig.set('Contacts','omit-organization', str(CONFIG_CONTACTS_OMIT_ORGANIZATION)) currentconfig.set('Contacts','omit-title', str(CONFIG_CONTACTS_OMIT_TITLE)) currentconfig.set('Contacts','omit-notes', str(CONFIG_CONTACTS_OMIT_NOTES)) currentconfig.set('Contacts','suppress-fax-warnings',str(CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS)) newconfigfilehandler = None try: newconfigfilehandler = open(CONFIGFILENAME, 'wb') currentconfig.write(newconfigfilehandler) except IOError: logging.critical("Cannot write to the config file \"%s\"" % CONFIGFILENAME) sys.exit(8) logging.info("config file \"%s\" is up to date now." % CONFIGFILENAME) def handleContactCommandLineOptions(): logging.debug("setting options from command line switches") global CONFIG_CONTACTS_CATEGORY_PREFIX logging.debug('CONFIG_CONTACTS_CATEGORY_PREFIX before command line argument: \"%s\"' % CONFIG_CONTACTS_CATEGORY_PREFIX) if options.category_prefix: CONFIG_CONTACTS_CATEGORY_PREFIX=True logging.debug('CONFIG_CONTACTS_CATEGORY_PREFIX after command line argument: \"%s\"' % CONFIG_CONTACTS_CATEGORY_PREFIX) global CONFIG_CONTACTS_TRUNCATE_FIRSTNAME logging.debug('CONFIG_CONTACTS_TRUNCATE_FIRSTNAME before command line argument: \"%s\"' % CONFIG_CONTACTS_TRUNCATE_FIRSTNAME) if options.truncate_firstname: CONFIG_CONTACTS_TRUNCATE_FIRSTNAME=True logging.debug('CONFIG_CONTACTS_TRUNCATE_FIRSTNAME after command line argument: \"%s\"' % CONFIG_CONTACTS_TRUNCATE_FIRSTNAME) global CONFIG_CONTACTS_TRUNCATE_LASTNAME logging.debug('CONFIG_CONTACTS_TRUNCATE_LASTNAME before command line argument: \"%s\"' % CONFIG_CONTACTS_TRUNCATE_LASTNAME) if options.truncate_lastname: CONFIG_CONTACTS_TRUNCATE_LASTNAME=True logging.debug('CONFIG_CONTACTS_TRUNCATE_LASTNAME after command line argument: \"%s\"' % CONFIG_CONTACTS_TRUNCATE_LASTNAME) global CONFIG_CONTACTS_OMIT_PHONES logging.debug('CONFIG_CONTACTS_OMIT_PHONES before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_PHONES) if options.omit_phones: CONFIG_CONTACTS_OMIT_PHONES=True logging.debug('CONFIG_CONTACTS_OMIT_PHONES after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_PHONES) global CONFIG_CONTACTS_OMIT_EMAILADDRESSES logging.debug('CONFIG_CONTACTS_OMIT_EMAILADDRESSES before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_EMAILADDRESSES) if options.omit_emailaddresses: CONFIG_CONTACTS_OMIT_EMAILADDRESSES=True logging.debug('CONFIG_CONTACTS_OMIT_EMAILADDRESSES after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_EMAILADDRESSES) global CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS logging.debug('CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS before command line argument: \"%s\"' % CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS) if options.suppress_fax_warnings: CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS=True logging.debug('CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS after command line argument: \"%s\"' % CONFIG_CONTACTS_SUPPRESS_FAXWARNINGS) global CONFIG_CONTACTS_OMIT_ADDRESSES logging.debug('CONFIG_CONTACTS_OMIT_ADDRESSES before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_ADDRESSES) if options.omit_addresses: CONFIG_CONTACTS_OMIT_ADDRESSES=True logging.debug('CONFIG_CONTACTS_OMIT_ADDRESSES after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_ADDRESSES) global CONFIG_CONTACTS_OMIT_ORGANIZATION logging.debug('CONFIG_CONTACTS_OMIT_ORGANIZATION before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_ORGANIZATION) if options.omit_organization: CONFIG_CONTACTS_OMIT_ORGANIZATION=True logging.debug('CONFIG_CONTACTS_OMIT_ORGANIZATION after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_ORGANIZATION) global CONFIG_CONTACTS_OMIT_TITLE logging.debug('CONFIG_CONTACTS_OMIT_TITLE before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_TITLE) if options.omit_title: CONFIG_CONTACTS_OMIT_TITLE=True logging.debug('CONFIG_CONTACTS_OMIT_TITLE after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_TITLE) global CONFIG_CONTACTS_OMIT_NOTES logging.debug('CONFIG_CONTACTS_OMIT_NOTES before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_NOTES) if options.omit_notes: CONFIG_CONTACTS_OMIT_NOTES=True logging.debug('CONFIG_CONTACTS_OMIT_NOTES after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_NOTES) global CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE logging.debug('CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE) if options.omit_if_no_email_and_phone: CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE=True logging.debug('CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_IF_NO_EMAIL_AND_PHONE) global CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN logging.debug('CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN before command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN) if options.omit_company_if_name_is_given: CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN=True logging.debug('CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN after command line argument: \"%s\"' % CONFIG_CONTACTS_OMIT_COMPANY_IF_NAME_IS_GIVEN) def main(): """Main function [make pylint happy :)]""" if options.version: print os.path.basename(sys.argv[0]) + " version "+PROG_VERSION_NUMBER+" from "+PROG_VERSION_DATE sys.exit(0) if len(args) < 2: parser.error("invalid usage") handle_logging() ## error, if config-file is not found #if not os.path.isfile( CONFIGFILENAME ): # raise vk_FileNotFoundException( CONFIGFILENAME ) if options.overwrite_config_file_if_options_are_missing: CONFIG_GENERAL_OVERWRITE_CONFIGFILE_IF_OPTIONS_ARE_MISSING = True else: CONFIG_GENERAL_OVERWRITE_CONFIGFILE_IF_OPTIONS_ARE_MISSING = False if os.path.isfile( CONFIGFILENAME ): logging.debug("found configfile \"%s\" and reading it ..." % CONFIGFILENAME ) parseConfigFile( CONFIGFILENAME ) else: logging.debug("found no configfile \"%s\"" % CONFIGFILENAME ) if options.convertcontacts: logging.debug("mode set to: converting JPilot CSV contacts") handleContactCommandLineOptions() if CONFIG_GENERAL_OVERWRITE_CONFIGFILE_IF_OPTIONS_ARE_MISSING: overwriteConfigFileWithCurrentSettings() jpilot_csv_file_name = args[0] google_csv_file_name = args[1] ## jpilot_csv_file_name has to be a file if not os.path.isfile(jpilot_csv_file_name): logging.critical("\"%s\" is not an existing file" % jpilot_csv_file_name) sys.exit(2) ## google_csv_file_name must not be a file/dir if os.path.isfile(google_csv_file_name) or os.path.isdir(google_csv_file_name): logging.warning("\"%s\" already exists" % google_csv_file_name) logging.debug("I will convert \"%s\" to \"%s\"" % ( jpilot_csv_file_name, google_csv_file_name ) ) generateContactFile(jpilot_csv_file_name, google_csv_file_name) sys.exit(0) if options.convertcalendar: logging.debug("I will convert JPilot CSV calendar") logging.critical("Sorry, calendar convertion support not implemented yet! (coming soon)") sys.exit(42) else: parser.error("You did not provide one of --contacts or --calendar") if __name__ == "__main__": try: main() except KeyboardInterrupt: logging.info("Received KeyboardInterrupt") ## END OF FILE ################################################################# # vim:foldmethod=indent expandtab ai ft=python tw=120 fileencoding=utf-8 shiftwidth=4