[Vobject] Mac OS X AddressBook and vobject
Lars Immisch
lars at ibp.de
Tue Jan 17 17:43:06 CST 2006
Dear Jeffrey,
I got as far as bubbling up the group info to ContentLine (without
breaking any doctests after adjustments).
So: another patch. This time as attachment.
The longer I think about RFC 2426 groups, the more am I convinced that
it's a classical standards bug: Not a bad idea in itself, but
underspecified and subsequently abused.
That being said, groups are in the standard, and I am strongly in favour
of including it into vobject, my peripheral doubts in RFC 2425 and RFC
2526 notwithstanding.
You'll probably see worse once Chandler becomes reality.
- Lars
P.S:
I do like the example in RFC 2425, section 8.3. Someone was in love with
Görlitz (and so am I):
begin:vcard
source:ldap://cn=Meister%20Berger,o=Universitaet%20Goerlitz,c=DE
name:Meister Berger
fn:Meister Berger
n:Berger;Meister
bday;value=date:1963-09-21
o:Universit=E6t G=F6rlitz
title:Mayor
title;language=de;value=text:Burgermeister
note:The Mayor of the great city of
Goerlitz in the great country of Germany.
email;internet:mb at goerlitz.de
home.tel;type=fax,voice,msg:+49 3581 123456
home.label:Hufenshlagel 1234\n
02828 Goerlitz\n
Deutschland
end:vcard
-------------- next part --------------
Index: vobject.py
===================================================================
--- vobject.py (revision 104)
+++ vobject.py (working copy)
@@ -177,6 +177,8 @@
be empty for empty parameters).
@ivar value:
The value of the contentline.
+ @ivar group:
+ The optional group prefix, used for provate purposes of the generator.
@ivar singletonparams:
A list of parameters for which it's unclear if the string represents the
parameter name or the parameter value. In vCard 2.1, "The value string
@@ -193,12 +195,14 @@
@ivar lineNumber:
An optional line number associated with the contentline.
"""
- def __init__(self, name, params, value, encoded=False, corruption=None,
- isNative=False, lineNumber = None, *args, **kwds):
+ def __init__(self, name, params, value, group = None,
+ encoded=False, corruption=None,
+ isNative=False, lineNumber = None, *args, **kwds):
"""Take output from parseLine, convert params list to dictionary."""
super(ContentLine, self).__init__(*args, **kwds)
self.name = name.upper()
self.value = value
+ self.group = group
self.corruption = corruption
self.encoded = encoded
self.params = {}
@@ -307,12 +311,14 @@
else:
object.__setattr__(self, name, value)
- def add(self, objOrName):
+ def add(self, objOrName, group = None):
"""Add objOrName to contents, set behavior if it can be inferred.
If objOrName is a string, create an empty component or line based on
behavior. If no behavior is found for the object, add a ContentLine.
-
+
+ group is an optional prefix to the name of the object (see
+ RFC 2425).
"""
if isinstance(objOrName, VBase):
obj = objOrName
@@ -327,12 +333,12 @@
if behavior.isComponent:
obj = Component(name)
else:
- obj = ContentLine(name, [], '')
+ obj = ContentLine(name, [], '', group)
obj.parentBehavior = self.behavior
obj.behavior = behavior
obj = obj.transformToNative()
except (KeyError, AttributeError):
- obj = ContentLine(objOrName, [], '')
+ obj = ContentLine(objOrName, [], '', group)
self.contents.setdefault(obj.name.lower(), []).append(obj)
return obj
@@ -464,11 +470,11 @@
)?
""" % patterns
-# get a full content line, break it up into name, parameters, and value
+# get a full content line, break it up into group, name, parameters, and value
patterns['line'] = r"""
-^ (?P<name> %(name)s ) # name group
- (?P<params> (?: %(param)s )* ) # params group (may be empty)
-: (?P<value> .* )$ # value group
+^ ((?P<group> %(name)s)\.)?(?P<name> %(name)s) # name group
+ (?P<params> (?: %(param)s )* ) # params group (may be empty)
+: (?P<value> .* )$ # value group
""" % patterns
' "%(qsafe_char)s*" | %(safe_char)s* '
@@ -503,15 +509,17 @@
def parseLine(line):
"""
>>> parseLine("BLAH:")
- ('BLAH', [], '')
+ ('BLAH', [], '', None)
>>> parseLine("RDATE:VALUE=DATE:19970304,19970504,19970704,19970904")
- ('RDATE', [], 'VALUE=DATE:19970304,19970504,19970704,19970904')
+ ('RDATE', [], 'VALUE=DATE:19970304,19970504,19970704,19970904', None)
>>> parseLine('DESCRIPTION;ALTREP="http://www.wiz.org":The Fall 98 Wild Wizards Conference - - Las Vegas, NV, USA')
- ('DESCRIPTION', [['ALTREP', 'http://www.wiz.org']], 'The Fall 98 Wild Wizards Conference - - Las Vegas, NV, USA')
+ ('DESCRIPTION', [['ALTREP', 'http://www.wiz.org']], 'The Fall 98 Wild Wizards Conference - - Las Vegas, NV, USA', None)
>>> parseLine("EMAIL;PREF;INTERNET:john at nowhere.com")
- ('EMAIL', [['PREF'], ['INTERNET']], 'john at nowhere.com')
+ ('EMAIL', [['PREF'], ['INTERNET']], 'john at nowhere.com', None)
>>> parseLine('EMAIL;TYPE="blah",hah;INTERNET="DIGI",DERIDOO:john at nowhere.com')
- ('EMAIL', [['TYPE', 'blah', 'hah'], ['INTERNET', 'DIGI', 'DERIDOO']], 'john at nowhere.com')
+ ('EMAIL', [['TYPE', 'blah', 'hah'], ['INTERNET', 'DIGI', 'DERIDOO']], 'john at nowhere.com', None)
+ >>> parseLine('item1.ADR;type=HOME;type=pref:;;Reeperbahn 116;Hamburg;;20359;')
+ ('ADR', [['type', 'HOME'], ['type', 'pref']], ';;Reeperbahn 116;Hamburg;;20359;', 'item1')
>>> parseLine(":")
Traceback (most recent call last):
...
@@ -523,7 +531,7 @@
raise ParseError("Failed to parse line: %s" % line)
return (match.group('name'),
parseParams(match.group('params')),
- match.group('value'))
+ match.group('value'), match.group('group'))
# logical line regular expressions
@@ -814,4 +822,4 @@
#------------------- Testing and running functions -----------------------------
if __name__ == '__main__':
import tests
- tests._test()
\ No newline at end of file
+ tests._test()
More information about the VObject
mailing list