diff -Nru python-dbusmock-0.28.4/dbusmock/__init__.py python-dbusmock-0.28.6/dbusmock/__init__.py --- python-dbusmock-0.28.4/dbusmock/__init__.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/__init__.py 2022-10-12 05:10:28.000000000 +0000 @@ -8,13 +8,22 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' -__version__ = '0.28.4' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' from dbusmock.mockobject import (DBusMockObject, MOCK_IFACE, OBJECT_MANAGER_IFACE, get_object, get_objects) from dbusmock.testcase import DBusTestCase +try: + # created by setuptools_scm + from dbusmock._version import __version__ +except ImportError: + __version__ = '0.git' + + __all__ = ['DBusMockObject', 'MOCK_IFACE', 'OBJECT_MANAGER_IFACE', 'DBusTestCase', 'get_object', 'get_objects'] diff -Nru python-dbusmock-0.28.4/dbusmock/__main__.py python-dbusmock-0.28.6/dbusmock/__main__.py --- python-dbusmock-0.28.4/dbusmock/__main__.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/__main__.py 2022-10-12 05:10:28.000000000 +0000 @@ -8,7 +8,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import argparse import json diff -Nru python-dbusmock-0.28.4/dbusmock/mockobject.py python-dbusmock-0.28.6/dbusmock/mockobject.py --- python-dbusmock-0.28.4/dbusmock/mockobject.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/mockobject.py 2022-10-12 05:10:28.000000000 +0000 @@ -8,7 +8,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import copy import functools @@ -18,6 +21,7 @@ import sys import time import types +from pathlib import Path from typing import Optional, Dict, Any, List, Tuple, Sequence, KeysView from xml.etree import ElementTree @@ -44,12 +48,13 @@ def load_module(name: str): '''Load a mock template Python module from dbusmock/templates/''' - if os.path.exists(name) and os.path.splitext(name)[1] == '.py': - spec = importlib.util.spec_from_file_location(os.path.splitext(os.path.basename(name))[0], name) + pname = Path(name) + + if pname.exists() and pname.suffix == '.py': + spec = importlib.util.spec_from_file_location(pname.stem, name) assert spec mod = importlib.util.module_from_spec(spec) - with open(name, encoding="UTF-8") as f: - exec(f.read(), mod.__dict__, mod.__dict__) # pylint: disable=exec-used + exec(pname.read_text("UTF-8"), mod.__dict__, mod.__dict__) # pylint: disable=exec-used return mod return importlib.import_module('dbusmock.templates.' + name) @@ -452,7 +457,7 @@ # mock_method(); using message_keyword with this dynamic approach fails # because inspect cannot handle those, so pass on interface and method # name as first positional arguments - method = lambda self, *args, **kwargs: DBusMockObject.mock_method( + method = lambda self, *args, **kwargs: DBusMockObject.mock_method( # noqa: E731 self, interface, name, in_sig, *args, **kwargs) # we cannot specify in_signature here, as that trips over a consistency @@ -614,7 +619,8 @@ args = _convert_args(signature, sigargs) - sig = dbus.lowlevel.SignalMessage(self.path, interface, name) + path = details.get("path", self.path) + sig = dbus.lowlevel.SignalMessage(path, interface, name) sig.append(*args, signature=signature) dest = details.get("destination", None) if dest is not None: @@ -623,7 +629,7 @@ for location in self.locations: conn = location[0] conn.send_message(sig) - self.log(f'emit {self.path} {interface}.{name}{_format_args(args)}') + self.log(f'emit {path} {interface}.{name}{_format_args(args)}') @dbus.service.method(MOCK_IFACE, in_signature='sssav', @@ -660,6 +666,7 @@ "signature" details: dictionary with a string key/value entries. Supported keys are: "destination": for the signal destination + "path": for the object path to send the signal from ''' self._emit_signal(interface, name, signature, sigargs, details) diff -Nru python-dbusmock-0.28.4/dbusmock/templates/bluez5-obex.py python-dbusmock-0.28.6/dbusmock/templates/bluez5-obex.py --- python-dbusmock-0.28.4/dbusmock/templates/bluez5-obex.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/bluez5-obex.py 2022-10-12 05:10:28.000000000 +0000 @@ -16,10 +16,13 @@ # of the license. __author__ = 'Philip Withnall' -__copyright__ = '(c) 2013 Collabora Ltd.' +__copyright__ = ''' +(c) 2013 Collabora Ltd. +(c) 2017 - 2022 Martin Pitt +''' import tempfile -import os +from pathlib import Path import dbus @@ -188,7 +191,7 @@ with tempfile.NamedTemporaryFile(suffix='.vcf', prefix='tmp-bluez5-obex-PullAll_', delete=False) as temp_file: - filename = os.path.abspath(temp_file.name) + filename = Path(temp_file.name).resolve() props = { 'Status': dbus.String('queued', variant_level=1), @@ -268,7 +271,7 @@ TransferCreated signal). ''' status = 'complete' if is_complete else 'active' - transferred = os.path.getsize(self.props[TRANSFER_IFACE]['Filename']) + transferred = Path(self.props[TRANSFER_IFACE]['Filename']).stat().st_size self.props[TRANSFER_IFACE]['Status'] = status self.props[TRANSFER_IFACE]['Transferred'] = dbus.UInt64(transferred, variant_level=1) diff -Nru python-dbusmock-0.28.4/dbusmock/templates/bluez5.py python-dbusmock-0.28.6/dbusmock/templates/bluez5.py --- python-dbusmock-0.28.4/dbusmock/templates/bluez5.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/bluez5.py 2022-10-12 05:10:28.000000000 +0000 @@ -16,9 +16,13 @@ # of the license. __author__ = 'Philip Withnall' -__copyright__ = '(c) 2013 Collabora Ltd.' +__copyright__ = ''' +(c) 2013 Collabora Ltd. +(c) 2017 - 2022 Martin Pitt +''' + +from pathlib import Path -import os import dbus from dbusmock import OBJECT_MANAGER_IFACE, mockobject @@ -298,7 +302,7 @@ 'Device already paired', name='org.bluez.Error.AlreadyExists') device_address = device.props[DEVICE_IFACE]['Address'] - adapter_device_name = os.path.basename(device.props[DEVICE_IFACE]['Adapter']) + adapter_device_name = Path(device.props[DEVICE_IFACE]['Adapter']).name device.PairDevice(adapter_device_name, device_address, MOCK_PHONE_CLASS) diff -Nru python-dbusmock-0.28.4/dbusmock/templates/gnome_screensaver.py python-dbusmock-0.28.6/dbusmock/templates/gnome_screensaver.py --- python-dbusmock-0.28.4/dbusmock/templates/gnome_screensaver.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/gnome_screensaver.py 2022-10-12 05:10:28.000000000 +0000 @@ -11,7 +11,10 @@ # of the license. __author__ = 'Bastien Nocera' -__copyright__ = '(c) 2013 Red Hat Inc.' +__copyright__ = ''' +(c) 2013 Red Hat Inc. +(c) 2017 - 2022 Martin Pitt +''' BUS_NAME = 'org.gnome.ScreenSaver' MAIN_OBJ = '/org/gnome/ScreenSaver' diff -Nru python-dbusmock-0.28.4/dbusmock/templates/iio-sensors-proxy.py python-dbusmock-0.28.6/dbusmock/templates/iio-sensors-proxy.py --- python-dbusmock-0.28.4/dbusmock/templates/iio-sensors-proxy.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/iio-sensors-proxy.py 2022-10-12 05:10:28.000000000 +0000 @@ -8,7 +8,10 @@ # of the license. __author__ = 'Marco Trevisan' -__copyright__ = '(c) 2021 Canonical Ltd.' +__copyright__ = ''' +(c) 2021 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import re diff -Nru python-dbusmock-0.28.4/dbusmock/templates/logind.py python-dbusmock-0.28.6/dbusmock/templates/logind.py --- python-dbusmock-0.28.4/dbusmock/templates/logind.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/logind.py 2022-10-12 05:10:28.000000000 +0000 @@ -12,7 +12,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import os import dbus @@ -189,20 +192,22 @@ self.AddObject(user_path, 'org.freedesktop.login1.User', { - 'Sessions': dbus.Array([], signature='(so)'), - 'IdleHint': False, 'DefaultControlGroup': 'systemd:/user/' + username, - 'Name': username, - 'RuntimePath': f'/run/user/{uid}', - 'Service': '', - 'State': (active and 'active' or 'online'), 'Display': ('', dbus.ObjectPath('/')), - 'UID': dbus.UInt32(uid), 'GID': dbus.UInt32(uid), + 'IdleHint': False, 'IdleSinceHint': dbus.UInt64(0), 'IdleSinceHintMonotonic': dbus.UInt64(0), + 'Linger': False, + 'Name': username, + 'RuntimePath': f'/run/user/{uid}', + 'Service': '', + 'Sessions': dbus.Array([], signature='(so)'), + 'Slice': f'user-{uid}.slice', + 'State': (active and 'active' or 'online'), 'Timestamp': dbus.UInt64(42), 'TimestampMonotonic': dbus.UInt64(42), + 'UID': dbus.UInt32(uid), }, [ ('Kill', 's', '', ''), diff -Nru python-dbusmock-0.28.4/dbusmock/templates/low_memory_monitor.py python-dbusmock-0.28.6/dbusmock/templates/low_memory_monitor.py --- python-dbusmock-0.28.4/dbusmock/templates/low_memory_monitor.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/low_memory_monitor.py 2022-10-12 05:10:28.000000000 +0000 @@ -13,7 +13,10 @@ # of the license. __author__ = 'Bastien Nocera' -__copyright__ = '(c) 2019, Red Hat Inc.' +__copyright__ = ''' +(c) 2019, Red Hat Inc. +(c) 2017 - 2022 Martin Pitt +''' import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/templates/networkmanager.py python-dbusmock-0.28.6/dbusmock/templates/networkmanager.py --- python-dbusmock-0.28.4/dbusmock/templates/networkmanager.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/networkmanager.py 2022-10-12 05:10:28.000000000 +0000 @@ -13,7 +13,10 @@ # of the license. __author__ = 'Iftikhar Ahmad' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import uuid import binascii diff -Nru python-dbusmock-0.28.4/dbusmock/templates/notification_daemon.py python-dbusmock-0.28.6/dbusmock/templates/notification_daemon.py --- python-dbusmock-0.28.4/dbusmock/templates/notification_daemon.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/notification_daemon.py 2022-10-12 05:10:28.000000000 +0000 @@ -12,7 +12,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' BUS_NAME = 'org.freedesktop.Notifications' MAIN_OBJ = '/org/freedesktop/Notifications' diff -Nru python-dbusmock-0.28.4/dbusmock/templates/ofono.py python-dbusmock-0.28.6/dbusmock/templates/ofono.py --- python-dbusmock-0.28.4/dbusmock/templates/ofono.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/ofono.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/templates/polkitd.py python-dbusmock-0.28.6/dbusmock/templates/polkitd.py --- python-dbusmock-0.28.4/dbusmock/templates/polkitd.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/polkitd.py 2022-10-12 05:10:28.000000000 +0000 @@ -13,7 +13,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2013-2021 Canonical Ltd.' +__copyright__ = ''' +(c) 2013-2021 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import time import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/templates/power_profiles_daemon.py python-dbusmock-0.28.6/dbusmock/templates/power_profiles_daemon.py --- python-dbusmock-0.28.4/dbusmock/templates/power_profiles_daemon.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/power_profiles_daemon.py 2022-10-12 05:10:28.000000000 +0000 @@ -13,7 +13,10 @@ # of the license. __author__ = 'Bastien Nocera' -__copyright__ = '(c) 2021, Red Hat Inc.' +__copyright__ = ''' +(c) 2021, Red Hat Inc. +(c) 2017 - 2022 Martin Pitt +''' import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/templates/SKELETON python-dbusmock-0.28.6/dbusmock/templates/SKELETON --- python-dbusmock-0.28.4/dbusmock/templates/SKELETON 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/SKELETON 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,64 @@ +'''CHANGEME mock template + +This creates the expected methods and properties of the main +CHANGEME object, but no devices. You can specify any property +such as CHANGEME in "parameters". +''' + +# This program is free software; you can redistribute it and/or modify it under +# the terms of the GNU Lesser General Public License as published by the Free +# Software Foundation; either version 3 of the License, or (at your option) any +# later version. See http://www.gnu.org/copyleft/lgpl.html for the full text +# of the license. + +__author__ = 'CHANGEME' +__copyright__ = 'CHANGEME' + +import dbus + +from dbusmock import MOCK_IFACE + +# False for session bus, True for system bus; if not present, the bus has to be +# specified in the spawn_server_template() call +SYSTEM_BUS = True # CHANGEME +BUS_NAME = 'org.freedesktop.CHANGEME' +MAIN_OBJ = '/org/freedesktop/CHANGEME' +# If your top-level object is an org.freedesktop.DBus.ObjectManager, you can +# skip setting MAIN_IFACE and set IS_OBJECT_MANAGER to True; then dbusmock will +# automatically provide the GetManagedObjects() API. In all other cases, +# specify the interface name of the main object here. +MAIN_IFACE = 'org.freedesktop.CHANGEME' +# IS_OBJECT_MANAGER = True + + +def load(mock, parameters): + mock.AddMethods(MAIN_IFACE, [ + # CHANGEME: Add some methods if required, otherwise drop the AddMethods call + ('CHANGEME', '', 'b', 'ret = %s' % parameters.get('CHANGEME', True)), + ]) + + mock.AddProperties(MAIN_IFACE, + dbus.Dictionary({ + # CHANGEME: Add properties if required, otherwise + # drop this call + 'MyProperty': parameters.get('MyProperty', 'CHANGEME'), + }, signature='sv')) + + +# CHANGEME: You can add convenience methods to the org.freedesktop.DBus.Mock +# interface to provide abstract functionality such as adding specific devices + +@dbus.service.method(MOCK_IFACE, + in_signature='ss', out_signature='s') +def AddCHANGEME(self, device_name, _CHANGEME): + '''Convenience method to add a CHANGEME object + + You have to specify a ... + + Please note that this does not set any global properties. + + Returns the new object path. + ''' + path = '/org/freedesktop/CHANGEME/' + device_name + self.AddObject(path, ...) + return path diff -Nru python-dbusmock-0.28.4/dbusmock/templates/systemd.py python-dbusmock-0.28.6/dbusmock/templates/systemd.py --- python-dbusmock-0.28.4/dbusmock/templates/systemd.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/systemd.py 2022-10-12 05:10:28.000000000 +0000 @@ -8,7 +8,10 @@ # of the license. __author__ = 'Jonas Ådahl' -__copyright__ = '(c) 2021 Red Hat' +__copyright__ = ''' +(c) 2021 Red Hat +(c) 2017 - 2022 Martin Pitt +''' from gi.repository import GLib import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/templates/timedated.py python-dbusmock-0.28.6/dbusmock/templates/timedated.py --- python-dbusmock-0.28.4/dbusmock/templates/timedated.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/timedated.py 2022-10-12 05:10:28.000000000 +0000 @@ -12,7 +12,10 @@ # of the license. __author__ = 'Iain Lane' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/templates/upower.py python-dbusmock-0.28.6/dbusmock/templates/upower.py --- python-dbusmock-0.28.4/dbusmock/templates/upower.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/upower.py 2022-10-12 05:10:28.000000000 +0000 @@ -15,7 +15,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012, 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2012, 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/templates/urfkill.py python-dbusmock-0.28.6/dbusmock/templates/urfkill.py --- python-dbusmock-0.28.4/dbusmock/templates/urfkill.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/templates/urfkill.py 2022-10-12 05:10:28.000000000 +0000 @@ -12,7 +12,10 @@ # of the license. __author__ = 'Jussi Pakkanen' -__copyright__ = '(C) 2015 Canonical ltd' +__copyright__ = ''' +(C) 2015 Canonical ltd +(c) 2017 - 2022 Martin Pitt +''' import dbus diff -Nru python-dbusmock-0.28.4/dbusmock/testcase.py python-dbusmock-0.28.6/dbusmock/testcase.py --- python-dbusmock-0.28.4/dbusmock/testcase.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/testcase.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import errno import os @@ -18,7 +21,8 @@ import tempfile import time import unittest -from typing import Tuple, Dict, Any +from pathlib import Path +from typing import Tuple, Dict, Any, Union import dbus @@ -36,7 +40,7 @@ ''' session_bus_pid = None system_bus_pid = None - _DBusTestCase__datadir = '' + _DBusTestCase__datadir = None @classmethod def get_services_dir(cls, system_bus: bool = False) -> str: @@ -51,15 +55,15 @@ else: services_dir = 'services' if not DBusTestCase._DBusTestCase__datadir: - DBusTestCase._DBusTestCase__datadir = tempfile.mkdtemp(prefix='dbusmock_data_') - os.mkdir(os.path.join(DBusTestCase._DBusTestCase__datadir, 'system_services')) - os.mkdir(os.path.join(DBusTestCase._DBusTestCase__datadir, 'services')) + DBusTestCase._DBusTestCase__datadir = Path(tempfile.mkdtemp(prefix='dbusmock_data_')) + (DBusTestCase._DBusTestCase__datadir / 'system_services').mkdir() + (DBusTestCase._DBusTestCase__datadir / 'services').mkdir() - return os.path.join(DBusTestCase._DBusTestCase__datadir, services_dir) + return str(DBusTestCase._DBusTestCase__datadir / services_dir) @classmethod def tearDownClass(cls): - setattr(cls, '_DBusTestCase__datadir', '') + setattr(cls, '_DBusTestCase__datadir', None) if cls._DBusTestCase__datadir: shutil.rmtree(cls._DBusTestCase__datadir) @@ -80,9 +84,10 @@ This gets stopped automatically at class teardown. ''' cls.get_services_dir() + assert cls._DBusTestCase__datadir - with open(os.path.join(DBusTestCase._DBusTestCase__datadir, f'dbusmock_{bus_type}_cfg'), 'w', encoding='ascii') as c: - c.write(f''' {bus_type} @@ -98,8 +103,7 @@ ''') - c.flush() - (pid, addr) = cls.start_dbus(conf=c.name) + (pid, addr) = cls.start_dbus(conf=conf) os.environ[f'DBUS_{bus_type.upper()}_BUS_ADDRESS'] = addr setattr(cls, f'{bus_type}_bus_pid', pid) @@ -120,7 +124,7 @@ DBusTestCase.__start_bus('system') @classmethod - def start_dbus(cls, conf: str = None) -> Tuple[int, str]: + def start_dbus(cls, conf: Union[str, Path] = None) -> Tuple[int, str]: '''Start a D-Bus daemon Return (pid, address) pair. @@ -130,7 +134,7 @@ ''' argv = ['dbus-daemon', '--fork', '--print-address=1', '--print-pid=1'] if conf: - argv.append('--config-file=' + conf) + argv.append('--config-file=' + str(conf)) else: argv.append('--session') lines = subprocess.check_output(argv, universal_newlines=True).strip().splitlines() @@ -306,9 +310,9 @@ xdg_data_dirs = os.environ.get('XDG_DATA_DIRS') or '/usr/local/share/:/usr/share/' for d in xdg_data_dirs.split(':'): - src = os.path.join(d, 'dbus-1', services_dir, service + '.service') - if os.path.exists(src): - os.symlink(src, os.path.join(cls.get_services_dir(system_bus), service + '.service')) + src = Path(d, 'dbus-1', services_dir, service + '.service') + if src.exists(): + Path(cls.get_services_dir(system_bus), service + '.service').symlink_to(src) break else: raise AssertionError(f"Service {service} not found in XDG_DATA_DIRS ({xdg_data_dirs})") @@ -329,7 +333,7 @@ daemon configuration if a test bus is running. ''' try: - os.unlink(os.path.join(cls.get_services_dir(system_bus), service + '.service')) + Path(cls.get_services_dir(system_bus), service + '.service').unlink() except OSError: raise AssertionError(f"Service {service} not found") from None diff -Nru python-dbusmock-0.28.4/dbusmock/_version.py python-dbusmock-0.28.6/dbusmock/_version.py --- python-dbusmock-0.28.4/dbusmock/_version.py 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/dbusmock/_version.py 2022-10-12 05:10:38.000000000 +0000 @@ -0,0 +1,2 @@ +'''auto-generated version from setuptools_scm''' +__version__ = "0.28.6" diff -Nru python-dbusmock-0.28.4/debian/changelog python-dbusmock-0.28.6/debian/changelog --- python-dbusmock-0.28.4/debian/changelog 2022-07-19 12:39:51.000000000 +0000 +++ python-dbusmock-0.28.6/debian/changelog 2022-10-12 05:31:35.000000000 +0000 @@ -1,3 +1,15 @@ +python-dbusmock (0.28.6-1) unstable; urgency=medium + + * New upstream version: + - Allow sending signals from a specific path (thanks Peter Hutterer) + - logind: Adjust for systemd 252 + - Use setuptools_scm to determine version + * debian/copyright: Update to current upstream copyrights + * debian/watch: Move to PyPI. GitHub's release page became obfuscated and + cannot be processed by uscan any more. + + -- Martin Pitt Wed, 12 Oct 2022 07:31:35 +0200 + python-dbusmock (0.28.4-1) unstable; urgency=medium * New upstream version: diff -Nru python-dbusmock-0.28.4/debian/copyright python-dbusmock-0.28.6/debian/copyright --- python-dbusmock-0.28.4/debian/copyright 2021-08-23 07:15:43.000000000 +0000 +++ python-dbusmock-0.28.6/debian/copyright 2022-10-12 05:24:30.000000000 +0000 @@ -5,7 +5,10 @@ Files: * Copyright: - Copyright (C) 2012 Canonical Ltd. + Copyright (C) 2012 - 2015 Canonical Ltd. + Copyright (c) 2013 Collabora Ltd. + Copyright (c) 2013, 2019, 2021 Red Hat Inc. + Copyright (c) 2017 - 2022 Martin Pitt License: GPL-3+ This program is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by diff -Nru python-dbusmock-0.28.4/debian/watch python-dbusmock-0.28.6/debian/watch --- python-dbusmock-0.28.4/debian/watch 2021-08-23 07:15:43.000000000 +0000 +++ python-dbusmock-0.28.6/debian/watch 2022-10-12 05:29:27.000000000 +0000 @@ -1,2 +1,3 @@ version=4 -https://github.com/martinpitt/python-dbusmock/releases/ .*/python-dbusmock-([\d\.]+)\.tar\.gz +https://pypi.python.org/packages/source/p/python-dbusmock/ \ + python-dbusmock-@ANY_VERSION@@ARCHIVE_EXT@ diff -Nru python-dbusmock-0.28.4/.flake8 python-dbusmock-0.28.6/.flake8 --- python-dbusmock-0.28.4/.flake8 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/.flake8 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,7 @@ +[flake8] +ignore= + # line break after binary operator + W504 + # closing bracket does not match visual indentation + E124 +max-line-length = 130 diff -Nru python-dbusmock-0.28.4/.github/release.eloquent.yml python-dbusmock-0.28.6/.github/release.eloquent.yml --- python-dbusmock-0.28.4/.github/release.eloquent.yml 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/.github/release.eloquent.yml 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,2 @@ +assets: + - path: dist/python-dbusmock*.tar.* diff -Nru python-dbusmock-0.28.4/.github/workflows/release.yml python-dbusmock-0.28.6/.github/workflows/release.yml --- python-dbusmock-0.28.4/.github/workflows/release.yml 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/.github/workflows/release.yml 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,47 @@ +name: tag +on: + push: + tags: + # this is a glob, not a regexp + - '[0-9]*' +jobs: + release: + runs-on: ubuntu-22.04 + steps: + - name: Clone repository + uses: actions/checkout@v2 + with: + # need this to also fetch tags + fetch-depth: 0 + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y python3-setuptools python3-setuptools-scm python3-dbus + dpkg -l + + - name: Build release tarball + run: ./setup.py sdist + + - name: Sanity check + run: | + set -eux + mkdir tmp + cd tmp + tar xf ../dist/python-dbusmock-${{ github.ref_name }}.tar.gz + cd python-dbusmock-* + test "$(PYTHONPATH=. python3 -c 'import dbusmock; print(dbusmock.__version__)')" = "${{ github.ref_name }}" + PYTHONPATH=. python3 tests/test_api.py + cd ../.. + rm -rf tmp + + - name: Create GitHub release + uses: eloquent/github-release-action@v2 + with: + prerelease: "false" + + - name: Create PyPy release + uses: pypa/gh-action-pypi-publish@release/v1 + with: + user: __token__ + password: ${{ secrets.PYPI_API_TOKEN }} diff -Nru python-dbusmock-0.28.4/.github/workflows/tests.yml python-dbusmock-0.28.6/.github/workflows/tests.yml --- python-dbusmock-0.28.4/.github/workflows/tests.yml 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/.github/workflows/tests.yml 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,35 @@ +name: unit-tests +on: + push: + pull_request: + schedule: + - cron: 0 4 * * MON,FRI +jobs: + OS: + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + scenario: + - docker.io/debian:unstable + - docker.io/ubuntu:devel + - docker.io/ubuntu:rolling + - docker.io/ubuntu:latest + - registry.fedoraproject.org/fedora:latest + - registry.fedoraproject.org/fedora:rawhide + - quay.io/centos/centos:stream8 + + timeout-minutes: 30 + steps: + - name: Clone repository + uses: actions/checkout@v2 + with: + # need this to also fetch tags + fetch-depth: 0 + + - name: Run unit tests + run: | + dpkg -s podman docker || true + cat /etc/apt/sources.list + cat /etc/apt/sources.list.d/* + ${{ matrix.env }} tests/run ${{ matrix.scenario }} diff -Nru python-dbusmock-0.28.4/.gitignore python-dbusmock-0.28.6/.gitignore --- python-dbusmock-0.28.4/.gitignore 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/.gitignore 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,6 @@ +/dist +/dbusmock/_version.py +__pycache__ +*.egg-info +MANIFEST +/build diff -Nru python-dbusmock-0.28.4/MANIFEST.in python-dbusmock-0.28.6/MANIFEST.in --- python-dbusmock-0.28.4/MANIFEST.in 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/MANIFEST.in 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -include .fmf/version -include plans/all.fmf -include tests/*.py -include tests/*.fmf -include COPYING* -include NEWS diff -Nru python-dbusmock-0.28.4/packaging/python-dbusmock.spec python-dbusmock-0.28.6/packaging/python-dbusmock.spec --- python-dbusmock-0.28.4/packaging/python-dbusmock.spec 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/packaging/python-dbusmock.spec 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,53 @@ +%global modname dbusmock + +Name: python-%{modname} +Version: 0.23.0 +Release: 1%{?dist} +Summary: Mock D-Bus objects + +License: LGPLv3+ +URL: https://pypi.python.org/pypi/python-dbusmock +Source0: https://files.pythonhosted.org/packages/source/p/%{name}/%{name}-%{version}.tar.gz + +BuildArch: noarch +BuildRequires: git +BuildRequires: python3-dbus +BuildRequires: python3-devel +BuildRequires: python3-setuptools +BuildRequires: python3-gobject +BuildRequires: dbus-x11 +BuildRequires: upower + +%global _description\ +With this program/Python library you can easily create mock objects on\ +D-Bus. This is useful for writing tests for software which talks to\ +D-Bus services such as upower, systemd, ConsoleKit, gnome-session or\ +others, and it is hard (or impossible without root privileges) to set\ +the state of the real services to what you expect in your tests. + +%description %_description + +%package -n python3-dbusmock +Summary: %summary (Python3) +Requires: python3-dbus, python3-gobject, dbus-x11 +%description -n python3-dbusmock %_description + +%prep +%autosetup -n %{name}-%{version} -S git +rm -rf python-%{modname}.egg-info + + +%build +%py3_build + +%install +%py3_install + +%check +%{__python3} -m unittest -v + +%files -n python3-dbusmock +%doc README.md COPYING +%{python3_sitelib}/*%{modname}* + +%changelog diff -Nru python-dbusmock-0.28.4/packit.yaml python-dbusmock-0.28.6/packit.yaml --- python-dbusmock-0.28.4/packit.yaml 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/packit.yaml 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,43 @@ +# See the documentation for more information: +# https://packit.dev/docs/configuration/ +upstream_project_url: https://github.com/martinpitt/python-dbusmock +# HACK: should work without, but propose_downstream fails; https://github.com/packit/packit-service/issues/1511 +specfile_path: packaging/python-dbusmock.spec +issue_repository: https://github.com/martinpitt/python-dbusmock +copy_upstream_release_description: true +upstream_package_name: python-dbusmock +downstream_package_name: python-dbusmock + +actions: + create-archive: + - ./setup.py sdist + # spec and tarball need to be in the same directory + - sh -c 'mv dist/*.tar.* packaging; ls packaging/python-dbusmock-*.tar.*' + +srpm_build_deps: + - python3-setuptools + - python3-setuptools_scm + +jobs: + - job: tests + trigger: pull_request + targets: + - fedora-all + - centos-stream-8-x86_64 + - centos-stream-9-x86_64 + + - job: propose_downstream + trigger: release + dist_git_branches: + - fedora-all + + - job: koji_build + trigger: commit + dist_git_branches: + - fedora-all + + - job: bodhi_update + trigger: commit + dist_git_branches: + # rawhide updates are created automatically + - fedora-branched diff -Nru python-dbusmock-0.28.4/PKG-INFO python-dbusmock-0.28.6/PKG-INFO --- python-dbusmock-0.28.4/PKG-INFO 2022-07-19 12:33:07.430766000 +0000 +++ python-dbusmock-0.28.6/PKG-INFO 2022-10-12 05:10:38.829541400 +0000 @@ -1,285 +1,12 @@ Metadata-Version: 2.1 Name: python-dbusmock -Version: 0.28.4 +Version: 0.28.6 Summary: Mock D-Bus objects Home-page: https://github.com/martinpitt/python-dbusmock Author: Martin Pitt Author-email: martin@piware.de License: LGPL 3+ Download-URL: https://pypi.python.org/pypi/python-dbusmock/ -Description: python-dbusmock - =============== - - ## Purpose - - With this program/Python library you can easily create mock objects on - D-Bus. This is useful for writing tests for software which talks to - D-Bus services such as upower, systemd, logind, gnome-session or others, - and it is hard (or impossible without root privileges) to set the state - of the real services to what you expect in your tests. - - Suppose you want to write tests for gnome-settings-daemon's power - plugin, or another program that talks to upower. You want to verify that - after the configured idle time the program suspends the machine. So your - program calls `org.freedesktop.UPower.Suspend()` on the system D-Bus. - - Now, your test suite should not really talk to the actual system D-Bus - and the real upower; a `make check` that suspends your machine will not - be considered very friendly by most people, and if you want to run this - in continuous integration test servers or package build environments, - chances are that your process does not have the privilege to suspend, or - there is no system bus or upower to begin with. Likewise, there is no - way for an user process to forcefully set the system/seat idle flag in - logind, so your tests cannot set up the expected test environment on the - real daemon. - - That's where mock objects come into play: They look like the real API - (or at least the parts that you actually need), but they do not actually - do anything (or only some action that you specify yourself). You can - configure their state, behaviour and responses as you like in your test, - without making any assumptions about the real system status. - - When using a local system/session bus, you can do unit or integration - testing without needing root privileges or disturbing a running system. - The Python API offers some convenience functions like - `start_session_bus()` and `start_system_bus()` for this, in a - `DBusTestCase` class (subclass of the standard `unittest.TestCase`). - - You can use this with any programming language, as you can run the - mocker as a normal program. The actual setup of the mock (adding - objects, methods, properties, and signals) all happen via D-Bus methods - on the `org.freedesktop.DBus.Mock` interface. You just don't have the - convenience D-Bus launch API that way. - - ## Simple example in Python - - Picking up the above example about mocking upower's `Suspend()` method, - this is how you would set up a mock upower in your test case: - - ```python - import dbus - import dbusmock - - class TestMyProgram(dbusmock.DBusTestCase): - @classmethod - def setUpClass(cls): - cls.start_system_bus() - cls.dbus_con = cls.get_dbus(system_bus=True) - - def setUp(self): - self.p_mock = self.spawn_server('org.freedesktop.UPower', - '/org/freedesktop/UPower', - 'org.freedesktop.UPower', - system_bus=True, - stdout=subprocess.PIPE) - - # Get a proxy for the UPower object's Mock interface - self.dbus_upower_mock = dbus.Interface(self.dbus_con.get_object( - 'org.freedesktop.UPower', '/org/freedesktop/UPower'), - dbusmock.MOCK_IFACE) - - self.dbus_upower_mock.AddMethod('', 'Suspend', '', '', '') - - def tearDown(self): - self.p_mock.stdout.close() - self.p_mock.terminate() - self.p_mock.wait() - - def test_suspend_on_idle(self): - # run your program in a way that should trigger one suspend call - - # now check the log that we got one Suspend() call - self.assertRegex(self.p_mock.stdout.readline(), b'^[0-9.]+ Suspend$') - ``` - - Let's walk through: - - - We derive our tests from `dbusmock.DBusTestCase` instead of - `unittest.TestCase` directly, to make use of the convenience API - to start a local system bus. - - - `setUpClass()` starts a local system bus, and makes a connection - to it available to all methods as `dbus_con`. `True` means that we - connect to the system bus, not the session bus. We can use the - same bus for all tests, so doing this once in `setUpClass()` - instead of `setUp()` is enough. - - - `setUp()` spawns the mock D-Bus server process for an initial - `/org/freedesktop/UPower` object with an `org.freedesktop.UPower` - D-Bus interface on the system bus. We capture its stdout to be - able to verify that methods were called. - - We then call `org.freedesktop.DBus.Mock.AddMethod()` to add a - `Suspend()` method to our new object to the default D-Bus - interface. This will not do anything (except log its call to - stdout). It takes no input arguments, returns nothing, and does - not run any custom code. - - - `tearDown()` stops our mock D-Bus server again. We do this so that - each test case has a fresh and clean upower instance, but of - course you can also set up everything in `setUpClass()` if tests - do not interfere with each other on setting up the mock. - - - `test_suspend_on_idle()` is the actual test case. It needs to run - your program in a way that should trigger one suspend call. Your - program will try to call `Suspend()`, but as that's now being - served by our mock instead of upower, there will not be any actual - machine suspend. Our mock process will log the method call - together with a time stamp; you can use the latter for doing - timing related tests, but we just ignore it here. - - ## Simple example from shell - - We use the actual session bus for this example. You can use - `dbus-run-session` to start a private one as well if you want, but that - is not part of the actual mocking. - - So let's start a mock at the D-Bus name `com.example.Foo` with an - initial "main" object on path /, with the main D-Bus interface - `com.example.Foo.Manager`: - - python3 -m dbusmock com.example.Foo / com.example.Foo.Manager - - On another terminal, let's first see what it does: - - gdbus introspect --session -d com.example.Foo -o / - - You'll see that it supports the standard D-Bus `Introspectable` and - `Properties` interfaces, as well as the `org.freedesktop.DBus.Mock` - interface for controlling the mock, but no "real" functionality yet. - So let's add a method: - - gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod '' Ping '' '' '' - - Now you can see the new method in `introspect`, and call it: - - gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Ping - - The mock process in the other terminal will log the method call with a - time stamp, and you'll see something like `1348832614.970 Ping`. - - Now add another method with two int arguments and a return value and - call it: - - gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod \ - '' Add 'ii' 'i' 'ret = args[0] + args[1]' - gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Add 2 3 - - This will print `(5,)` as expected (remember that the return value is - always a tuple), and again the mock process will log the Add method - call. - - You can do the same operations in e. g. d-feet or any other D-Bus - language binding. - - ## Logging - - Usually you want to verify which methods have been called on the mock - with which arguments. There are three ways to do that: - - - By default, the mock process writes the call log to stdout. - - You can call the mock process with the `-l`/`--logfile` argument, - or specify a log file object in the `spawn_server()` method if you - are using Python. - - You can use the `GetCalls()`, `GetMethodCalls()` and - `ClearCalls()` methods on the `org.freedesktop.DBus.Mock` D-Bus - interface to get an array of tuples describing the calls. - - ## Templates - - Some D-Bus services are commonly used in test suites, such as UPower or - NetworkManager. python-dbusmock provides "templates" which set up the - common structure of these services (their main objects, properties, and - methods) so that you do not need to carry around this common code, and - only need to set up the particular properties and specific D-Bus objects - that you need. These templates can be parameterized for common - customizations, and they can provide additional convenience methods on - the `org.freedesktop.DBus.Mock` interface to provide more abstract - functionality like "add a battery". - - For example, for starting a server with the `upower` template in - Python you can run - - (self.p_mock, self.obj_upower) = self.spawn_server_template( - 'upower', {'OnBattery': True}, stdout=subprocess.PIPE) - - or load a template into an already running server with the - `AddTemplate()` method; this is particularly useful if you are not using - Python: - - python3 -m dbusmock --system org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower - - gdbus call --system -d org.freedesktop.UPower -o /org/freedesktop/UPower -m org.freedesktop.DBus.Mock.AddTemplate 'upower' '{"OnBattery": }' - - This creates all expected properties such as `DaemonVersion`, and - changes the default for one of them (`OnBattery`) through the (optional) - parameters dict. - - If you do not need to specify parameters, you can do this in a simpler - way with - - python3 -m dbusmock --template upower - - The template does not create any devices by default. You can add some - with the template's convenience methods like - - ac_path = self.dbusmock.AddAC('mock_AC', 'Mock AC') - bt_path = self.dbusmock.AddChargingBattery('mock_BAT', 'Mock Battery', 30.0, 1200) - - or calling `AddObject()` yourself with the desired properties, of - course. - - Templates commonly implement some non-trivial functionality with actual Python - methods and the standard [dbus-python](https://dbus.freedesktop.org/doc/dbus-python/) - [`@dbus.service.method`](https://dbus.freedesktop.org/doc/dbus-python/dbus.service.html#dbus.service.method) - decorator. - - If you want to contribute a template, look at - dbusmock/templates/upower.py for a real-life implementation. You can - copy dbusmock/templates/SKELETON to your new template file name and - replace `CHANGEME` with the actual code/values. - - ## More Examples - - Have a look at the test suite for two real-live use cases: - - - `tests/test_upower.py` simulates upowerd, in a more complete way - than in above example and using the `upower` template. It verifies - that `upower --dump` is convinced that it's talking to upower. - - `tests/test_api.py` runs a mock on the session bus and exercises - all available functionality, such as adding additional objects, - properties, multiple methods, input arguments, return values, code - in methods, sending signals, raising exceptions, and introspection. - - ## Documentation - - The `dbusmock` module has extensive documentation built in, which you - can read with e. g. `pydoc3 dbusmock`. - - `pydoc3 dbusmock.DBusMockObject` shows the D-Bus API of the mock object, - i. e. methods like `AddObject()`, `AddMethod()` etc. which are used to - set up your mock object. - - `pydoc3 dbusmock.DBusTestCase` shows the convenience Python API for - writing test cases with local private session/system buses and launching - the server. - - `pydoc3 dbusmock.templates` shows all available templates. - - `pydoc3 dbusmock.templates.NAME` shows the documentation and available - parameters for the `NAME` template. - - `python3 -m dbusmock --help` shows the arguments and options for running - the mock server as a program. - - ## Development - - python-dbusmock is hosted on https://github.com/martinpitt/python-dbusmock - - Run the unit tests with - - python3 -m unittest - Platform: UNKNOWN Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Classifier: Programming Language :: Python :: 3 @@ -293,3 +20,279 @@ Classifier: Topic :: Software Development :: Testing :: Unit Classifier: Topic :: Software Development :: Libraries :: Python Modules Description-Content-Type: text/markdown +License-File: COPYING + +python-dbusmock +=============== + +## Purpose + +With this program/Python library you can easily create mock objects on +D-Bus. This is useful for writing tests for software which talks to +D-Bus services such as upower, systemd, logind, gnome-session or others, +and it is hard (or impossible without root privileges) to set the state +of the real services to what you expect in your tests. + +Suppose you want to write tests for gnome-settings-daemon's power +plugin, or another program that talks to upower. You want to verify that +after the configured idle time the program suspends the machine. So your +program calls `org.freedesktop.UPower.Suspend()` on the system D-Bus. + +Now, your test suite should not really talk to the actual system D-Bus +and the real upower; a `make check` that suspends your machine will not +be considered very friendly by most people, and if you want to run this +in continuous integration test servers or package build environments, +chances are that your process does not have the privilege to suspend, or +there is no system bus or upower to begin with. Likewise, there is no +way for an user process to forcefully set the system/seat idle flag in +logind, so your tests cannot set up the expected test environment on the +real daemon. + +That's where mock objects come into play: They look like the real API +(or at least the parts that you actually need), but they do not actually +do anything (or only some action that you specify yourself). You can +configure their state, behaviour and responses as you like in your test, +without making any assumptions about the real system status. + +When using a local system/session bus, you can do unit or integration +testing without needing root privileges or disturbing a running system. +The Python API offers some convenience functions like +`start_session_bus()` and `start_system_bus()` for this, in a +`DBusTestCase` class (subclass of the standard `unittest.TestCase`). + +You can use this with any programming language, as you can run the +mocker as a normal program. The actual setup of the mock (adding +objects, methods, properties, and signals) all happen via D-Bus methods +on the `org.freedesktop.DBus.Mock` interface. You just don't have the +convenience D-Bus launch API that way. + +## Simple example in Python + +Picking up the above example about mocking upower's `Suspend()` method, +this is how you would set up a mock upower in your test case: + +```python +import dbus +import dbusmock + +class TestMyProgram(dbusmock.DBusTestCase): + @classmethod + def setUpClass(cls): + cls.start_system_bus() + cls.dbus_con = cls.get_dbus(system_bus=True) + + def setUp(self): + self.p_mock = self.spawn_server('org.freedesktop.UPower', + '/org/freedesktop/UPower', + 'org.freedesktop.UPower', + system_bus=True, + stdout=subprocess.PIPE) + + # Get a proxy for the UPower object's Mock interface + self.dbus_upower_mock = dbus.Interface(self.dbus_con.get_object( + 'org.freedesktop.UPower', '/org/freedesktop/UPower'), + dbusmock.MOCK_IFACE) + + self.dbus_upower_mock.AddMethod('', 'Suspend', '', '', '') + + def tearDown(self): + self.p_mock.stdout.close() + self.p_mock.terminate() + self.p_mock.wait() + + def test_suspend_on_idle(self): + # run your program in a way that should trigger one suspend call + + # now check the log that we got one Suspend() call + self.assertRegex(self.p_mock.stdout.readline(), b'^[0-9.]+ Suspend$') +``` + +Let's walk through: + + - We derive our tests from `dbusmock.DBusTestCase` instead of + `unittest.TestCase` directly, to make use of the convenience API + to start a local system bus. + + - `setUpClass()` starts a local system bus, and makes a connection + to it available to all methods as `dbus_con`. `True` means that we + connect to the system bus, not the session bus. We can use the + same bus for all tests, so doing this once in `setUpClass()` + instead of `setUp()` is enough. + + - `setUp()` spawns the mock D-Bus server process for an initial + `/org/freedesktop/UPower` object with an `org.freedesktop.UPower` + D-Bus interface on the system bus. We capture its stdout to be + able to verify that methods were called. + + We then call `org.freedesktop.DBus.Mock.AddMethod()` to add a + `Suspend()` method to our new object to the default D-Bus + interface. This will not do anything (except log its call to + stdout). It takes no input arguments, returns nothing, and does + not run any custom code. + + - `tearDown()` stops our mock D-Bus server again. We do this so that + each test case has a fresh and clean upower instance, but of + course you can also set up everything in `setUpClass()` if tests + do not interfere with each other on setting up the mock. + + - `test_suspend_on_idle()` is the actual test case. It needs to run + your program in a way that should trigger one suspend call. Your + program will try to call `Suspend()`, but as that's now being + served by our mock instead of upower, there will not be any actual + machine suspend. Our mock process will log the method call + together with a time stamp; you can use the latter for doing + timing related tests, but we just ignore it here. + +## Simple example from shell + +We use the actual session bus for this example. You can use +`dbus-run-session` to start a private one as well if you want, but that +is not part of the actual mocking. + +So let's start a mock at the D-Bus name `com.example.Foo` with an +initial "main" object on path /, with the main D-Bus interface +`com.example.Foo.Manager`: + + python3 -m dbusmock com.example.Foo / com.example.Foo.Manager + +On another terminal, let's first see what it does: + + gdbus introspect --session -d com.example.Foo -o / + +You'll see that it supports the standard D-Bus `Introspectable` and +`Properties` interfaces, as well as the `org.freedesktop.DBus.Mock` +interface for controlling the mock, but no "real" functionality yet. +So let's add a method: + + gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod '' Ping '' '' '' + +Now you can see the new method in `introspect`, and call it: + + gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Ping + +The mock process in the other terminal will log the method call with a +time stamp, and you'll see something like `1348832614.970 Ping`. + +Now add another method with two int arguments and a return value and +call it: + + gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod \ + '' Add 'ii' 'i' 'ret = args[0] + args[1]' + gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Add 2 3 + +This will print `(5,)` as expected (remember that the return value is +always a tuple), and again the mock process will log the Add method +call. + +You can do the same operations in e. g. d-feet or any other D-Bus +language binding. + +## Logging + +Usually you want to verify which methods have been called on the mock +with which arguments. There are three ways to do that: + + - By default, the mock process writes the call log to stdout. + - You can call the mock process with the `-l`/`--logfile` argument, + or specify a log file object in the `spawn_server()` method if you + are using Python. + - You can use the `GetCalls()`, `GetMethodCalls()` and + `ClearCalls()` methods on the `org.freedesktop.DBus.Mock` D-Bus + interface to get an array of tuples describing the calls. + +## Templates + +Some D-Bus services are commonly used in test suites, such as UPower or +NetworkManager. python-dbusmock provides "templates" which set up the +common structure of these services (their main objects, properties, and +methods) so that you do not need to carry around this common code, and +only need to set up the particular properties and specific D-Bus objects +that you need. These templates can be parameterized for common +customizations, and they can provide additional convenience methods on +the `org.freedesktop.DBus.Mock` interface to provide more abstract +functionality like "add a battery". + +For example, for starting a server with the `upower` template in +Python you can run + + (self.p_mock, self.obj_upower) = self.spawn_server_template( + 'upower', {'OnBattery': True}, stdout=subprocess.PIPE) + +or load a template into an already running server with the +`AddTemplate()` method; this is particularly useful if you are not using +Python: + + python3 -m dbusmock --system org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower + + gdbus call --system -d org.freedesktop.UPower -o /org/freedesktop/UPower -m org.freedesktop.DBus.Mock.AddTemplate 'upower' '{"OnBattery": }' + +This creates all expected properties such as `DaemonVersion`, and +changes the default for one of them (`OnBattery`) through the (optional) +parameters dict. + +If you do not need to specify parameters, you can do this in a simpler +way with + + python3 -m dbusmock --template upower + +The template does not create any devices by default. You can add some +with the template's convenience methods like + + ac_path = self.dbusmock.AddAC('mock_AC', 'Mock AC') + bt_path = self.dbusmock.AddChargingBattery('mock_BAT', 'Mock Battery', 30.0, 1200) + +or calling `AddObject()` yourself with the desired properties, of +course. + +Templates commonly implement some non-trivial functionality with actual Python +methods and the standard [dbus-python](https://dbus.freedesktop.org/doc/dbus-python/) +[`@dbus.service.method`](https://dbus.freedesktop.org/doc/dbus-python/dbus.service.html#dbus.service.method) +decorator. + +If you want to contribute a template, look at +dbusmock/templates/upower.py for a real-life implementation. You can +copy dbusmock/templates/SKELETON to your new template file name and +replace `CHANGEME` with the actual code/values. + +## More Examples + +Have a look at the test suite for two real-live use cases: + + - `tests/test_upower.py` simulates upowerd, in a more complete way + than in above example and using the `upower` template. It verifies + that `upower --dump` is convinced that it's talking to upower. + - `tests/test_api.py` runs a mock on the session bus and exercises + all available functionality, such as adding additional objects, + properties, multiple methods, input arguments, return values, code + in methods, sending signals, raising exceptions, and introspection. + +## Documentation + +The `dbusmock` module has extensive documentation built in, which you +can read with e. g. `pydoc3 dbusmock`. + +`pydoc3 dbusmock.DBusMockObject` shows the D-Bus API of the mock object, +i. e. methods like `AddObject()`, `AddMethod()` etc. which are used to +set up your mock object. + +`pydoc3 dbusmock.DBusTestCase` shows the convenience Python API for +writing test cases with local private session/system buses and launching +the server. + +`pydoc3 dbusmock.templates` shows all available templates. + +`pydoc3 dbusmock.templates.NAME` shows the documentation and available +parameters for the `NAME` template. + +`python3 -m dbusmock --help` shows the arguments and options for running +the mock server as a program. + +## Development + +python-dbusmock is hosted on https://github.com/martinpitt/python-dbusmock + +Run the unit tests with + + python3 -m unittest + + diff -Nru python-dbusmock-0.28.4/pyproject.toml python-dbusmock-0.28.6/pyproject.toml --- python-dbusmock-0.28.4/pyproject.toml 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/pyproject.toml 2022-10-12 05:10:28.000000000 +0000 @@ -35,6 +35,11 @@ packages = ["dbusmock", "dbusmock.templates"] [tool.setuptools_scm] +write_to = "dbusmock/_version.py" +# otherwise pylint complains about missing-module-docstring +write_to_template = """'''auto-generated version from setuptools_scm''' +__version__ = "{version}" +""" version_scheme = 'post-release' [tool.pylint] @@ -45,5 +50,5 @@ [tool.mypy] warn_unused_configs = true [[tool.mypy.overrides]] -module = ["dbus.*", "gi.repository"] +module = ["dbus.*", "gi.repository", "dbusmock._version"] ignore_missing_imports = true diff -Nru python-dbusmock-0.28.4/python_dbusmock.egg-info/PKG-INFO python-dbusmock-0.28.6/python_dbusmock.egg-info/PKG-INFO --- python-dbusmock-0.28.4/python_dbusmock.egg-info/PKG-INFO 2022-07-19 12:33:07.000000000 +0000 +++ python-dbusmock-0.28.6/python_dbusmock.egg-info/PKG-INFO 2022-10-12 05:10:38.000000000 +0000 @@ -1,285 +1,12 @@ Metadata-Version: 2.1 Name: python-dbusmock -Version: 0.28.4 +Version: 0.28.6 Summary: Mock D-Bus objects Home-page: https://github.com/martinpitt/python-dbusmock Author: Martin Pitt Author-email: martin@piware.de License: LGPL 3+ Download-URL: https://pypi.python.org/pypi/python-dbusmock/ -Description: python-dbusmock - =============== - - ## Purpose - - With this program/Python library you can easily create mock objects on - D-Bus. This is useful for writing tests for software which talks to - D-Bus services such as upower, systemd, logind, gnome-session or others, - and it is hard (or impossible without root privileges) to set the state - of the real services to what you expect in your tests. - - Suppose you want to write tests for gnome-settings-daemon's power - plugin, or another program that talks to upower. You want to verify that - after the configured idle time the program suspends the machine. So your - program calls `org.freedesktop.UPower.Suspend()` on the system D-Bus. - - Now, your test suite should not really talk to the actual system D-Bus - and the real upower; a `make check` that suspends your machine will not - be considered very friendly by most people, and if you want to run this - in continuous integration test servers or package build environments, - chances are that your process does not have the privilege to suspend, or - there is no system bus or upower to begin with. Likewise, there is no - way for an user process to forcefully set the system/seat idle flag in - logind, so your tests cannot set up the expected test environment on the - real daemon. - - That's where mock objects come into play: They look like the real API - (or at least the parts that you actually need), but they do not actually - do anything (or only some action that you specify yourself). You can - configure their state, behaviour and responses as you like in your test, - without making any assumptions about the real system status. - - When using a local system/session bus, you can do unit or integration - testing without needing root privileges or disturbing a running system. - The Python API offers some convenience functions like - `start_session_bus()` and `start_system_bus()` for this, in a - `DBusTestCase` class (subclass of the standard `unittest.TestCase`). - - You can use this with any programming language, as you can run the - mocker as a normal program. The actual setup of the mock (adding - objects, methods, properties, and signals) all happen via D-Bus methods - on the `org.freedesktop.DBus.Mock` interface. You just don't have the - convenience D-Bus launch API that way. - - ## Simple example in Python - - Picking up the above example about mocking upower's `Suspend()` method, - this is how you would set up a mock upower in your test case: - - ```python - import dbus - import dbusmock - - class TestMyProgram(dbusmock.DBusTestCase): - @classmethod - def setUpClass(cls): - cls.start_system_bus() - cls.dbus_con = cls.get_dbus(system_bus=True) - - def setUp(self): - self.p_mock = self.spawn_server('org.freedesktop.UPower', - '/org/freedesktop/UPower', - 'org.freedesktop.UPower', - system_bus=True, - stdout=subprocess.PIPE) - - # Get a proxy for the UPower object's Mock interface - self.dbus_upower_mock = dbus.Interface(self.dbus_con.get_object( - 'org.freedesktop.UPower', '/org/freedesktop/UPower'), - dbusmock.MOCK_IFACE) - - self.dbus_upower_mock.AddMethod('', 'Suspend', '', '', '') - - def tearDown(self): - self.p_mock.stdout.close() - self.p_mock.terminate() - self.p_mock.wait() - - def test_suspend_on_idle(self): - # run your program in a way that should trigger one suspend call - - # now check the log that we got one Suspend() call - self.assertRegex(self.p_mock.stdout.readline(), b'^[0-9.]+ Suspend$') - ``` - - Let's walk through: - - - We derive our tests from `dbusmock.DBusTestCase` instead of - `unittest.TestCase` directly, to make use of the convenience API - to start a local system bus. - - - `setUpClass()` starts a local system bus, and makes a connection - to it available to all methods as `dbus_con`. `True` means that we - connect to the system bus, not the session bus. We can use the - same bus for all tests, so doing this once in `setUpClass()` - instead of `setUp()` is enough. - - - `setUp()` spawns the mock D-Bus server process for an initial - `/org/freedesktop/UPower` object with an `org.freedesktop.UPower` - D-Bus interface on the system bus. We capture its stdout to be - able to verify that methods were called. - - We then call `org.freedesktop.DBus.Mock.AddMethod()` to add a - `Suspend()` method to our new object to the default D-Bus - interface. This will not do anything (except log its call to - stdout). It takes no input arguments, returns nothing, and does - not run any custom code. - - - `tearDown()` stops our mock D-Bus server again. We do this so that - each test case has a fresh and clean upower instance, but of - course you can also set up everything in `setUpClass()` if tests - do not interfere with each other on setting up the mock. - - - `test_suspend_on_idle()` is the actual test case. It needs to run - your program in a way that should trigger one suspend call. Your - program will try to call `Suspend()`, but as that's now being - served by our mock instead of upower, there will not be any actual - machine suspend. Our mock process will log the method call - together with a time stamp; you can use the latter for doing - timing related tests, but we just ignore it here. - - ## Simple example from shell - - We use the actual session bus for this example. You can use - `dbus-run-session` to start a private one as well if you want, but that - is not part of the actual mocking. - - So let's start a mock at the D-Bus name `com.example.Foo` with an - initial "main" object on path /, with the main D-Bus interface - `com.example.Foo.Manager`: - - python3 -m dbusmock com.example.Foo / com.example.Foo.Manager - - On another terminal, let's first see what it does: - - gdbus introspect --session -d com.example.Foo -o / - - You'll see that it supports the standard D-Bus `Introspectable` and - `Properties` interfaces, as well as the `org.freedesktop.DBus.Mock` - interface for controlling the mock, but no "real" functionality yet. - So let's add a method: - - gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod '' Ping '' '' '' - - Now you can see the new method in `introspect`, and call it: - - gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Ping - - The mock process in the other terminal will log the method call with a - time stamp, and you'll see something like `1348832614.970 Ping`. - - Now add another method with two int arguments and a return value and - call it: - - gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod \ - '' Add 'ii' 'i' 'ret = args[0] + args[1]' - gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Add 2 3 - - This will print `(5,)` as expected (remember that the return value is - always a tuple), and again the mock process will log the Add method - call. - - You can do the same operations in e. g. d-feet or any other D-Bus - language binding. - - ## Logging - - Usually you want to verify which methods have been called on the mock - with which arguments. There are three ways to do that: - - - By default, the mock process writes the call log to stdout. - - You can call the mock process with the `-l`/`--logfile` argument, - or specify a log file object in the `spawn_server()` method if you - are using Python. - - You can use the `GetCalls()`, `GetMethodCalls()` and - `ClearCalls()` methods on the `org.freedesktop.DBus.Mock` D-Bus - interface to get an array of tuples describing the calls. - - ## Templates - - Some D-Bus services are commonly used in test suites, such as UPower or - NetworkManager. python-dbusmock provides "templates" which set up the - common structure of these services (their main objects, properties, and - methods) so that you do not need to carry around this common code, and - only need to set up the particular properties and specific D-Bus objects - that you need. These templates can be parameterized for common - customizations, and they can provide additional convenience methods on - the `org.freedesktop.DBus.Mock` interface to provide more abstract - functionality like "add a battery". - - For example, for starting a server with the `upower` template in - Python you can run - - (self.p_mock, self.obj_upower) = self.spawn_server_template( - 'upower', {'OnBattery': True}, stdout=subprocess.PIPE) - - or load a template into an already running server with the - `AddTemplate()` method; this is particularly useful if you are not using - Python: - - python3 -m dbusmock --system org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower - - gdbus call --system -d org.freedesktop.UPower -o /org/freedesktop/UPower -m org.freedesktop.DBus.Mock.AddTemplate 'upower' '{"OnBattery": }' - - This creates all expected properties such as `DaemonVersion`, and - changes the default for one of them (`OnBattery`) through the (optional) - parameters dict. - - If you do not need to specify parameters, you can do this in a simpler - way with - - python3 -m dbusmock --template upower - - The template does not create any devices by default. You can add some - with the template's convenience methods like - - ac_path = self.dbusmock.AddAC('mock_AC', 'Mock AC') - bt_path = self.dbusmock.AddChargingBattery('mock_BAT', 'Mock Battery', 30.0, 1200) - - or calling `AddObject()` yourself with the desired properties, of - course. - - Templates commonly implement some non-trivial functionality with actual Python - methods and the standard [dbus-python](https://dbus.freedesktop.org/doc/dbus-python/) - [`@dbus.service.method`](https://dbus.freedesktop.org/doc/dbus-python/dbus.service.html#dbus.service.method) - decorator. - - If you want to contribute a template, look at - dbusmock/templates/upower.py for a real-life implementation. You can - copy dbusmock/templates/SKELETON to your new template file name and - replace `CHANGEME` with the actual code/values. - - ## More Examples - - Have a look at the test suite for two real-live use cases: - - - `tests/test_upower.py` simulates upowerd, in a more complete way - than in above example and using the `upower` template. It verifies - that `upower --dump` is convinced that it's talking to upower. - - `tests/test_api.py` runs a mock on the session bus and exercises - all available functionality, such as adding additional objects, - properties, multiple methods, input arguments, return values, code - in methods, sending signals, raising exceptions, and introspection. - - ## Documentation - - The `dbusmock` module has extensive documentation built in, which you - can read with e. g. `pydoc3 dbusmock`. - - `pydoc3 dbusmock.DBusMockObject` shows the D-Bus API of the mock object, - i. e. methods like `AddObject()`, `AddMethod()` etc. which are used to - set up your mock object. - - `pydoc3 dbusmock.DBusTestCase` shows the convenience Python API for - writing test cases with local private session/system buses and launching - the server. - - `pydoc3 dbusmock.templates` shows all available templates. - - `pydoc3 dbusmock.templates.NAME` shows the documentation and available - parameters for the `NAME` template. - - `python3 -m dbusmock --help` shows the arguments and options for running - the mock server as a program. - - ## Development - - python-dbusmock is hosted on https://github.com/martinpitt/python-dbusmock - - Run the unit tests with - - python3 -m unittest - Platform: UNKNOWN Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+) Classifier: Programming Language :: Python :: 3 @@ -293,3 +20,279 @@ Classifier: Topic :: Software Development :: Testing :: Unit Classifier: Topic :: Software Development :: Libraries :: Python Modules Description-Content-Type: text/markdown +License-File: COPYING + +python-dbusmock +=============== + +## Purpose + +With this program/Python library you can easily create mock objects on +D-Bus. This is useful for writing tests for software which talks to +D-Bus services such as upower, systemd, logind, gnome-session or others, +and it is hard (or impossible without root privileges) to set the state +of the real services to what you expect in your tests. + +Suppose you want to write tests for gnome-settings-daemon's power +plugin, or another program that talks to upower. You want to verify that +after the configured idle time the program suspends the machine. So your +program calls `org.freedesktop.UPower.Suspend()` on the system D-Bus. + +Now, your test suite should not really talk to the actual system D-Bus +and the real upower; a `make check` that suspends your machine will not +be considered very friendly by most people, and if you want to run this +in continuous integration test servers or package build environments, +chances are that your process does not have the privilege to suspend, or +there is no system bus or upower to begin with. Likewise, there is no +way for an user process to forcefully set the system/seat idle flag in +logind, so your tests cannot set up the expected test environment on the +real daemon. + +That's where mock objects come into play: They look like the real API +(or at least the parts that you actually need), but they do not actually +do anything (or only some action that you specify yourself). You can +configure their state, behaviour and responses as you like in your test, +without making any assumptions about the real system status. + +When using a local system/session bus, you can do unit or integration +testing without needing root privileges or disturbing a running system. +The Python API offers some convenience functions like +`start_session_bus()` and `start_system_bus()` for this, in a +`DBusTestCase` class (subclass of the standard `unittest.TestCase`). + +You can use this with any programming language, as you can run the +mocker as a normal program. The actual setup of the mock (adding +objects, methods, properties, and signals) all happen via D-Bus methods +on the `org.freedesktop.DBus.Mock` interface. You just don't have the +convenience D-Bus launch API that way. + +## Simple example in Python + +Picking up the above example about mocking upower's `Suspend()` method, +this is how you would set up a mock upower in your test case: + +```python +import dbus +import dbusmock + +class TestMyProgram(dbusmock.DBusTestCase): + @classmethod + def setUpClass(cls): + cls.start_system_bus() + cls.dbus_con = cls.get_dbus(system_bus=True) + + def setUp(self): + self.p_mock = self.spawn_server('org.freedesktop.UPower', + '/org/freedesktop/UPower', + 'org.freedesktop.UPower', + system_bus=True, + stdout=subprocess.PIPE) + + # Get a proxy for the UPower object's Mock interface + self.dbus_upower_mock = dbus.Interface(self.dbus_con.get_object( + 'org.freedesktop.UPower', '/org/freedesktop/UPower'), + dbusmock.MOCK_IFACE) + + self.dbus_upower_mock.AddMethod('', 'Suspend', '', '', '') + + def tearDown(self): + self.p_mock.stdout.close() + self.p_mock.terminate() + self.p_mock.wait() + + def test_suspend_on_idle(self): + # run your program in a way that should trigger one suspend call + + # now check the log that we got one Suspend() call + self.assertRegex(self.p_mock.stdout.readline(), b'^[0-9.]+ Suspend$') +``` + +Let's walk through: + + - We derive our tests from `dbusmock.DBusTestCase` instead of + `unittest.TestCase` directly, to make use of the convenience API + to start a local system bus. + + - `setUpClass()` starts a local system bus, and makes a connection + to it available to all methods as `dbus_con`. `True` means that we + connect to the system bus, not the session bus. We can use the + same bus for all tests, so doing this once in `setUpClass()` + instead of `setUp()` is enough. + + - `setUp()` spawns the mock D-Bus server process for an initial + `/org/freedesktop/UPower` object with an `org.freedesktop.UPower` + D-Bus interface on the system bus. We capture its stdout to be + able to verify that methods were called. + + We then call `org.freedesktop.DBus.Mock.AddMethod()` to add a + `Suspend()` method to our new object to the default D-Bus + interface. This will not do anything (except log its call to + stdout). It takes no input arguments, returns nothing, and does + not run any custom code. + + - `tearDown()` stops our mock D-Bus server again. We do this so that + each test case has a fresh and clean upower instance, but of + course you can also set up everything in `setUpClass()` if tests + do not interfere with each other on setting up the mock. + + - `test_suspend_on_idle()` is the actual test case. It needs to run + your program in a way that should trigger one suspend call. Your + program will try to call `Suspend()`, but as that's now being + served by our mock instead of upower, there will not be any actual + machine suspend. Our mock process will log the method call + together with a time stamp; you can use the latter for doing + timing related tests, but we just ignore it here. + +## Simple example from shell + +We use the actual session bus for this example. You can use +`dbus-run-session` to start a private one as well if you want, but that +is not part of the actual mocking. + +So let's start a mock at the D-Bus name `com.example.Foo` with an +initial "main" object on path /, with the main D-Bus interface +`com.example.Foo.Manager`: + + python3 -m dbusmock com.example.Foo / com.example.Foo.Manager + +On another terminal, let's first see what it does: + + gdbus introspect --session -d com.example.Foo -o / + +You'll see that it supports the standard D-Bus `Introspectable` and +`Properties` interfaces, as well as the `org.freedesktop.DBus.Mock` +interface for controlling the mock, but no "real" functionality yet. +So let's add a method: + + gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod '' Ping '' '' '' + +Now you can see the new method in `introspect`, and call it: + + gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Ping + +The mock process in the other terminal will log the method call with a +time stamp, and you'll see something like `1348832614.970 Ping`. + +Now add another method with two int arguments and a return value and +call it: + + gdbus call --session -d com.example.Foo -o / -m org.freedesktop.DBus.Mock.AddMethod \ + '' Add 'ii' 'i' 'ret = args[0] + args[1]' + gdbus call --session -d com.example.Foo -o / -m com.example.Foo.Manager.Add 2 3 + +This will print `(5,)` as expected (remember that the return value is +always a tuple), and again the mock process will log the Add method +call. + +You can do the same operations in e. g. d-feet or any other D-Bus +language binding. + +## Logging + +Usually you want to verify which methods have been called on the mock +with which arguments. There are three ways to do that: + + - By default, the mock process writes the call log to stdout. + - You can call the mock process with the `-l`/`--logfile` argument, + or specify a log file object in the `spawn_server()` method if you + are using Python. + - You can use the `GetCalls()`, `GetMethodCalls()` and + `ClearCalls()` methods on the `org.freedesktop.DBus.Mock` D-Bus + interface to get an array of tuples describing the calls. + +## Templates + +Some D-Bus services are commonly used in test suites, such as UPower or +NetworkManager. python-dbusmock provides "templates" which set up the +common structure of these services (their main objects, properties, and +methods) so that you do not need to carry around this common code, and +only need to set up the particular properties and specific D-Bus objects +that you need. These templates can be parameterized for common +customizations, and they can provide additional convenience methods on +the `org.freedesktop.DBus.Mock` interface to provide more abstract +functionality like "add a battery". + +For example, for starting a server with the `upower` template in +Python you can run + + (self.p_mock, self.obj_upower) = self.spawn_server_template( + 'upower', {'OnBattery': True}, stdout=subprocess.PIPE) + +or load a template into an already running server with the +`AddTemplate()` method; this is particularly useful if you are not using +Python: + + python3 -m dbusmock --system org.freedesktop.UPower /org/freedesktop/UPower org.freedesktop.UPower + + gdbus call --system -d org.freedesktop.UPower -o /org/freedesktop/UPower -m org.freedesktop.DBus.Mock.AddTemplate 'upower' '{"OnBattery": }' + +This creates all expected properties such as `DaemonVersion`, and +changes the default for one of them (`OnBattery`) through the (optional) +parameters dict. + +If you do not need to specify parameters, you can do this in a simpler +way with + + python3 -m dbusmock --template upower + +The template does not create any devices by default. You can add some +with the template's convenience methods like + + ac_path = self.dbusmock.AddAC('mock_AC', 'Mock AC') + bt_path = self.dbusmock.AddChargingBattery('mock_BAT', 'Mock Battery', 30.0, 1200) + +or calling `AddObject()` yourself with the desired properties, of +course. + +Templates commonly implement some non-trivial functionality with actual Python +methods and the standard [dbus-python](https://dbus.freedesktop.org/doc/dbus-python/) +[`@dbus.service.method`](https://dbus.freedesktop.org/doc/dbus-python/dbus.service.html#dbus.service.method) +decorator. + +If you want to contribute a template, look at +dbusmock/templates/upower.py for a real-life implementation. You can +copy dbusmock/templates/SKELETON to your new template file name and +replace `CHANGEME` with the actual code/values. + +## More Examples + +Have a look at the test suite for two real-live use cases: + + - `tests/test_upower.py` simulates upowerd, in a more complete way + than in above example and using the `upower` template. It verifies + that `upower --dump` is convinced that it's talking to upower. + - `tests/test_api.py` runs a mock on the session bus and exercises + all available functionality, such as adding additional objects, + properties, multiple methods, input arguments, return values, code + in methods, sending signals, raising exceptions, and introspection. + +## Documentation + +The `dbusmock` module has extensive documentation built in, which you +can read with e. g. `pydoc3 dbusmock`. + +`pydoc3 dbusmock.DBusMockObject` shows the D-Bus API of the mock object, +i. e. methods like `AddObject()`, `AddMethod()` etc. which are used to +set up your mock object. + +`pydoc3 dbusmock.DBusTestCase` shows the convenience Python API for +writing test cases with local private session/system buses and launching +the server. + +`pydoc3 dbusmock.templates` shows all available templates. + +`pydoc3 dbusmock.templates.NAME` shows the documentation and available +parameters for the `NAME` template. + +`python3 -m dbusmock --help` shows the arguments and options for running +the mock server as a program. + +## Development + +python-dbusmock is hosted on https://github.com/martinpitt/python-dbusmock + +Run the unit tests with + + python3 -m unittest + + diff -Nru python-dbusmock-0.28.4/python_dbusmock.egg-info/SOURCES.txt python-dbusmock-0.28.6/python_dbusmock.egg-info/SOURCES.txt --- python-dbusmock-0.28.4/python_dbusmock.egg-info/SOURCES.txt 2022-07-19 12:33:07.000000000 +0000 +++ python-dbusmock-0.28.6/python_dbusmock.egg-info/SOURCES.txt 2022-10-12 05:10:38.000000000 +0000 @@ -1,15 +1,22 @@ +.flake8 +.gitignore COPYING -MANIFEST.in NEWS README.md +packit.yaml pyproject.toml setup.cfg setup.py .fmf/version +.github/release.eloquent.yml +.github/workflows/release.yml +.github/workflows/tests.yml dbusmock/__init__.py dbusmock/__main__.py +dbusmock/_version.py dbusmock/mockobject.py dbusmock/testcase.py +dbusmock/templates/SKELETON dbusmock/templates/__init__.py dbusmock/templates/bluez5-obex.py dbusmock/templates/bluez5.py @@ -26,6 +33,7 @@ dbusmock/templates/timedated.py dbusmock/templates/upower.py dbusmock/templates/urfkill.py +packaging/python-dbusmock.spec plans/all.fmf python_dbusmock.egg-info/PKG-INFO python_dbusmock.egg-info/SOURCES.txt @@ -34,6 +42,11 @@ python_dbusmock.egg-info/top_level.txt tests/__init__.py tests/main.fmf +tests/run +tests/run-centos +tests/run-debian +tests/run-fedora +tests/run-ubuntu tests/test_api.py tests/test_bluez5.py tests/test_cli.py diff -Nru python-dbusmock-0.28.4/tests/run python-dbusmock-0.28.6/tests/run --- python-dbusmock-0.28.4/tests/run 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/tests/run 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,18 @@ +#!/bin/sh +set -eux +IMAGE="$1" + +if type podman >/dev/null 2>&1; then + RUNC=podman +else + RUNC="sudo docker" +fi + +# only run pylint on a single release, too annoying to keep the code compatible with multiple versions +if [ "${IMAGE%fedora:latest}" != "$IMAGE" ]; then + TEST_CODE="1" +fi + +OS=${IMAGE##*/} +OS=${OS%:*} +$RUNC run --interactive -e DEBUG=${DEBUG:-} -e TEST_CODE="${TEST_CODE:-}" --rm ${RUNC_OPTIONS:-} --volume `pwd`:/source:ro --workdir /source "$IMAGE" /bin/sh tests/run-$OS diff -Nru python-dbusmock-0.28.4/tests/run-centos python-dbusmock-0.28.6/tests/run-centos --- python-dbusmock-0.28.4/tests/run-centos 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/tests/run-centos 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,26 @@ +#!/bin/sh +set -eux +# install build dependencies +dnf -y install python3-setuptools python3 python3-gobject-base \ + python3-dbus dbus-x11 util-linux \ + upower NetworkManager bluez libnotify polkit + +if ! grep -q :el8 /etc/os-release; then + dnf -y install python3-flake8 python3-pylint python3-mypy \ + power-profiles-daemon iio-sensor-proxy +fi + +# systemd's tools otherwise fail on "not been booted with systemd" +mkdir -p /run/systemd/system + +# run build and test as user +useradd build +su -s /bin/sh - build << EOF +set -ex +cd /source +export TEST_CODE="$TEST_CODE" +python3 -m unittest -v || { + [ -z "$DEBUG" ] || sleep infinity + exit 1 +} +EOF diff -Nru python-dbusmock-0.28.4/tests/run-debian python-dbusmock-0.28.6/tests/run-debian --- python-dbusmock-0.28.4/tests/run-debian 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/tests/run-debian 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,53 @@ +#!/bin/sh +set -eux + +# go-faster apt +echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/90nolanguages + +# upgrade +export DEBIAN_FRONTEND=noninteractive +apt-get update +apt-get install -y eatmydata +eatmydata apt-get -y --purge dist-upgrade + +# install build dependencies +eatmydata apt-get install --no-install-recommends -y git \ + python3-all python3-setuptools python3-setuptools-scm python3-build python3-venv \ + python3-dbus python3-gi gir1.2-glib-2.0 \ + dbus libnotify-bin upower network-manager bluez ofono ofono-scripts + +# systemd's tools otherwise fail on "not been booted with systemd" +mkdir -p /run/systemd/system + +# run build and test as user +useradd build +su -s /bin/sh - build << EOF || { [ -z "$DEBUG" ] || sleep infinity; exit 1; } +set -ex +export TEST_CODE="$TEST_CODE" +cp -r $(pwd) /tmp/source +cd /tmp/source +python3 -m unittest -v +# massively parallel test to check for races +for i in \$(seq 100); do + ( PYTHONPATH=. python3 tests/test_api.py TestTemplates || touch /tmp/fail ) & +done +wait +[ ! -e /tmp/fail ] + +my_version=\$(git describe --abbrev=0) + +# test sdist with direct setuptools +./setup.py sdist +tar --wildcards --strip-components=1 -xvf dist/python-dbusmock-\${my_version}*.tar.gz '*/PKG-INFO' +grep "^Version: \${my_version}" PKG-INFO +grep "^## Purpose" PKG-INFO +git clean -ffdx + +# test sdist with PyPA build; note https://bugs.debian.org/1009916 +if dpkg --compare-versions \$(dpkg-query -f '\${Version}' --show python3-build) '>=' 0.7.0-3; then + python3 -m build --sdist + tar --wildcards --strip-components=1 -xvf dist/python-dbusmock-\${my_version}*.tar.gz '*/PKG-INFO' + grep "^Version: \${my_version}" PKG-INFO + grep "^## Purpose" PKG-INFO +fi +EOF diff -Nru python-dbusmock-0.28.4/tests/run-fedora python-dbusmock-0.28.6/tests/run-fedora --- python-dbusmock-0.28.4/tests/run-fedora 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/tests/run-fedora 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,26 @@ +#!/bin/sh +set -eux +# install build dependencies +dnf -y install python3-setuptools python3 python3-gobject-base \ + python3-dbus dbus-x11 util-linux \ + upower NetworkManager bluez libnotify polkit + +if ! grep -q :el8 /etc/os-release; then + dnf -y install python3-flake8 python3-pylint python3-mypy \ + power-profiles-daemon iio-sensor-proxy +fi + +# systemd's tools otherwise fail on "not been booted with systemd" +mkdir -p /run/systemd/system + +# run build and test as user +useradd build +su -s /bin/sh - build << EOF +set -ex +cd /source +export TEST_CODE="$TEST_CODE" +python3 -m unittest -v || { + [ -z "$DEBUG" ] || sleep infinity + exit 1 +} +EOF diff -Nru python-dbusmock-0.28.4/tests/run-ubuntu python-dbusmock-0.28.6/tests/run-ubuntu --- python-dbusmock-0.28.4/tests/run-ubuntu 1970-01-01 00:00:00.000000000 +0000 +++ python-dbusmock-0.28.6/tests/run-ubuntu 2022-10-12 05:10:28.000000000 +0000 @@ -0,0 +1,53 @@ +#!/bin/sh +set -eux + +# go-faster apt +echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/90nolanguages + +# upgrade +export DEBIAN_FRONTEND=noninteractive +apt-get update +apt-get install -y eatmydata +eatmydata apt-get -y --purge dist-upgrade + +# install build dependencies +eatmydata apt-get install --no-install-recommends -y git \ + python3-all python3-setuptools python3-setuptools-scm python3-build python3-venv \ + python3-dbus python3-gi gir1.2-glib-2.0 \ + dbus libnotify-bin upower network-manager bluez ofono ofono-scripts + +# systemd's tools otherwise fail on "not been booted with systemd" +mkdir -p /run/systemd/system + +# run build and test as user +useradd build +su -s /bin/sh - build << EOF || { [ -z "$DEBUG" ] || sleep infinity; exit 1; } +set -ex +export TEST_CODE="$TEST_CODE" +cp -r $(pwd) /tmp/source +cd /tmp/source +python3 -m unittest -v +# massively parallel test to check for races +for i in \$(seq 100); do + ( PYTHONPATH=. python3 tests/test_api.py TestTemplates || touch /tmp/fail ) & +done +wait +[ ! -e /tmp/fail ] + +my_version=\$(git describe --abbrev=0) + +# test sdist with direct setuptools +./setup.py sdist +tar --wildcards --strip-components=1 -xvf dist/python-dbusmock-\${my_version}*.tar.gz '*/PKG-INFO' +grep "^Version: \${my_version}" PKG-INFO +grep "^## Purpose" PKG-INFO +git clean -ffdx + +# test sdist with PyPA build; note https://bugs.debian.org/1009916 +if dpkg --compare-versions \$(dpkg-query -f '\${Version}' --show python3-build) '>=' 0.7.0-3; then + python3 -m build --sdist + tar --wildcards --strip-components=1 -xvf dist/python-dbusmock-\${my_version}*.tar.gz '*/PKG-INFO' + grep "^Version: \${my_version}" PKG-INFO + grep "^## Purpose" PKG-INFO +fi +EOF diff -Nru python-dbusmock-0.28.4/tests/test_api.py python-dbusmock-0.28.6/tests/test_api.py --- python-dbusmock-0.28.4/tests/test_api.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_api.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,17 +7,21 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' -import unittest -import sys +import importlib.util import os -import tempfile -import subprocess import shutil +import subprocess +import sys +import tempfile import time -import importlib.util import tracemalloc +import unittest +from pathlib import Path import dbus import dbus.mainloop.glib @@ -55,8 +59,7 @@ self.dbus_props = dbus.Interface(self.obj_test, dbus.PROPERTIES_IFACE) def assertLog(self, regex): - with open(self.mock_log.name, "rb") as f: - self.assertRegex(f.read(), regex) + self.assertRegex(Path(self.mock_log.name,).read_bytes(), regex) def tearDown(self): if self.p_mock.stdout: @@ -335,12 +338,11 @@ self.assertEqual(self.dbus_props.Get('org.freedesktop.Test.Main', 'version'), 4) # check that the Get/Set calls get logged - with open(self.mock_log.name, encoding="UTF-8") as f: - contents = f.read() - self.assertRegex(contents, '\n[0-9.]+ Get / org.freedesktop.Test.Main.version\n') - self.assertRegex(contents, '\n[0-9.]+ Get / org.freedesktop.Test.Main.connected\n') - self.assertRegex(contents, '\n[0-9.]+ GetAll / org.freedesktop.Test.Main\n') - self.assertRegex(contents, '\n[0-9.]+ Set / org.freedesktop.Test.Main.version 4\n') + log = Path(self.mock_log.name).read_text("UTF-8") + self.assertRegex(log, '\n[0-9.]+ Get / org.freedesktop.Test.Main.version\n') + self.assertRegex(log, '\n[0-9.]+ Get / org.freedesktop.Test.Main.connected\n') + self.assertRegex(log, '\n[0-9.]+ GetAll / org.freedesktop.Test.Main\n') + self.assertRegex(log, '\n[0-9.]+ Set / org.freedesktop.Test.Main.version 4\n') # add property to different interface self.dbus_mock.AddProperty('org.freedesktop.Test.Other', @@ -463,6 +465,8 @@ def test_signals(self): '''emitting signals''' + self.dbus_mock.AddObject('/obj1', 'org.freedesktop.Test.Sub', {}, []) + def do_emit(): self.dbus_mock.EmitSignal('', 'SigNoArgs', '', []) self.dbus_mock.EmitSignal('org.freedesktop.Test.Sub', @@ -476,6 +480,10 @@ 'SigDetailed', 'su', ['details', 123], {'destination': self.dbus_con.get_unique_name()}) + self.dbus_mock.EmitSignalDetailed('', + 'SigDetailedWithPath', + 'su', ['details', 456], + {'path': '/obj1'}) caught = [] ml = GLib.MainLoop() @@ -483,7 +491,7 @@ def catch(*args, **kwargs): if kwargs['interface'].startswith('org.freedesktop.Test'): caught.append((args, kwargs)) - if len(caught) == 4: + if len(caught) == 5: # we caught everything there is to catch, don't wait for the # timeout ml.quit() @@ -538,14 +546,19 @@ self.assertEqual(caught[3][1]['path'], '/') self.assertEqual(caught[3][1]['interface'], 'org.freedesktop.Test.Main') + self.assertEqual(caught[4][0], ('details', 456)) + self.assertEqual(caught[4][1]['member'], 'SigDetailedWithPath') + self.assertEqual(caught[4][1]['path'], '/obj1') + self.assertEqual(caught[4][1]['interface'], 'org.freedesktop.Test.Main') + # check correct logging - with open(self.mock_log.name, encoding="UTF-8") as f: - log = f.read() + log = Path(self.mock_log.name).read_text("UTF-8") self.assertRegex(log, '[0-9.]+ emit / org.freedesktop.Test.Main.SigNoArgs\n') self.assertRegex(log, '[0-9.]+ emit / org.freedesktop.Test.Sub.SigTwoArgs "hello" 42\n') self.assertRegex(log, '[0-9.]+ emit / org.freedesktop.Test.Sub.SigTypeTest -42 42') self.assertRegex(log, r'[0-9.]+ emit / org.freedesktop.Test.Sub.SigTypeTest -42 42 "hello" \["/a", "/b"\]\n') self.assertRegex(log, '[0-9.]+ emit / org.freedesktop.Test.Main.SigDetailed "details" 123\n') + self.assertRegex(log, '[0-9.]+ emit /obj1 org.freedesktop.Test.Main.SigDetailedWithPath "details" 456\n') def test_signals_type_mismatch(self): '''emitting signals with wrong arguments''' @@ -667,6 +680,9 @@ obj1 = self.dbus_con.get_object('org.freedesktop.Test', '/obj1') self.assertRaises(dbus.exceptions.DBusException, obj1.GetAll, '') + def test_version(self): + self.assertGreater(dbusmock.__version__, "0.28.0") + class TestTemplates(dbusmock.DBusTestCase): '''Test template API''' @@ -698,8 +714,8 @@ # ensure that we don't use/write any .pyc files, they are dangerous # in a world-writable directory like /tmp - self.assertFalse(os.path.exists(my_template.name + 'c')) - self.assertFalse(os.path.exists(importlib.util.cache_from_source(my_template.name))) + self.assertFalse(Path(my_template.name + 'c').exists()) + self.assertFalse(Path(importlib.util.cache_from_source(my_template.name)).exists()) loop = GLib.MainLoop() caught_signals = [] @@ -997,27 +1013,27 @@ os.environ['XDG_DATA_DIRS'] = cls.xdg_data_dir - os.mkdir(os.path.join(cls.xdg_data_dir, 'dbus-1')) - system_dir = os.path.join(cls.xdg_data_dir, 'dbus-1', 'system-services') - session_dir = os.path.join(cls.xdg_data_dir, 'dbus-1', 'services') - os.mkdir(system_dir) - os.mkdir(session_dir) - - with open(os.path.join(system_dir, 'org.TestSystem.service'), 'w', encoding='ascii') as s: - s.write('[D-BUS Service]\n' + - 'Name=org.TestSystem\n' - 'Exec=/usr/bin/python3 -c "import sys; from gi.repository import GLib, Gio; ' - ' Gio.bus_own_name(Gio.BusType.SYSTEM, \'org.TestSystem\', 0, None, None, lambda *args: sys.exit(0)); ' - ' GLib.MainLoop().run()"\n' - 'User=root') - - with open(os.path.join(session_dir, 'org.TestSession.service'), 'w', encoding='ascii') as s: - s.write('[D-BUS Service]\n' - 'Name=org.TestSession\n' - 'Exec=/usr/bin/python3 -c "import sys; from gi.repository import GLib, Gio; ' - ' Gio.bus_own_name(Gio.BusType.SESSION, \'org.TestSession\', 0, None, None, lambda *args: sys.exit(0)); ' - ' GLib.MainLoop().run()"\n' - 'User=root') + dbus_dir = Path(cls.xdg_data_dir, 'dbus-1') + system_dir = dbus_dir / 'system-services' + session_dir = dbus_dir / 'services' + system_dir.mkdir(parents=True) + session_dir.mkdir() + + (system_dir / 'org.TestSystem.service').write_text( + '[D-BUS Service]\n' + + 'Name=org.TestSystem\n' + 'Exec=/usr/bin/python3 -c "import sys; from gi.repository import GLib, Gio; ' + ' Gio.bus_own_name(Gio.BusType.SYSTEM, \'org.TestSystem\', 0, None, None, lambda *args: sys.exit(0)); ' + ' GLib.MainLoop().run()"\n' + 'User=root') + + (session_dir / 'org.TestSession.service').write_text( + '[D-BUS Service]\n' + 'Name=org.TestSession\n' + 'Exec=/usr/bin/python3 -c "import sys; from gi.repository import GLib, Gio; ' + ' Gio.bus_own_name(Gio.BusType.SESSION, \'org.TestSession\', 0, None, None, lambda *args: sys.exit(0)); ' + ' GLib.MainLoop().run()"\n' + 'User=root') cls.start_system_bus() cls.start_session_bus() @@ -1073,9 +1089,6 @@ dbus_if.StartServiceByName('org.TestSystem', 0) - def test_version(self): - self.assertGreater(dbusmock.__version__, "0.28.0") - if __name__ == '__main__': # avoid writing to stderr diff -Nru python-dbusmock-0.28.4/tests/test_bluez5.py python-dbusmock-0.28.6/tests/test_bluez5.py --- python-dbusmock-0.28.4/tests/test_bluez5.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_bluez5.py 2022-10-12 05:10:28.000000000 +0000 @@ -8,7 +8,10 @@ # of the license. __author__ = 'Philip Withnall' -__copyright__ = '(c) 2013 Collabora Ltd.' +__copyright__ = ''' +(c) 2013 Collabora Ltd. +(c) 2017 - 2022 Martin Pitt +''' import os @@ -16,8 +19,9 @@ import subprocess import sys import time -import unittest import tracemalloc +import unittest +from pathlib import Path import dbus import dbus.mainloop.glib @@ -243,20 +247,19 @@ obj = bus.get_object('org.bluez.obex', path) transfer = dbus.Interface(obj, 'org.bluez.obex.transfer1.Mock') - with open(transfer_filename, 'wb') as f: - f.write( - b'BEGIN:VCARD\r\n' + - b'VERSION:3.0\r\n' + - b'FN:Forrest Gump\r\n' + - b'TEL;TYPE=WORK,VOICE:(111) 555-1212\r\n' + - b'TEL;TYPE=HOME,VOICE:(404) 555-1212\r\n' + - b'EMAIL;TYPE=PREF,INTERNET:forrestgump@example.com\r\n' + - b'EMAIL:test@example.com\r\n' + - b'URL;TYPE=HOME:http://example.com/\r\n' + - b'URL:http://forest.com/\r\n' + - b'URL:https://test.com/\r\n' + - b'END:VCARD\r\n' - ) + Path(transfer_filename).write_bytes( + b'BEGIN:VCARD\r\n' + + b'VERSION:3.0\r\n' + + b'FN:Forrest Gump\r\n' + + b'TEL;TYPE=WORK,VOICE:(111) 555-1212\r\n' + + b'TEL;TYPE=HOME,VOICE:(404) 555-1212\r\n' + + b'EMAIL;TYPE=PREF,INTERNET:forrestgump@example.com\r\n' + + b'EMAIL:test@example.com\r\n' + + b'URL;TYPE=HOME:http://example.com/\r\n' + + b'URL:http://forest.com/\r\n' + + b'URL:https://test.com/\r\n' + + b'END:VCARD\r\n' + ) transfer.UpdateStatus(True) transferred_files.append(transfer_filename) diff -Nru python-dbusmock-0.28.4/tests/test_cli.py python-dbusmock-0.28.6/tests/test_cli.py --- python-dbusmock-0.28.4/tests/test_cli.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_cli.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,16 +7,19 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import importlib.util -import os -import unittest import shutil -import sys import subprocess +import sys import tempfile import tracemalloc +import unittest +from pathlib import Path import dbus @@ -72,7 +75,7 @@ def test_template_upower_explicit_path(self): spec = importlib.util.find_spec('dbusmock.templates.upower') - self.assertTrue(os.path.exists(spec.origin)) + self.assertTrue(Path(spec.origin).exists()) self.start_mock(['-t', spec.origin], 'org.freedesktop.UPower', '/org/freedesktop/UPower', True) self.check_upower_running() diff -Nru python-dbusmock-0.28.4/tests/test_code.py python-dbusmock-0.28.6/tests/test_code.py --- python-dbusmock-0.28.4/tests/test_code.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_code.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,34 +7,23 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import glob +import os import subprocess import sys import unittest -checkers = {} -for checker in ['pycodestyle', 'pyflakes', 'pylint', 'mypy']: - try: - checkers[checker] = subprocess.check_output( - [sys.executable, '-m', checker, '--version'], stderr=subprocess.DEVNULL) - except subprocess.CalledProcessError: - pass - - +@unittest.skipUnless(os.getenv("TEST_CODE", None), "$TEST_CODE not set, not running static code checks") class StaticCodeTests(unittest.TestCase): - @unittest.skipUnless('pyflakes' in checkers, 'pyflakes3 not installed') - def test_pyflakes(self): # pylint: disable=no-self-use - subprocess.check_call([sys.executable, '-m', 'pyflakes', '.']) - - @unittest.skipUnless('pycodestyle' in checkers, 'pycodestyle not installed') - def test_codestyle(self): # pylint: disable=no-self-use - subprocess.check_call([sys.executable, '-m', 'pycodestyle', - '--max-line-length=130', '--ignore=E124,E402,E731,W504', '.']) + def test_flake8(self): # pylint: disable=no-self-use + subprocess.check_call(['flake8']) - @unittest.skipUnless('pylint' in checkers, 'pylint not installed') def test_pylint(self): # pylint: disable=no-self-use subprocess.check_call([sys.executable, '-m', 'pylint'] + glob.glob('dbusmock/*.py')) # signatures/arguments are not determined by us, docstrings are a bit pointless, and code repetition @@ -49,7 +38,6 @@ '--disable=too-many-public-methods,too-many-lines,too-many-statements,R0801', 'tests/']) - @unittest.skipUnless('mypy' in checkers, 'mypy not installed') def test_types(self): # pylint: disable=no-self-use subprocess.check_call([sys.executable, '-m', 'mypy', 'dbusmock/', 'tests/']) diff -Nru python-dbusmock-0.28.4/tests/test_gnome_screensaver.py python-dbusmock-0.28.6/tests/test_gnome_screensaver.py --- python-dbusmock-0.28.4/tests/test_gnome_screensaver.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_gnome_screensaver.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import unittest import os diff -Nru python-dbusmock-0.28.4/tests/test_iio_sensors_proxy.py python-dbusmock-0.28.6/tests/test_iio_sensors_proxy.py --- python-dbusmock-0.28.4/tests/test_iio_sensors_proxy.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_iio_sensors_proxy.py 2022-10-12 05:10:28.000000000 +0000 @@ -8,7 +8,10 @@ # of the license. __author__ = 'Marco Trevisan' -__copyright__ = '(c) 2021 Canonical Ltd.' +__copyright__ = ''' +(c) 2021 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import fcntl import os diff -Nru python-dbusmock-0.28.4/tests/test_logind.py python-dbusmock-0.28.6/tests/test_logind.py --- python-dbusmock-0.28.4/tests/test_logind.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_logind.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,15 +7,18 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' -import os import re import shutil import subprocess import sys -import unittest import tracemalloc +import unittest +from pathlib import Path import dbus import dbusmock @@ -25,7 +28,7 @@ @unittest.skipUnless(have_loginctl, 'loginctl not installed') -@unittest.skipUnless(os.path.exists('/run/systemd/system'), '/run/systemd/system does not exist') +@unittest.skipUnless(Path('/run/systemd/system').exists(), '/run/systemd/system does not exist') class TestLogind(dbusmock.DBusTestCase): '''Test mocking logind''' @@ -83,7 +86,7 @@ out = subprocess.check_output(['loginctl', 'list-users'], universal_newlines=True) - self.assertRegex(out, r'(^|\n)\s*500\s+joe\s*($|\n)') + self.assertRegex(out, r'(^|\n)\s*500\s+joe\s*') # note, this does an actual getpwnam() in the client, so we cannot call # this with hardcoded user names; get from actual user in the system diff -Nru python-dbusmock-0.28.4/tests/test_low_memory_monitor.py python-dbusmock-0.28.6/tests/test_low_memory_monitor.py --- python-dbusmock-0.28.4/tests/test_low_memory_monitor.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_low_memory_monitor.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Bastien Nocera' -__copyright__ = '(c) 2019 Red Hat Inc.' +__copyright__ = ''' +(c) 2019 Red Hat Inc. +(c) 2017 - 2022 Martin Pitt +''' import unittest import sys diff -Nru python-dbusmock-0.28.4/tests/test_networkmanager.py python-dbusmock-0.28.6/tests/test_networkmanager.py --- python-dbusmock-0.28.4/tests/test_networkmanager.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_networkmanager.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Iftikhar Ahmad' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import os import re diff -Nru python-dbusmock-0.28.4/tests/test_notification_daemon.py python-dbusmock-0.28.6/tests/test_notification_daemon.py --- python-dbusmock-0.28.4/tests/test_notification_daemon.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_notification_daemon.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import unittest import sys diff -Nru python-dbusmock-0.28.4/tests/test_ofono.py python-dbusmock-0.28.6/tests/test_ofono.py --- python-dbusmock-0.28.4/tests/test_ofono.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_ofono.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,19 +7,23 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' -import unittest -import sys -import subprocess import os +import subprocess +import sys +import unittest +from pathlib import Path import dbus import dbusmock -script_dir = os.environ.get('OFONO_SCRIPT_DIR', '/usr/share/ofono/scripts') +script_dir = Path(os.environ.get('OFONO_SCRIPT_DIR', '/usr/share/ofono/scripts')) -have_scripts = os.access(os.path.join(script_dir, 'list-modems'), os.X_OK) +have_scripts = os.access(script_dir / 'list-modems', os.X_OK) @unittest.skipUnless(have_scripts, @@ -40,7 +44,7 @@ def test_list_modems(self): '''Manager.GetModems()''' - out = subprocess.check_output([os.path.join(script_dir, 'list-modems')]) + out = subprocess.check_output([script_dir / 'list-modems']) self.assertTrue(out.startswith(b'[ /ril_0 ]'), out) self.assertIn(b'Powered = 1', out) self.assertIn(b'Online = 1', out) @@ -62,50 +66,49 @@ '''outgoing voice call''' # no calls by default - out = subprocess.check_output([os.path.join(script_dir, 'list-calls')]) + out = subprocess.check_output([script_dir / 'list-calls']) self.assertEqual(out, b'[ /ril_0 ]\n') # start call - out = subprocess.check_output([os.path.join(script_dir, 'dial-number'), '12345']) + out = subprocess.check_output([script_dir / 'dial-number', '12345']) self.assertEqual(out, b'Using modem /ril_0\n/ril_0/voicecall01\n') - out = subprocess.check_output([os.path.join(script_dir, 'list-calls')]) + out = subprocess.check_output([script_dir / 'list-calls']) self.assertIn(b'/ril_0/voicecall01', out) self.assertIn(b'LineIdentification = 12345', out) self.assertIn(b'State = dialing', out) - out = subprocess.check_output([os.path.join(script_dir, 'hangup-call'), + out = subprocess.check_output([script_dir / 'hangup-call', '/ril_0/voicecall01']) self.assertEqual(out, b'') # no active calls any more - out = subprocess.check_output([os.path.join(script_dir, 'list-calls')]) + out = subprocess.check_output([script_dir / 'list-calls']) self.assertEqual(out, b'[ /ril_0 ]\n') def test_hangup_all(self): '''multiple outgoing voice calls''' - out = subprocess.check_output([os.path.join(script_dir, 'dial-number'), '12345']) + out = subprocess.check_output([script_dir / 'dial-number', '12345']) self.assertEqual(out, b'Using modem /ril_0\n/ril_0/voicecall01\n') - out = subprocess.check_output([os.path.join(script_dir, 'dial-number'), '54321']) + out = subprocess.check_output([script_dir / 'dial-number', '54321']) self.assertEqual(out, b'Using modem /ril_0\n/ril_0/voicecall02\n') - out = subprocess.check_output([os.path.join(script_dir, 'list-calls')]) + out = subprocess.check_output([script_dir / 'list-calls']) self.assertIn(b'/ril_0/voicecall01', out) self.assertIn(b'/ril_0/voicecall02', out) self.assertIn(b'LineIdentification = 12345', out) self.assertIn(b'LineIdentification = 54321', out) - out = subprocess.check_output([os.path.join(script_dir, 'hangup-all')]) - out = subprocess.check_output([os.path.join(script_dir, 'list-calls')]) + out = subprocess.check_output([script_dir / 'hangup-all']) + out = subprocess.check_output([script_dir / 'list-calls']) self.assertEqual(out, b'[ /ril_0 ]\n') def test_list_operators(self): '''list operators''' - out = subprocess.check_output([os.path.join(script_dir, 'list-operators')], - universal_newlines=True) + out = subprocess.check_output([script_dir / 'list-operators'], universal_newlines=True) self.assertTrue(out.startswith('[ /ril_0 ]'), out) self.assertIn('[ /ril_0/operator/op1 ]', out) self.assertIn('Status = current', out) @@ -142,14 +145,14 @@ def test_second_modem(self): '''Add a second modem''' - out = subprocess.check_output([os.path.join(script_dir, 'list-modems')]) + out = subprocess.check_output([script_dir / 'list-modems']) self.assertIn(b'CardIdentifier = 893581234000000000000', out) self.assertIn(b'Serial = 12345678-1234-1234-1234-000000000000', out) self.assertIn(b'SubscriberIdentity = 310150000000000', out) self.obj_ofono.AddModem('sim2', {'Powered': True}) - out = subprocess.check_output([os.path.join(script_dir, 'list-modems')]) + out = subprocess.check_output([script_dir / 'list-modems']) self.assertTrue(out.startswith(b'[ /ril_0 ]'), out) self.assertIn(b'[ /sim2 ]', out) self.assertIn(b'Powered = 1', out) diff -Nru python-dbusmock-0.28.4/tests/test_polkitd.py python-dbusmock-0.28.6/tests/test_polkitd.py --- python-dbusmock-0.28.4/tests/test_polkitd.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_polkitd.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import shutil import subprocess diff -Nru python-dbusmock-0.28.4/tests/test_power_profiles_daemon.py python-dbusmock-0.28.6/tests/test_power_profiles_daemon.py --- python-dbusmock-0.28.4/tests/test_power_profiles_daemon.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_power_profiles_daemon.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Bastien Nocera' -__copyright__ = '(c) 2021 Red Hat Inc.' +__copyright__ = ''' +(c) 2021 Red Hat Inc. +(c) 2017 - 2022 Martin Pitt +''' import fcntl import os diff -Nru python-dbusmock-0.28.4/tests/test_systemd.py python-dbusmock-0.28.6/tests/test_systemd.py --- python-dbusmock-0.28.4/tests/test_systemd.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_systemd.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Jonas Ådahl' -__copyright__ = '(c) 2021 Red Hat' +__copyright__ = ''' +(c) 2021 Red Hat +(c) 2017 - 2022 Martin Pitt +''' import subprocess import sys diff -Nru python-dbusmock-0.28.4/tests/test_timedated.py python-dbusmock-0.28.6/tests/test_timedated.py --- python-dbusmock-0.28.4/tests/test_timedated.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_timedated.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,13 +7,16 @@ # of the license. __author__ = 'Iain Lane' -__copyright__ = '(c) 2013 Canonical Ltd.' +__copyright__ = ''' +(c) 2013 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' -import os import shutil import subprocess import sys import unittest +from pathlib import Path import dbusmock @@ -24,7 +27,7 @@ @unittest.skipUnless(have_timedatectl, 'timedatectl not installed') -@unittest.skipUnless(os.path.exists('/run/systemd/system'), '/run/systemd/system does not exist') +@unittest.skipUnless(Path('/run/systemd/system').exists(), '/run/systemd/system does not exist') class TestTimedated(dbusmock.DBusTestCase): '''Test mocking timedated''' diff -Nru python-dbusmock-0.28.4/tests/test_upower.py python-dbusmock-0.28.6/tests/test_upower.py --- python-dbusmock-0.28.4/tests/test_upower.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_upower.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Martin Pitt' -__copyright__ = '(c) 2012 Canonical Ltd.' +__copyright__ = ''' +(c) 2012 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import fcntl import os diff -Nru python-dbusmock-0.28.4/tests/test_urfkill.py python-dbusmock-0.28.6/tests/test_urfkill.py --- python-dbusmock-0.28.4/tests/test_urfkill.py 2022-07-19 12:32:59.000000000 +0000 +++ python-dbusmock-0.28.6/tests/test_urfkill.py 2022-10-12 05:10:28.000000000 +0000 @@ -7,7 +7,10 @@ # of the license. __author__ = 'Jussi Pakkanen' -__copyright__ = '(c) 2015 Canonical Ltd.' +__copyright__ = ''' +(c) 2015 Canonical Ltd. +(c) 2017 - 2022 Martin Pitt +''' import unittest import sys