Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-khard for openSUSE:Factory checked in at 2026-10-05 12:56:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-khard (Old) and /work/SRC/openSUSE:Factory/.python-khard.new.3698736 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-khard" Mon Oct 5 12:56:48 2026 rev:6 rq:1382329 version:0.22.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-khard/python-khard.changes 2026-06-28 21:07:55.384882215 +0200 +++ /work/SRC/openSUSE:Factory/.python-khard.new.3698736/python-khard.changes 2026-10-05 12:57:52.728405175 +0200 @@ -1,0 +2,9 @@ +Sun Oct 4 14:43:24 UTC 2026 - Dirk Müller <[email protected]> + +- update to 0.22.0: + * Support vcard IMPP field (#359) + * Fix YAML output for single organisation (#358) + * Require setuptools >= 77 (60be3cb) + * deps: remove dependency on sphinx_autodoc_typehints extension + +------------------------------------------------------------------- Old: ---- khard-0.21.0.tar.gz New: ---- khard-0.22.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-khard.spec ++++++ --- /var/tmp/diff_new_pack.p9Aj8c/_old 2026-10-05 12:57:53.527438691 +0200 +++ /var/tmp/diff_new_pack.p9Aj8c/_new 2026-10-05 12:57:53.530438817 +0200 @@ -18,7 +18,7 @@ %{?sle15_python_module_pythons} Name: python-khard -Version: 0.21.0 +Version: 0.22.0 Release: 0 Summary: Console carddav client License: GPL-3.0-only ++++++ khard-0.21.0.tar.gz -> khard-0.22.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/CHANGES new/khard-0.22.0/CHANGES --- old/khard-0.21.0/CHANGES 2026-06-15 15:39:35.000000000 +0200 +++ new/khard-0.22.0/CHANGES 2026-10-02 09:11:55.000000000 +0200 @@ -1,6 +1,14 @@ Change Log ========== +v0.22.0 2026-10-02 + +- Support vcard IMPP field (#359) +- Fix YAML output for single organisation (#358) +- Require setuptools >= 77 (60be3cb) +- deps: remove dependency on sphinx_autodoc_typehints extension (#356) + + v0.21.0 2026-06-15 - Remove support for python 3.9 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/PKG-INFO new/khard-0.22.0/PKG-INFO --- old/khard-0.21.0/PKG-INFO 2026-06-15 15:42:00.077532300 +0200 +++ new/khard-0.22.0/PKG-INFO 2026-10-02 09:15:32.092392000 +0200 @@ -1,9 +1,9 @@ Metadata-Version: 2.4 Name: khard -Version: 0.21.0 +Version: 0.22.0 Summary: A console address book manager Author-email: Eric Scheibler <[email protected]> -License: GPL +License-Expression: GPL-3.0-only Project-URL: homepage, https://github.com/lucc/khard Project-URL: documentation, https://khard.readthedocs.io/en/latest/ Project-URL: repository, https://github.com/lucc/khard.git @@ -13,7 +13,6 @@ Classifier: Environment :: Console Classifier: Topic :: Utilities Classifier: Topic :: Communications :: Email :: Address Book -Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Intended Audience :: End Users/Desktop Classifier: Operating System :: POSIX Classifier: Programming Language :: Python :: 3 :: Only @@ -27,7 +26,6 @@ Requires-Dist: sphinx; extra == "doc" Requires-Dist: sphinx-argparse; extra == "doc" Requires-Dist: sphinx-autoapi; extra == "doc" -Requires-Dist: sphinx-autodoc-typehints; extra == "doc" Provides-Extra: typing Requires-Dist: mypy; extra == "typing" Dynamic: license-file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard/cli.py new/khard-0.22.0/khard/cli.py --- old/khard-0.21.0/khard/cli.py 2026-06-15 15:13:21.000000000 +0200 +++ new/khard-0.22.0/khard/cli.py 2026-10-02 08:54:01.000000000 +0200 @@ -457,6 +457,6 @@ sys.exit(str(err)) -def _sphinxarg_helper(): +def _sphinxarg_helper() -> argparse.ArgumentParser: """Helper function to return the correct argument parser for the docs.""" return create_parsers()[1] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard/contacts.py new/khard-0.22.0/khard/contacts.py --- old/khard-0.21.0/khard/contacts.py 2026-06-15 15:13:34.000000000 +0200 +++ new/khard-0.22.0/khard/contacts.py 2026-10-02 08:54:01.000000000 +0200 @@ -807,6 +807,47 @@ label_obj.value = custom_types[0] @property + def impp(self) -> dict[str, list[str]]: + """ + :returns: dict of type and instant message handle list + """ + impp_dict: dict[str, list[str]] = {} + try: + impp = self.vcard.impp_list + except AttributeError: + return {} + for child in impp: + try: + type, value = child.value.split(":", maxsplit=1) + except ValueError: + continue + try: + pref = int(child.params.get("PREF")[0]) + type += f", pref={pref}" + except (IndexError, TypeError, ValueError): + pass + if type not in impp_dict: + impp_dict[type] = [] + impp_dict[type].append(value) + # sort impp handles lists + for impp_list in impp_dict.values(): + impp_list.sort() + return impp_dict + + def _add_impp(self, type: str, handle: str) -> None: + _, types, pref = self._parse_type_value(string_to_list(type, ","), []) + if not types: + raise ValueError(f"Type for impp handle {handle} is missing.") + for type in types: + if ":" in type: + raise ValueError(f"Impp type \"{type}\" must not contain a colon.") + impp_obj = self.vcard.add('impp') + handle = convert_to_vcard("impp handle", handle, str) + impp_obj.value = f"{type}:{handle}" + if pref > 0: + impp_obj.params['PREF'] = str(pref) + + @property def post_addresses(self) -> dict[str, list[PostAddress]]: """ :returns: dict of type and post address list @@ -1176,6 +1217,25 @@ else: raise ValueError("Missing type value for email address field") + # impp + self._delete_vcard_object("IMPP") + impp_data = contact_data.get("Impp") + if impp_data: + if isinstance(impp_data, dict): + for type, impp_list in impp_data.items(): + if isinstance(impp_list, str): + impp_list = [impp_list] + if isinstance(impp_list, list): + for impp in impp_list: + if impp: + self._add_impp(type, impp) + else: + raise ValueError( + "Got no impp or list of impps for the " + f"impp address type {type}") + else: + raise ValueError("Missing type value for impp handle field") + # post addresses self._delete_vcard_object("ADR") address_data = contact_data.get("Address") @@ -1308,6 +1368,8 @@ self.phone_numbers, defaults=["cell", "home"]), "Email": helpers.yaml_dicts( self.emails, defaults=["home", "work"]), + "Impp": helpers.yaml_dicts( + self.impp, defaults=["xmpp", "irc"]), "Categories": self.categories, "Note": self.notes, "Webpage": self.webpages, @@ -1550,6 +1612,14 @@ strings += helpers.convert_to_yaml( type, email_list, 4, -1, False) + # impp addresses + if self.impp: + strings.append("IMPP") + for type, impp_list in sorted(self.impp.items(), + key=lambda k: k[0].lower()): + strings += helpers.convert_to_yaml( + type, impp_list, 4, -1, False) + # post addresses if self.post_addresses: strings.append("Address") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard/data/template.yaml new/khard-0.22.0/khard/data/template.yaml --- old/khard-0.21.0/khard/data/template.yaml 2025-01-03 10:45:04.000000000 +0100 +++ new/khard-0.22.0/khard/data/template.yaml 2026-10-02 08:54:01.000000000 +0200 @@ -86,6 +86,12 @@ home : work : +# impp handles +# format like phone numbers above +Impp : + xmpp : + irc : + # post addresses # allowed types: # vcard 3.0: At least one of dom, intl, home, parcel, postal, pref, work diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard/formatter.py new/khard-0.22.0/khard/formatter.py --- old/khard-0.21.0/khard/formatter.py 2026-02-04 09:01:43.000000000 +0100 +++ new/khard-0.22.0/khard/formatter.py 2026-10-02 09:01:58.000000000 +0200 @@ -69,6 +69,9 @@ if vcard.emails: return self.format_labeled_field(vcard.emails, self._preferred_email) + if field == 'impp': + if vcard.impp: + return self.format_labeled_field(vcard.impp, []) if field == 'kind': return vcard.kind return "" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard/helpers/__init__.py new/khard-0.22.0/khard/helpers/__init__.py --- old/khard-0.21.0/khard/helpers/__init__.py 2026-06-15 15:13:34.000000000 +0200 +++ new/khard-0.22.0/khard/helpers/__init__.py 2026-10-02 08:54:01.000000000 +0200 @@ -71,7 +71,7 @@ """ sanitize yaml values according to some simple principles: 1. empty values are none, so ruamel does not print an empty list/str - 2. list with only one item become this item + 2. simple single-item lists are flattened 3. multiline strings use the YAML literal style: https://yaml.org/spec/1.2.2/#literal-style @@ -83,9 +83,19 @@ return None if isinstance(value, list): - # special case for single item lists: + # Flatten a single string value, e.g. ["foo"] -> "foo" if len(value) == 1 and isinstance(value[0], str): return value[0] + + # Flatten a nested single string value, e.g. [["foo"]] -> "foo" + if ( + len(value) == 1 + and isinstance(value[0], list) + and len(value[0]) == 1 + and isinstance(value[0][0], str) + ): + return value[0][0] + elif isinstance(value, str): if "\n" in value: return LiteralScalarString(value) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard/khard.py new/khard-0.22.0/khard/khard.py --- old/khard-0.21.0/khard/khard.py 2026-06-15 15:13:21.000000000 +0200 +++ new/khard-0.22.0/khard/khard.py 2026-10-02 08:54:01.000000000 +0200 @@ -11,7 +11,7 @@ import os import sys import textwrap -from typing import cast, Callable, Iterable +from typing import Any, cast, Callable, Iterable from . import helpers from .address_book import AddressBookCollection, VdirAddressBook @@ -205,7 +205,7 @@ for field in table_header: if field == 'index': row.append(str(index + 1)) - elif field in ['name', 'phone', 'email', 'kind']: + elif field in ['name', 'phone', 'email', 'kind', 'impp']: row.append(formatter.get_special_field(vcard, field)) elif field == 'uid': if parsable: @@ -656,15 +656,14 @@ """ message = message_from_string(text, policy=SMTP_POLICY) - def extract_addresses(header) -> list[Address]: + def extract_addresses(header: Any) -> list[Address]: if header and isinstance(header, (AddressHeader, Group)): return list(header.addresses) return [] email_addresses = [] - _all = any([f == "all" for f in fields]) - if _all: + if "all" in fields: for _, value in message.items(): email_addresses.extend(extract_addresses(value)) else: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard/version.py new/khard-0.22.0/khard/version.py --- old/khard-0.21.0/khard/version.py 2026-06-15 15:41:59.000000000 +0200 +++ new/khard-0.22.0/khard/version.py 2026-10-02 09:15:31.000000000 +0200 @@ -28,7 +28,7 @@ commit_id: COMMIT_ID __commit_id__: COMMIT_ID -__version__ = version = '0.21.0' -__version_tuple__ = version_tuple = (0, 21, 0) +__version__ = version = '0.22.0' +__version_tuple__ = version_tuple = (0, 22, 0) -__commit_id__ = commit_id = 'gfc30a66ca' +__commit_id__ = commit_id = 'ga644aa0f4' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard.egg-info/PKG-INFO new/khard-0.22.0/khard.egg-info/PKG-INFO --- old/khard-0.21.0/khard.egg-info/PKG-INFO 2026-06-15 15:41:59.000000000 +0200 +++ new/khard-0.22.0/khard.egg-info/PKG-INFO 2026-10-02 09:15:31.000000000 +0200 @@ -1,9 +1,9 @@ Metadata-Version: 2.4 Name: khard -Version: 0.21.0 +Version: 0.22.0 Summary: A console address book manager Author-email: Eric Scheibler <[email protected]> -License: GPL +License-Expression: GPL-3.0-only Project-URL: homepage, https://github.com/lucc/khard Project-URL: documentation, https://khard.readthedocs.io/en/latest/ Project-URL: repository, https://github.com/lucc/khard.git @@ -13,7 +13,6 @@ Classifier: Environment :: Console Classifier: Topic :: Utilities Classifier: Topic :: Communications :: Email :: Address Book -Classifier: License :: OSI Approved :: GNU General Public License (GPL) Classifier: Intended Audience :: End Users/Desktop Classifier: Operating System :: POSIX Classifier: Programming Language :: Python :: 3 :: Only @@ -27,7 +26,6 @@ Requires-Dist: sphinx; extra == "doc" Requires-Dist: sphinx-argparse; extra == "doc" Requires-Dist: sphinx-autoapi; extra == "doc" -Requires-Dist: sphinx-autodoc-typehints; extra == "doc" Provides-Extra: typing Requires-Dist: mypy; extra == "typing" Dynamic: license-file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard.egg-info/SOURCES.txt new/khard-0.22.0/khard.egg-info/SOURCES.txt --- old/khard-0.21.0/khard.egg-info/SOURCES.txt 2026-06-15 15:41:59.000000000 +0200 +++ new/khard-0.22.0/khard.egg-info/SOURCES.txt 2026-10-02 09:15:31.000000000 +0200 @@ -41,6 +41,8 @@ khard.egg-info/dependency_links.txt khard.egg-info/entry_points.txt khard.egg-info/requires.txt +khard.egg-info/scm_file_list.json +khard.egg-info/scm_version.json khard.egg-info/top_level.txt khard/data/config.spec khard/data/template.yaml diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard.egg-info/requires.txt new/khard-0.22.0/khard.egg-info/requires.txt --- old/khard-0.21.0/khard.egg-info/requires.txt 2026-06-15 15:41:59.000000000 +0200 +++ new/khard-0.22.0/khard.egg-info/requires.txt 2026-10-02 09:15:31.000000000 +0200 @@ -6,7 +6,6 @@ sphinx sphinx-argparse sphinx-autoapi -sphinx-autodoc-typehints [typing] mypy diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard.egg-info/scm_file_list.json new/khard-0.22.0/khard.egg-info/scm_file_list.json --- old/khard-0.21.0/khard.egg-info/scm_file_list.json 1970-01-01 01:00:00.000000000 +0100 +++ new/khard-0.22.0/khard.egg-info/scm_file_list.json 2026-08-17 22:30:38.000000000 +0200 @@ -0,0 +1,106 @@ +{ + "files": [ + ".github/workflows/ci.yml", + ".gitignore", + ".readthedocs.yml", + "CHANGES", + "CONTRIBUTING.rst", + "LICENSE", + "README.md", + "doc/Makefile", + "doc/source/bench.rst", + "doc/source/commandline.rst", + "doc/source/conf.py", + "doc/source/contributing.rst", + "doc/source/davcontroller.rst", + "doc/source/examples/khard.conf.example", + "doc/source/index.rst", + "doc/source/indices.rst", + "doc/source/man.rst", + "doc/source/man/khard-subcommands.rst", + "doc/source/man/khard.conf.rst", + "doc/source/man/khard.rst", + "doc/source/scripting.rst", + "flake.lock", + "flake.nix", + "khard/__init__.py", + "khard/__main__.py", + "khard/actions.py", + "khard/address_book.py", + "khard/cli.py", + "khard/config.py", + "khard/contacts.py", + "khard/data/config.spec", + "khard/data/template.yaml", + "khard/exceptions.py", + "khard/formatter.py", + "khard/helpers/__init__.py", + "khard/helpers/interactive.py", + "khard/helpers/typing.py", + "khard/khard.py", + "khard/query.py", + "misc/davcontroller/davcontroller.py", + "misc/sdiff/sdiff_khard_wrapper.sh", + "misc/twinkle/scripts/config.py", + "misc/twinkle/scripts/incoming_call.py", + "misc/twinkle/scripts/incoming_call_ended.py", + "misc/twinkle/scripts/incoming_call_failed.py", + "misc/twinkle/sounds/incoming_call.ogg", + "misc/twinkle/sounds/outgoing_call.ogg", + "misc/twinkle/sounds/ringtone_segment.ogg", + "misc/zsh/_email-khard", + "misc/zsh/_khard", + "pyproject.toml", + "test/__init__.py", + "test/fixture/broken.abook/unparsable.vcf", + "test/fixture/discover.conf", + "test/fixture/minimal.abook/minimal.vcf", + "test/fixture/minimal.conf", + "test/fixture/multiple_values.yaml", + "test/fixture/nick.abook/joe.vcf", + "test/fixture/nick.abook/nickname.vcf", + "test/fixture/nick.conf", + "test/fixture/single_values.yaml", + "test/fixture/test.abook/contact1.vcf", + "test/fixture/test.abook/contact2.vcf", + "test/fixture/test.abook/text-bday.vcf", + "test/fixture/vcards/altid.vcf", + "test/fixture/vcards/category.vcf", + "test/fixture/vcards/contact1.vcf", + "test/fixture/vcards/contact2.vcf", + "test/fixture/vcards/individual.vcf", + "test/fixture/vcards/issue249.vcf", + "test/fixture/vcards/joe.vcf", + "test/fixture/vcards/korean-c.vcf", + "test/fixture/vcards/korean-j.vcf", + "test/fixture/vcards/labels.vcf", + "test/fixture/vcards/minimal.vcf", + "test/fixture/vcards/nickname.vcf", + "test/fixture/vcards/no-nickname.vcf", + "test/fixture/vcards/org.vcf", + "test/fixture/vcards/photov3.vcf", + "test/fixture/vcards/photov4.vcf", + "test/fixture/vcards/post.vcf", + "test/fixture/vcards/tel-value-uri.vcf", + "test/fixture/vcards/text-bday.vcf", + "test/fixture/vcards/unparsable.vcf", + "test/helpers.py", + "test/test_actions.py", + "test/test_address_book.py", + "test/test_cli.py", + "test/test_command_line_interface.py", + "test/test_config.py", + "test/test_contacts.py", + "test/test_editor.py", + "test/test_formatter.py", + "test/test_helpers.py", + "test/test_helpers_interactive.py", + "test/test_helpers_typing.py", + "test/test_khard.py", + "test/test_query.py", + "test/test_vcard_wrapper.py", + "test/test_yaml.py", + "test/test_yaml_editable.py", + "todo.txt" + ] +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/khard.egg-info/scm_version.json new/khard-0.22.0/khard.egg-info/scm_version.json --- old/khard-0.21.0/khard.egg-info/scm_version.json 1970-01-01 01:00:00.000000000 +0100 +++ new/khard-0.22.0/khard.egg-info/scm_version.json 2026-08-17 22:30:38.000000000 +0200 @@ -0,0 +1,8 @@ +{ + "tag": "0.21.0", + "distance": 4, + "node": "g214becc0ebee2dbbf21817602f8167cb356f7cd6", + "dirty": false, + "branch": "main", + "node_date": "2026-06-19" +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/pyproject.toml new/khard-0.22.0/pyproject.toml --- old/khard-0.21.0/pyproject.toml 2026-06-15 15:13:21.000000000 +0200 +++ new/khard-0.22.0/pyproject.toml 2026-10-02 08:54:01.000000000 +0200 @@ -13,14 +13,13 @@ "Environment :: Console", "Topic :: Utilities", "Topic :: Communications :: Email :: Address Book", - "License :: OSI Approved :: GNU General Public License (GPL)", "Intended Audience :: End Users/Desktop", "Operating System :: POSIX", "Programming Language :: Python :: 3 :: Only", ] keywords = ["vcard", "console", "addressbook"] -license = {text = "GPL"} +license = "GPL-3.0-only" dependencies = [ "configobj == 5.*, >= 5.0.6", @@ -33,7 +32,6 @@ 'sphinx', 'sphinx-argparse', 'sphinx-autoapi', - 'sphinx-autodoc-typehints', ] typing = [ "mypy", @@ -51,7 +49,7 @@ khard = "khard.khard:main" [build-system] -requires = ["setuptools>=61.0", "setuptools_scm[toml]>=6.2"] +requires = ["setuptools>=77.0", "setuptools_scm[toml]>=6.2"] build-backend = "setuptools.build_meta" [tool.setuptools] @@ -64,7 +62,7 @@ packages = ["khard", "test"] check_untyped_defs = true disallow_untyped_calls = true -#disallow_untyped_defs = true +disallow_untyped_defs = true warn_redundant_casts = true warn_unused_configs = true warn_unused_ignores = true @@ -91,6 +89,7 @@ module = "test.*" check_untyped_defs = false disallow_untyped_calls = false +disallow_untyped_defs = false [tool.pylint.main] py-version = "3.10" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/test/helpers.py new/khard-0.22.0/test/helpers.py --- old/khard-0.21.0/test/helpers.py 2025-05-03 09:04:23.000000000 +0200 +++ new/khard-0.22.0/test/helpers.py 2026-10-02 08:54:01.000000000 +0200 @@ -7,17 +7,19 @@ import os import shutil import tempfile -from typing import Generator +from collections.abc import Generator from unittest import SkipTest, mock import vobject -from khard import address_book -from khard import contacts +from khard import address_book, contacts -def vCard(**kwargs): - """Create a simple vobject.vCard for tests.""" +def vCard(**kwargs) -> vobject.base.Component: + """Create a simple vobject.vCard for tests. + + The default version is 3.0. + """ vcard = vobject.vCard() if 'fn' not in kwargs: kwargs['fn'] = 'Test vCard' @@ -28,19 +30,19 @@ return vcard -def TestVCardWrapper(**kwargs): +def TestVCardWrapper(**kwargs) -> contacts.VCardWrapper: """Create a simple VCardWrapper for tests.""" return contacts.VCardWrapper(vCard(**kwargs)) -def TestYAMLEditable(**kwargs): +def TestYAMLEditable(**kwargs) -> contacts.YAMLEditable: """Create a simple YAMLEditable for tests.""" return contacts.YAMLEditable(vCard(**kwargs)) -def TestContact(**kwargs): +def TestContact(**kwargs) -> contacts.Contact: """Create a simple Contact for tests.""" - return contacts.Contact(vCard(**kwargs), None, None) + return contacts.Contact(vCard(**kwargs), None, None) # type: ignore def mock_stream(name="stdout"): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/test/test_vcard_wrapper.py new/khard-0.22.0/test/test_vcard_wrapper.py --- old/khard-0.21.0/test/test_vcard_wrapper.py 2026-06-15 15:13:21.000000000 +0200 +++ new/khard-0.22.0/test/test_vcard_wrapper.py 2026-10-02 08:54:01.000000000 +0200 @@ -311,6 +311,29 @@ self.assertDictEqual(wrapper.emails, {'home': ['[email protected]'], 'home, pref': ['[email protected]']}) + def test_adding_a_simple_impp(self): + wrapper = TestVCardWrapper() + wrapper._add_impp('xmpp', '[email protected]') + self.assertDictEqual(wrapper.impp, {'xmpp': ['[email protected]']}) + + def test_adding_multiple_impp(self): + wrapper = TestVCardWrapper() + wrapper._add_impp('matrix', '@foo:example.com') + wrapper._add_impp('xmpp', '[email protected]') + wrapper._add_impp('xmpp', '[email protected]') + self.assertDictEqual( + wrapper.impp, + # The lists are sorted! + {'matrix': ['@foo:example.com'], 'xmpp': ['[email protected]', '[email protected]']}) + + def test_adding_preferred_impp(self): + wrapper = TestVCardWrapper() + wrapper._add_impp('xmpp', '[email protected]') + wrapper._add_impp('pref,xmpp', '[email protected]') + self.assertDictEqual( + wrapper.impp, {'xmpp': ['[email protected]'], + 'xmpp, pref=1': ['[email protected]']}) + def test_adding_a_simple_address(self): wrapper = TestVCardWrapper() components = ('box', 'extended', 'street', 'code', 'city', 'region', @@ -389,6 +412,24 @@ def test_list_of_strings_as_country(self): self._test_list_of_strings_as("country") + def test_pref_formatting_for_v3_vcards(self): + vcard = TestVCardWrapper(version="3.0") + vcard.add_email("pref", "[email protected]") + line = self._find_line("EMAIL", vcard.vcard.serialize()) + self.assertEqual(line, ["EMAIL;TYPE=pref:[email protected]"]) + + def test_pref_formatting_for_v4_vcards(self): + vcard = TestVCardWrapper(version="4.0") + vcard.add_email("pref", "[email protected]") + line = self._find_line("EMAIL", vcard.vcard.serialize()) + self.assertEqual(line, ["EMAIL;PREF=1:[email protected]"]) + + @staticmethod + def _find_line(pattern: str, lines: str | list[str]) -> list[str]: + if isinstance(lines, str): + lines = lines.splitlines() + return [line for line in lines if pattern in line] + class OtherProperties(unittest.TestCase): @@ -578,7 +619,7 @@ LIST_PROPERTIES = ["categories", "titles", "webpages", "organisations", "notes", "roles", "nicknames"] - DICT_PROPERTIES = ["post_addresses", "emails", "phone_numbers"] + DICT_PROPERTIES = ["post_addresses", "emails", "phone_numbers", "impp"] BASE_PROPERTIES = ["formatted_name", "kind", "version"] def test_for_non_existing_attributes(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/test/test_yaml.py new/khard-0.22.0/test/test_yaml.py --- old/khard-0.21.0/test/test_yaml.py 2025-01-03 10:45:05.000000000 +0100 +++ new/khard-0.22.0/test/test_yaml.py 2026-10-02 08:54:01.000000000 +0200 @@ -149,6 +149,14 @@ card.update(data) self.assertListEqual(card.organisations, [org]) + def test_org_simple_to_yaml(self): + card = create_test_card() + card._add_organisation("Foo") + + data = YAML().load(card.to_yaml()) + + self.assertEqual(data["Organisation"], "Foo") + def test_update_categories_simple(self): card = create_test_card() data = {"Categories": "foo"} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/khard-0.21.0/test/test_yaml_editable.py new/khard-0.22.0/test/test_yaml_editable.py --- old/khard-0.21.0/test/test_yaml_editable.py 2024-12-20 18:36:07.000000000 +0100 +++ new/khard-0.22.0/test/test_yaml_editable.py 2026-10-02 08:54:01.000000000 +0200 @@ -47,6 +47,14 @@ self.assertIn("home1", yaml_dump) self.assertIn("home2", yaml_dump) + def test_dumping_multiple_impp_handles_to_yaml(self): + yaml_editable = TestYAMLEditable() + yaml_editable._add_impp("xmpp", "[email protected]") + yaml_editable._add_impp("xmpp", "[email protected]") + yaml_dump = yaml_editable.to_yaml() + self.assertIn("[email protected]", yaml_dump) + self.assertIn("[email protected]", yaml_dump) + def test_empty_kind_is_included_in_yaml_format(self): contact = TestYAMLEditable() yaml = contact.to_yaml()
