suppose i have built a VObject called vobj
(e.g., built via vobject.readComponents(vcfStr)
) and want to add a new key:value pair to it:
print('k=%s v=%s' % (k,v))
try:
stmnt1 = "vobj.add('%s')" % (k)
print('stmnt1:"%s"' % stmnt1)
eval(stmnt1)
print('vobj after add\n'+20*'#'+'\n')
vobj.prettyPrint()
stmnt2 = "vobj.%s.value = '%s'" % (k,v)
print('\n'+20*'#'+('\nstmnt2:"%s"' % stmnt2))
eval(stmnt2)
except Exception as e:
print('wazzup?!',e)
all the extra prints and the try:except
are because i can't
make it work! here's the output produced:
k=bday v=1931-02-10
stmnt1:"vobj.add('bday')"
vobj after add
####################
VCARD
VERSION: 3.0
PRODID: -//Apple Inc.//Mac OS X 10.12.3//EN
N: Foo Bar
FN: Foo Bar
EMAIL: foo@bar.com
params for EMAIL:
TYPE ['INTERNET', 'WORK', 'pref']
...
BDAY:
####################
stmnt2:"vobj.bday.value = '1931-02-10'"
wazzup?! invalid syntax (<string>, line 1)
i have three specific questions:
VObject makes use of object.attribute
"dot" notation,
and the only way i've found to handle arbitrary key names
is using eval()
. there must be a more pythonic way?
evaluation of the first statement stmnt1
works, and changes
vobj
as expected, producing an unbound slot for BDAY
.
but stmnt2
fails with bad syntax and i don't know why.
i have also tried stmnt2 = "vobj.%s.value = ['%s']" %
(k,v)
, making the value a list, because of the two
alternatives on the VObject README:
j.email.value = 'jeffrey@osafoundation.org'
...
j.org.value = ['Open Source Applications Foundation']
does it matter whether a string atom or list is used?
I tried to simplify your code, and ended up with:
import vobject
s = 'BEGIN:VCARD\r\nFN:John Smith\r\nN:Smith;John;;;\r\nEND:VCARD'
vobj = vobject.readOne(s)
vobj.add('bday')
vobj.prettyPrint()
vobj.bday.value = '1931-02-10'
vobj.prettyPrint()
which produced:
> python test.py
VCARD
FN: John Smith
N: John Smith
BDAY:
VCARD
FN: John Smith
N: John Smith
BDAY: 1931-02-10
>
which seems to be what was expected.
Question 1 There's not generally a need for arbitrary names in vObjects, because the specifications dictate what values are required, and they're all handled by the vobject code.
A common pattern when adding a value is to save a reference to the added attribute, and access it directly, like:
notes = vobj.add("NOTES")
notes.value = "The content of my notes"
or, just do it inline:
vobj.add("NOTES").value = "Notes in one line"
Or you can access it directly:
vobj.notes.value = "New notes content"
Question 2
The problem here is nothing to do with vobject, but rather with Python. In Python, eval
only works for expressions. To dynamically compile and execute a statement (like your stmnt2
), you need to use exec
.
If you change
eval(stmnt2)
to
exec(stmnt2)
your example code sets the BDAY property without an exception.
See What's the difference between eval, exec, and compile? for a full explanation.
Question 3 Yes, it matters. The type of values of the various attributes of a vObject are determined by the specifications. Some have a single value, others are (optionally) a set of values. vobject doesn't enforce this, currently.