khard.carddav_object

Classes and logic to handle vCards in khard.

This module explicitly supports the vCard specifications version 3.0 and 4.0 which can be found here: - version 3.0: https://tools.ietf.org/html/rfc2426 - version 4.0: https://tools.ietf.org/html/rfc6350

Module Contents

khard.carddav_object.logger
khard.carddav_object.Query
khard.carddav_object.convert_to_vcard(name: str, value: Union[str, List[str]], allowed_object_type: ObjectType) → Union[str, List[str]]

converts user input into vcard compatible data structures

Parameters
  • name – object name, only required for error messages

  • value – user input

  • allowed_object_type – set the accepted return type for vcard attribute

Returns

cleaned user input, ready for vcard or a ValueError

khard.carddav_object.multi_property_key(item: Union[str, Dict]) → List

key function to pass to sorted(), allowing sorting of dicts with lists and strings. Dicts will be sorted by their label, after other types.

Parameters

item (a dict with a single entry or any sortable type) – member of the list being sorted

Returns

a list with two members. The first is int(isinstance(item, dict). The second is either the key from the dict or the unchanged item if it is not a dict.

Return type

list(int, type(item)) or list(int, str)

class khard.carddav_object.VCardWrapper(vcard: vobject.vCard, version: Optional[str] = None)

Wrapper class around a vobject.vCard object.

This class can wrap a single vCard and presents its data in a manner suitable for khard. Additionally some details of the vCard specifications in RFC 2426 (version 3.0) and RFC 6350 (version 4.0) that are not enforced by the vobject library are enforced here.

_default_version = 3.0
_supported_versions = ['3.0', '4.0']
phone_types_v3 = ['bbs', 'car', 'cell', 'fax', 'home', 'isdn', 'msg', 'modem', 'pager', 'pcs', 'video', 'voice', 'work']
email_types_v3 = ['home', 'internet', 'work', 'x400']
address_types_v3 = ['dom', 'intl', 'home', 'parcel', 'postal', 'work']
phone_types_v4 = ['text', 'voice', 'fax', 'cell', 'video', 'pager', 'textphone', 'home', 'work']
email_types_v4 = ['home', 'internet', 'work']
address_types_v4 = ['home', 'work']
__str__(self)
_get_string_field(self, field: str)

Get a string field from the underlying vCard.

Parameters

field – the field value to get

Returns

the field value or the empty string

_get_multi_property(self, name: str)

Get a vCard property that can exist more than once.

It does not matter what the individual vcard properties store as their value. This function returnes them untouched inside an agregating list.

If the property is part of a group containing exactly two items, with exactly one ABLABEL. the property will be prefixed with that ABLABEL.

Parameters

name – the name of the property (should be UPPER case)

Returns

the values from all occurences of the named property

_delete_vcard_object(self, name: str)

Delete all fields with the given name from the underlying vCard.

If a field that will be deleted is in a group with an X-ABLABEL field, that X-ABLABEL field will also be deleted. These fields are commonly added by the Apple address book to attach custom labels to some fields.

Parameters

name – the name of the fields to delete

static _parse_type_value(types: List[str], supported_types: List[str])

Parse type value of phone numbers, email and post addresses.

Parameters
  • types – list of type values

  • supported_types – all allowed standard types

Returns

tuple of standard and custom types and pref integer

_get_types_for_vcard_object(self, object: vobject.base.ContentLine, default_type: str)

get list of types for phone number, email or post address

Parameters
  • object – vcard class object

  • default_type – use if the object contains no type

Returns

list of type labels

property version(self)
property uid(self)
_update_revision(self)

Generate a new REV field for the vCard, replace any existing

All vCards should only always have one revision, this is a requirement for version 4 but also makes sense for all other versions.

Return type

NoneType

property birthday(self)

Return the birthday as a datetime object or a string depending on weather it is of type text or not. If no birthday is present in the vcard None is returned.

Returns

contacts birthday or None if not available

property anniversary(self)
Returns

contacts anniversary or None if not available

_get_ablabel(self, item: vobject.base.ContentLine)

Get an ABLABEL for a specified item in the vCard. Will return the ABLABEL only if the item is part of a group with exactly two items, exactly one of which is an ABLABEL.

Parameters

item – the item to be labelled

Returns

the ABLABEL in the circumstances above or an empty string

_get_new_group(self, group_type: str = '')
Get an unused group name for adding new groups. Uses the form item123

or itemgroup_type123 if a grouptype is specified.

Parameters

group_type – (Optional) a string to add between “item” and the number

Returns

the name of the first unused group of the specified form

_add_labelled_object(self, obj_type: str, user_input, name_groups: bool = False, allowed_object_type: ObjectType = ObjectType.string)
Add an object to the VCARD. If user_input is a dict, the object will

be added to a group with an ABLABEL created from the key of the dict.

Parameters
  • obj_type – type of object to add to the VCARD.

  • user_input (str or list(str) or dict(str) or dict(list(str))) – Contents of the object to add. If a dict

  • name_groups – (Optional) If True, use the obj_type in the group name for labelled objects.

  • allowed_object_type – (Optional) set the accepted return type for vcard attribute

_prepare_birthday_value(self, date: Union[str, datetime.datetime])

Prepare a value to be stored in a BDAY or ANNIVERSARY attribute.

Parameters

date (datetime.datetime or str) – the date like value to be stored

Returns

the object to set as the .value for the attribute and weather it should be stored as plain text

Return type

tuple(str,bool)

property formatted_name(self)
_get_names_part(self, part: str)

Get some part of the “N” entry in the vCard as a list

Parameters

part – the name to get e.g. “prefix” or “given”

Returns

a list of entries for this name part

_get_name_prefixes(self)
_get_first_names(self)
_get_additional_names(self)
_get_last_names(self)
_get_name_suffixes(self)
get_first_name_last_name(self)

Compute the full name of the contact by joining first, additional and last names together

get_last_name_first_name(self)

Compute the full name of the contact by joining the last names and then after a comma the first and additional names together

_add_name(self, prefix: Union[str, List[str]], first_name: Union[str, List[str]], additional_name: Union[str, List[str]], last_name: Union[str, List[str]], suffix: Union[str, List[str]])

Add an N entry to the vCard. No old entries are affected.

Parameters
  • prefix

  • first_name

  • additional_name

  • last_name

  • suffix

property organisations(self)
Returns

list of organisations, sorted alphabetically

_add_organisation(self, organisation: Union[str, List[str]])

Add one ORG entry to the underlying vcard

Parameters

organisation – the value to add

property titles(self)
_add_title(self, title)
property roles(self)
_add_role(self, role)
property nicknames(self)
_add_nickname(self, nickname)
property notes(self)
_add_note(self, note)
property webpages(self)
_add_webpage(self, webpage)
property categories(self)
_add_category(self, categories: List[str])

Add categories to the vCard

Parameters

categories

property phone_numbers(self)
Returns

dict of type and phone number list

_add_phone_number(self, type, number)
property emails(self)
Returns

dict of type and email address list

add_email(self, type, address)
property post_addresses(self)
Returns

dict of type and post address list

get_formatted_post_addresses(self)
_add_post_address(self, type, box, extended, street, code, city, region, country)
class khard.carddav_object.YAMLEditable(vcard: vobject.vCard, supported_private_objects: Optional[List[str]] = None, version: Optional[str] = None, localize_dates: bool = False)

Bases: khard.carddav_object.VCardWrapper

Conversion of vcards to YAML and updateing the vcard from YAML

_get_private_objects(self)
_add_private_object(self, key: str, value)
get_formatted_anniversary(self)
get_formatted_birthday(self)
static _format_date_object(date: Union[None, str, datetime.datetime], localize: bool)
static _filter_invalid_tags(contents: str)
static _parse_yaml(input: str)

Parse a YAML document into a dictinary and validate the data to some degree.

Parameters

input (str) – the YAML document to parse

Returns

the parsed datastructure

Return type

dict

static _set_string_list(setter: Callable[[Union[str, List]], None], key: str, data: Dict)

Prepocess a string or list and set each value with the given setter

Parameters
  • setter – the setter method to add a value to a card

  • key

  • data

_set_date(self, target: str, key: str, data: Dict)
update(self, input: str)

Update this vcard with some yaml input

Parameters

input – a yaml string to parse and then use to update self

to_yaml(self)

Convert this contact to a YAML string

The conversion follows the implicit schema that is given by the internal YAML template of khard.

Returns

a YAML representation of this contact

class khard.carddav_object.CarddavObject(vcard: vobject.vCard, address_book: address_book.VdirAddressBook, filename: str, supported_private_objects: Optional[List[str]] = None, vcard_version: Optional[str] = None, localize_dates: bool = False)

Bases: khard.carddav_object.YAMLEditable

classmethod new(cls, address_book: address_book.VdirAddressBook, supported_private_objects: Optional[List[str]] = None, version: Optional[str] = None, localize_dates: bool = False)

Create a new CarddavObject from scratch

classmethod from_file(cls, address_book: address_book.VdirAddressBook, filename: str, query: Query, supported_private_objects: Optional[List[str]] = None, localize_dates: bool = False)

Load a CarddavObject object from a .vcf file if the plain file matches the query.

Parameters
  • address_book – the address book where this contact is stored

  • filename – the file name of the .vcf file

  • query – the query to search in the source file or None to load the file unconditionally

  • supported_private_objects – the list of private property names that will be loaded from the actual vcard and represented in this pobject

  • localize_dates – should the formatted output of anniversary and birthday be localized or should the isoformat be used instead

Returns

the loaded CarddavObject or None if the file didn’t match

classmethod from_yaml(cls, address_book: address_book.VdirAddressBook, yaml: str, supported_private_objects: Optional[List[str]] = None, version: Optional[str] = None, localize_dates: bool = False)

Use this if you want to create a new contact from user input.

classmethod clone_with_yaml_update(cls, contact: CarddavObject, yaml: str, localize_dates: bool = False)

Use this if you want to clone an existing contact and replace its data with new user input in one step.

static match(string: str, query: Query)

Check if the given string matches against the query. The query is a list of lists of strings. The inner lists are AND joined and the outer lists are OR joined.

Parameters
  • string – the string which to check

  • query

__eq__(self, other: object)
__ne__(self, other: object)
print_vcard(self, show_address_book: bool = True, show_uid: bool = True)
write_to_file(self, overwrite: bool = False)
delete_vcard_file(self)