Module Gnumed.business.gmVCard
Import vCard data.
Expand source code
# -*- coding: utf-8 -*-
"""Import vCard data."""
#============================================================
__author__ = "K.Hilbert <Karsten.Hilbert@gmx.net>"
__license__ = "GPL v2"
# std lib
import sys
import datetime as pyDT
import logging
# GNUmed
if __name__ == '__main__':
sys.path.insert(0, '../../')
from Gnumed.pycommon import gmI18N
gmI18N.activate_locale()
gmI18N.install_domain()
from Gnumed.pycommon import gmDateTime
from Gnumed.business import gmPerson
from Gnumed.business import gmDemographicRecord
_log = logging.getLogger('gm-vcf')
#============================================================
def __parse_vcard_adr2dto(vcard, dto):
adr = None
try:
adr = vcard.adr.value
except AttributeError:
_log.debug('vCard.ADR attribute not available')
return None
if not adr:
return None
region_code = None
region = adr.region.strip()
if region == '':
region = None
# deduce country
country_code = None
country = adr.country.strip()
if country == '':
country = None
if country is None:
country_row = gmDemographicRecord.map_urb_zip_region2country(urb = adr.city, zip = adr.code, region = region)
if country_row is not None:
country = country_row['country']
country_code = country_row['code_country']
else:
country_code = gmDemographicRecord.map_country2code(country = country)
if None in [country, country_code]:
_log.error('unknown vCard.ADR.country (%s), skipping address', adr.country)
return None
# deduce region
if region is None:
region_row = gmDemographicRecord.map_urb_zip_country2region(urb = adr.city, zip = adr.code, country_code = country_code)
if region_row is not None:
region = region_row['region']
region_code = region_row['code_region']
else:
region_code = gmDemographicRecord.map_region2code(region = region, country_code = country_code)
if region_code is None:
_log.warning('unknown vCard.ADR.region (%s), using default region', adr.region)
dto.remember_address (
number = '?',
street = adr.street,
urb = adr.city,
region_code = region_code,
zip = adr.code,
country_code = country_code,
adr_type = 'home',
subunit = None
)
return dto
#------------------------------------------------------------
def parse_vcard2dto(vc_text=None, filename=None):
import vobject
if vc_text is None:
_log.info('trying to parse vCard from [%s]', filename)
for encoding in ['utf-8-sig', 'Windows-1252']:
try:
vcf = open(filename, mode = 'rt', encoding = encoding)
vc_text = vcf.read()
vcf.close()
break
except UnicodeDecodeError:
_log.exception('vCard not encoded as [%s]', encoding)
if vc_text is None:
return None
vcf_lines = []
found_first = False
for line in vc_text.split('\n'):
if not found_first:
if line.strip() == 'BEGIN:VCARD':
found_first = True
vcf_lines.append(line)
continue
vcf_lines.append(line)
if line.strip() == 'END:VCARD':
break
vc_text = '\n'.join(vcf_lines)
dob_format = '%Y%m%d'
try:
vc = vobject.readOne(vc_text)
except vobject.base.ParseError:
_log.exception('cannot parse, really a vcf ?')
return None
try:
if vc.kind.value.strip() != 'individual':
_log.warning('not a vCard for a single person (vCard.KIND=%s)', vc.kind.value)
return None
except AttributeError:
_log.debug('vCard.KIND attribute not available')
dto = gmPerson.cDTO_person()
dto.firstnames = vc.n.value.given.strip()
dto.lastnames = vc.n.value.family.strip()
try:
dto.title = vc.title.value.strip()
except AttributeError:
_log.debug('vCard.TITLE attribute not available')
try:
gender = vc.gender.value.strip().casefold()
if gender != '':
dto.gender = gender
except AttributeError:
_log.debug('vCard.GENDER attribute not available')
try:
dob = pyDT.datetime.strptime(vc.bday.value.strip(), dob_format)
dto.dob = dob.replace(tzinfo = gmDateTime.pydt_now_here().tzinfo)
dto.dob_is_estimated = False
except AttributeError:
_log.debug('vCard.BDAY attribute not available')
dto.source = 'vCard %s' % vc.version.value.strip()
dto = __parse_vcard_adr2dto(vc, dto)
tel = None
try:
tel = vc.tel.value
except AttributeError:
_log.debug('vCard.TEL attribute not available')
if tel is not None:
if 'TYPE' in vc.tel.params:
channel = (vc.tel.params['TYPE'][0]).casefold()
if not channel.endswith('phone'):
channel += 'phone'
else:
channel = 'homephone'
dto.remember_comm_channel(channel = channel, url = tel)
email = None
try:
email = vc.email.value
except AttributeError:
_log.debug('vCard.EMAIL attribute not available')
if email is not None:
dto.remember_comm_channel(channel = 'email', url = email)
url = None
try:
url = vc.url.value
except AttributeError:
_log.debug('vCard.URL attribute not available')
if url is not None:
dto.remember_comm_channel(channel = 'web', url = url)
return dto
#============================================================
# main/testing
#============================================================
if __name__ == '__main__':
if len(sys.argv) == 1:
sys.exit()
if sys.argv[1] != 'test':
sys.exit()
gmDateTime.init()
def test():
dto = parse_vcard2dto(filename = sys.argv[2])
print(dto)
print(dto.addresses)
print(dto.comm_channels)
test()
Functions
def parse_vcard2dto(vc_text=None, filename=None)
-
Expand source code
def parse_vcard2dto(vc_text=None, filename=None): import vobject if vc_text is None: _log.info('trying to parse vCard from [%s]', filename) for encoding in ['utf-8-sig', 'Windows-1252']: try: vcf = open(filename, mode = 'rt', encoding = encoding) vc_text = vcf.read() vcf.close() break except UnicodeDecodeError: _log.exception('vCard not encoded as [%s]', encoding) if vc_text is None: return None vcf_lines = [] found_first = False for line in vc_text.split('\n'): if not found_first: if line.strip() == 'BEGIN:VCARD': found_first = True vcf_lines.append(line) continue vcf_lines.append(line) if line.strip() == 'END:VCARD': break vc_text = '\n'.join(vcf_lines) dob_format = '%Y%m%d' try: vc = vobject.readOne(vc_text) except vobject.base.ParseError: _log.exception('cannot parse, really a vcf ?') return None try: if vc.kind.value.strip() != 'individual': _log.warning('not a vCard for a single person (vCard.KIND=%s)', vc.kind.value) return None except AttributeError: _log.debug('vCard.KIND attribute not available') dto = gmPerson.cDTO_person() dto.firstnames = vc.n.value.given.strip() dto.lastnames = vc.n.value.family.strip() try: dto.title = vc.title.value.strip() except AttributeError: _log.debug('vCard.TITLE attribute not available') try: gender = vc.gender.value.strip().casefold() if gender != '': dto.gender = gender except AttributeError: _log.debug('vCard.GENDER attribute not available') try: dob = pyDT.datetime.strptime(vc.bday.value.strip(), dob_format) dto.dob = dob.replace(tzinfo = gmDateTime.pydt_now_here().tzinfo) dto.dob_is_estimated = False except AttributeError: _log.debug('vCard.BDAY attribute not available') dto.source = 'vCard %s' % vc.version.value.strip() dto = __parse_vcard_adr2dto(vc, dto) tel = None try: tel = vc.tel.value except AttributeError: _log.debug('vCard.TEL attribute not available') if tel is not None: if 'TYPE' in vc.tel.params: channel = (vc.tel.params['TYPE'][0]).casefold() if not channel.endswith('phone'): channel += 'phone' else: channel = 'homephone' dto.remember_comm_channel(channel = channel, url = tel) email = None try: email = vc.email.value except AttributeError: _log.debug('vCard.EMAIL attribute not available') if email is not None: dto.remember_comm_channel(channel = 'email', url = email) url = None try: url = vc.url.value except AttributeError: _log.debug('vCard.URL attribute not available') if url is not None: dto.remember_comm_channel(channel = 'web', url = url) return dto