| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167 | 
							- import vobject
 
- import glob
 
- import csv
 
- import argparse
 
- import os.path
 
- import sys
 
- import logging
 
- import collections
 
- column_order = [
 
-     'Name',
 
-     'Full name',
 
-     'Cell phone',
 
-     'Work phone',
 
-     'Home phone',
 
-     'Email',
 
-     'Note',
 
- ]
 
- def get_phone_numbers(vCard):
 
-     cell = home = work = None
 
-     for tel in vCard.tel_list:
 
-         if vCard.version.value == '2.1':
 
-             if 'CELL' in tel.singletonparams:
 
-                 cell = str(tel.value).strip()
 
-             elif 'WORK' in tel.singletonparams:
 
-                 work = str(tel.value).strip()
 
-             elif 'HOME' in tel.singletonparams:
 
-                 home = str(tel.value).strip()
 
-             else:
 
-                 logging.warning("Warning: Unrecognized phone number category in `{}'".format(vCard))
 
-                 tel.prettyPrint()
 
-         elif vCard.version.value == '3.0':
 
-             if 'CELL' in tel.params['TYPE']:
 
-                 cell = str(tel.value).strip()
 
-             elif 'WORK' in tel.params['TYPE']:
 
-                 work = str(tel.value).strip()
 
-             elif 'HOME' in tel.params['TYPE']:
 
-                 home = str(tel.value).strip()
 
-             else:
 
-                 logging.warning("Unrecognized phone number category in `{}'".format(vCard))
 
-                 tel.prettyPrint()
 
-         else:
 
-             raise NotImplementedError("Version not implemented: {}".format(vCard.version.value))
 
-     return cell, home, work
 
- def get_info_list(vCard, vcard_filepath):
 
-     vcard = collections.OrderedDict()
 
-     for column in column_order:
 
-         vcard[column] = None
 
-     name = cell = work = home = email = note = None
 
-     vCard.validate()
 
-     for key, val in list(vCard.contents.items()):
 
-         if key == 'fn':
 
-             vcard['Full name'] = vCard.fn.value
 
-         elif key == 'n':
 
-             name = str(vCard.n.valueRepr()).replace('  ', ' ').strip()
 
-             vcard['Name'] = name
 
-         elif key == 'tel':
 
-             cell, home, work = get_phone_numbers(vCard)
 
-             vcard['Cell phone'] = cell
 
-             vcard['Home phone'] = home
 
-             vcard['Work phone'] = work
 
-         elif key == 'email':
 
-             email = str(vCard.email.value).strip()
 
-             vcard['Email'] = email
 
-         elif key == 'note':
 
-             note = str(vCard.note.value)
 
-             vcard['Note'] = note
 
-         else:
 
-             
 
-             pass
 
-     if name is None:
 
-         logging.warning("no name for vCard in file `{}'".format(vcard_filepath))
 
-     if all(telephone_number is None for telephone_number in [cell, work, home]):
 
-         logging.warning("no telephone numbers for file `{}' with name `{}'".format(vcard_filepath, name))
 
-     return vcard
 
- def get_vcards(vcard_filepath):
 
-     with open(vcard_filepath) as fp:
 
-         all_text = fp.read()
 
-     for vCard in vobject.readComponents(all_text):
 
-         yield vCard
 
- def readable_directory(path):
 
-     if not os.path.isdir(path):
 
-         raise argparse.ArgumentTypeError(
 
-             'not an existing directory: {}'.format(path))
 
-     if not os.access(path, os.R_OK):
 
-         raise argparse.ArgumentTypeError(
 
-             'not a readable directory: {}'.format(path))
 
-     return path
 
- def writable_file(path):
 
-     if os.path.exists(path):
 
-         if not os.access(path, os.W_OK):
 
-             raise argparse.ArgumentTypeError(
 
-                 'not a writable file: {}'.format(path))
 
-     else:
 
-         
 
-         
 
-         
 
-         with open(path, 'w') as fp:
 
-             pass
 
-     return path
 
- def main():
 
-     parser = argparse.ArgumentParser(
 
-         description='Convert a bunch of vCard (.vcf) files to a single TSV file.'
 
-     )
 
-     parser.add_argument(
 
-         'read_dir',
 
-         type=readable_directory,
 
-         help='Directory to read vCard files from.'
 
-     )
 
-     parser.add_argument(
 
-         'tsv_file',
 
-         type=writable_file,
 
-         help='Output file',
 
-     )
 
-     parser.add_argument(
 
-         '-v',
 
-         '--verbose',
 
-         help='More verbose logging',
 
-         dest="loglevel",
 
-         default=logging.WARNING,
 
-         action="store_const",
 
-         const=logging.INFO,
 
-     )
 
-     parser.add_argument(
 
-         '-d',
 
-         '--debug',
 
-         help='Enable debugging logs',
 
-         action="store_const",
 
-         dest="loglevel",
 
-         const=logging.DEBUG,
 
-     )
 
-     args = parser.parse_args()
 
-     logging.basicConfig(level=args.loglevel)
 
-     vcard_pattern = os.path.join(args.read_dir, "*.vcf")
 
-     vcard_paths = sorted(glob.glob(vcard_pattern))
 
-     if len(vcard_paths) == 0:
 
-         logging.error("no files ending with `.vcf` in directory `{}'".format(args.read_dir))
 
-         sys.exit(2)
 
-     
 
-     with open(args.tsv_file, 'w') as tsv_fp:
 
-         writer = csv.writer(tsv_fp, delimiter='\t')
 
-         writer.writerow(column_order)
 
-         for vcard_path in vcard_paths:
 
-             for vcard in get_vcards(vcard_path):
 
-                 vcard_info = get_info_list(vcard, vcard_path)
 
-                 writer.writerow(list(vcard_info.values()))
 
- if __name__ == "__main__":
 
-     main()
 
 
  |