# khard.contacts

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

For further details about the application and device values for the kind field see: - application: https://tools.ietf.org/html/rfc6473 - device: https://tools.ietf.org/html/rfc6869

## Attributes

`logger` |
`T` |
`LabeledStrs` |

## Classes

`VCardWrapper` | Wrapper class around a vobject.vCard object.
`YAMLEditable` | Conversion of vcards to YAML and updating the vcard from YAML
`Contact` | Conversion of vcards to YAML and updating the vcard from YAML

## Functions

`multi_property_key`(…) | Key function to pass to sorted(), allowing sorting of dicts with lists
`atomic_write`(→ Iterator[IO[str]]) | Atomically write to the destination file.

## Module Contents

khard.contacts.logger

khard.contacts.T

khard.contacts.LabeledStrs

khard.contacts.multi_property_key(item: str) → tuple[Literal[0], str]
khard.contacts.multi_property_key(item: dict[T, Any]) → tuple[Literal[1], T]
khard.contacts.multi_property_key(item: str | dict[T, Any]) → tuple[Literal[0, 1], T | str]

  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 pair, the first item is int(isinstance(item, dict). The second is either the key from the dict or the unchanged item if it is not a dict.

class khard.contacts.VCardWrapper(vcard: vobject.base.Component, version: str | None = 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')
  _default_kind = 'individual'
  _supported_kinds = ('individual', 'group', 'org', 'location', 'application', 'device')
  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')
  vcard
  __str__() → str
  get_first(property: Literal['n']) → vobject.vcard.Name | None
  get_first(property: Literal['adr']) → vobject.vcard.Address | None
  get_first(property: str) → str | None

    Get a property from the underlying vCard.

    This method should only be called for properties with cardinality *1 (zero or one). Otherwise only the first value will be returned. If the property is not present None will be retuned.

    The type annotation for the return value is str but this is not enforced so it is up to the caller to make sure to only call this method for properties where the underlying vobject library returns a str.

    Parameters:

      property – the field value to get

    Returns:

      the property value or None

  get_all(name: str) → list

    Get all values of the given vCard property.

    It does not matter what the individual vcard properties store as their value. This function returns them untouched inside an aggregating 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 occurrences of the named property

  _delete_vcard_object(name: str) → None

    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: Sequence[str], supported_types: Sequence[str]) → tuple[list[str], list[str], int]

    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(object: vobject.base.ContentLine, default_type: str) → list[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: str | None
  property uid: str | None
  _update_revision() → None

    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.

  property birthday: khard.helpers.typing.Date | None

    Return the birthday as a datetime object or a string depending on whether 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: khard.helpers.typing.Date | None
    Returns:

      contacts anniversary or None if not available

  _get_ablabel(item: vobject.base.ContentLine) → str

    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(group_type: str = '') → 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_property(property: str, value: khard.helpers.typing.StrList, label: str | None = None, name_groups: bool = False, allowed_object_type: None | type[str] | type[list] = str) → None

    Add an object to the VCARD. If a label is given it will be added to a group with an ABLABEL.

    Parameters:

      - property – type of object to add to the VCARD.

      - value – Contents of the object to add.

      - label – an optional label to add to the property

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

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

  _prepare_birthday_value(date: khard.helpers.typing.Date) → tuple[str | None, bool]

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

    Parameters:

      date – the date like value to be stored

    Returns:

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

  property kind: str
  _kind_attribute_name() → str
  property formatted_name: str
  _get_names_part(part: str) → list[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() → list[str]
  _get_first_names() → list[str]
  _get_additional_names() → list[str]
  _get_last_names() → list[str]
  _get_name_suffixes() → list[str]
  get_first_name_last_name() → str

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

  get_last_name_first_name() → str

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

  property first_name: str | None
  property last_name: str | None
  _add_name(prefix: khard.helpers.typing.StrList, first_name: khard.helpers.typing.StrList, additional_name: khard.helpers.typing.StrList, last_name: khard.helpers.typing.StrList, suffix: khard.helpers.typing.StrList) → None

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

    Parameters:

      - prefix

      - first_name

      - additional_name

      - last_name

      - suffix

  property organisations: list[list[str] | dict[str, list[str]]]
    Returns:

      list of organisations, sorted alphabetically

  _add_organisation(organisation: khard.helpers.typing.StrList, label: str | None = None) → None

    Add one ORG entry to the underlying vcard

    Parameters:

      - organisation – the value to add

      - label – an optional label to add

  property titles: LabeledStrs
  _add_title(title: str, label: str | None = None) → None
  property roles: LabeledStrs
  _add_role(role: str, label: str | None = None) → None
  property nicknames: LabeledStrs
  _add_nickname(nickname: str, label: str | None = None) → None
  property notes: LabeledStrs
  _add_note(note: str, label: str | None = None) → None
  property webpages: LabeledStrs
  _add_webpage(webpage: str, label: str | None = None) → None
  property categories: list[str] | list[list[str]]
  _add_category(categories: list[str]) → None

    Add categories to the vCard

    Parameters:

      categories

  property phone_numbers: dict[str, list[str]]
    Returns:

      dict of type and phone number list

  _add_phone_number(type: str, number: str) → None
  property emails: dict[str, list[str]]
    Returns:

      dict of type and email address list

  add_email(type: str, address: str) → None
  property post_addresses: dict[str, list[khard.helpers.typing.PostAddress]]
    Returns:

      dict of type and post address list

  get_formatted_post_addresses() → dict[str, list[str]]
  _add_post_address(type: str, box: khard.helpers.typing.StrList, extended: khard.helpers.typing.StrList, street: khard.helpers.typing.StrList, code: khard.helpers.typing.StrList, city: khard.helpers.typing.StrList, region: khard.helpers.typing.StrList, country: khard.helpers.typing.StrList) → None

class khard.contacts.YAMLEditable(vcard: vobject.base.Component, supported_private_objects: list[str] | None = None, version: str | None = None, localize_dates: bool = False)

  Bases: `VCardWrapper`

  Conversion of vcards to YAML and updating the vcard from YAML

  supported_private_objects = []
  localize_dates = False
  _get_private_objects() → dict[str, LabeledStrs]
  _add_private_object(key: str, value: str) → None
  get_formatted_anniversary() → str
  get_formatted_birthday() → str
  static _format_date_object(date: khard.helpers.typing.Date | None, localize: bool) → str
  static _filter_invalid_tags(contents: str) → str
  static _parse_yaml(input: str) → dict

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

    Parameters:

      input – the YAML document to parse

    Returns:

      the parsed data structure

  static _set_string_list(setter: Callable[[str, str | None], None], key: str, data: dict[str, str | list[str]]) → None

    Pre-process 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(target: str, key: str, data: dict) → None
  update(input: str) → None

    Update this vcard with some yaml input

    Parameters:

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

  to_yaml() → str

    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

khard.contacts.atomic_write(dest: str, overwrite: bool = False) → Iterator[IO[str]]

  Atomically write to the destination file.

  Optionally overwrite the path (using rename) rather than using os.link.

class khard.contacts.Contact(vcard: vobject.base.Component, address_book: Contact.__init__.address_book, filename: str, supported_private_objects: list[str] | None = None, vcard_version: str | None = None, localize_dates: bool = False)

  Bases: `YAMLEditable`

  Conversion of vcards to YAML and updating the vcard from YAML

  address_book
  filename
  classmethod new(address_book: Contact.new.address_book, supported_private_objects: list[str] | None = None, version: str | None = None, localize_dates: bool = False) → Contact

    Create a new Contact from scratch

  classmethod from_file(address_book: Contact.from_file.address_book, filename: str, query: khard.query.Query = AnyQuery(), supported_private_objects: list[str] | None = None, localize_dates: bool = False) → Contact | None

    Load a Contact 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 object

      - localize_dates – should the formatted output of anniversary and birthday be localized or should the iso format be used instead

    Returns:

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

  classmethod from_yaml(address_book: Contact.from_yaml.address_book, yaml: str, supported_private_objects: list[str] | None = None, version: str | None = None, localize_dates: bool = False) → Contact

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

  classmethod clone_with_yaml_update(contact: Contact, yaml: str, localize_dates: bool = False) → Contact

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

  __eq__(other: object) → bool
  __ne__(other: object) → bool
  pretty(verbose: bool = True) → str
  write_to_file(overwrite: bool = False) → None
  delete_vcard_file() → None
  classmethod get_properties() → list[str]

    Return the property names that are defined on this class.