Skip to content

Commit

Permalink
Added boolean arguments to the default bus name request functions
Browse files Browse the repository at this point in the history
The undocumented argument `flags` was removed. Since it was not
documented it is removed without going through deprecation.

The boolean flags provide the control over the name acquisition
behavior.

Looks like the `request_default_bus_name` was async on accident.
Add a special deprecation warning on awaiting the return object.
  • Loading branch information
igo95862 committed Jan 14, 2023
1 parent a8bcbd2 commit b246d56
Show file tree
Hide file tree
Showing 5 changed files with 185 additions and 18 deletions.
10 changes: 10 additions & 0 deletions DEPRECATIONS.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,15 @@
# Deprecation information

## Awaiting on `request_default_bus_name`

By mistake `request_default_bus_name` was made in to async function
even though it was never documented to be one. It is now a blocking
function but returns an awaitable for backwards compatibility.

* **Since**: 0.11.0
* **Warning**: 0.11.0
* **Removed**: 1.0.0

## Importing exceptions from `sdbus` module

All exceptions have been moved to `sdbus.exceptions` to clean up imports.
Expand Down
22 changes: 20 additions & 2 deletions docs/common_api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,39 @@ These calls are shared between async and blocking API.
Dbus connections calls
++++++++++++++++++++++++++++++++++

.. py:function:: request_default_bus_name_async(new_name)
.. py:function:: request_default_bus_name_async(new_name, allow_replacement, replace_existing, queue)
:async:

Acquire a name on the default bus async.

:param str new_name: the name to acquire.
Must be a valid dbus service name.
:param str new_name: the name to acquire.
Must be a valid dbus service name.
:param bool allow_replacement: If name was acquired allow other peers
to take away the name.
:param bool replace_existing: If current name owner allows, take
away the name.
:param bool queue: Queue up for name acquisition.
:py:exc:`.SdBusRequestNameInQueueError` will be raised when successfully
placed in queue. :py:meth:`Ownership change signal <sdbus_async.dbus_daemon.FreedesktopDbus.name_owner_changed>`
should be monitored get notified when the name was acquired.
:raises: :ref:`name-request-exceptions` and other D-Bus exceptions.

.. py:function:: request_default_bus_name(new_name)
.. py:function:: request_default_bus_name(new_name, allow_replacement, replace_existing, queue)
Acquire a name on the default bus.

:param str new_name: the name to acquire.
Must be a valid dbus service name.
:param bool allow_replacement: If name was acquired allow other peers
to take away the name.
:param bool replace_existing: If current name owner allows, take
away the name.
:param bool queue: Queue up for name acquisition.
:py:exc:`.SdBusRequestNameInQueueError` will be raised when successfully
placed in queue. :py:meth:`Ownership change signal <sdbus_async.dbus_daemon.FreedesktopDbus.name_owner_changed>`
should be monitored get notified when the name was acquired.
:raises: :ref:`name-request-exceptions` and other D-Bus exceptions.

.. py:function:: set_default_bus(new_default)
Expand Down
73 changes: 63 additions & 10 deletions src/sdbus/dbus_common_funcs.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@

# SPDX-License-Identifier: LGPL-2.1-or-later

# Copyright (C) 2020-2022 igo95862
# Copyright (C) 2020-2023 igo95862

# This file is part of python-sdbus

Expand All @@ -20,15 +20,19 @@
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from __future__ import annotations

from asyncio import get_running_loop
from asyncio import Future, get_running_loop
from contextvars import ContextVar
from typing import Iterator
from typing import Generator, Iterator
from warnings import warn

from .sd_bus_internals import (
DbusPropertyConstFlag,
DbusPropertyEmitsChangeFlag,
DbusPropertyEmitsInvalidationFlag,
DbusPropertyExplicitFlag,
NameAllowReplacementFlag,
NameQueueFlag,
NameReplaceExistingFlag,
SdBus,
sd_bus_open,
)
Expand All @@ -50,6 +54,20 @@ def _is_property_flags_correct(flags: int) -> bool:
return (0 <= num_of_flag_bits <= 1)


def _prepare_request_name_flags(
allow_replacement: bool,
replace_existing: bool,
queue: bool,
) -> int:
return (
(NameAllowReplacementFlag if allow_replacement else 0)
+
(NameReplaceExistingFlag if replace_existing else 0)
+
(NameQueueFlag if queue else 0)
)


def get_default_bus() -> SdBus:
try:
return DEFAULT_BUS.get()
Expand All @@ -65,16 +83,51 @@ def set_default_bus(new_default: SdBus) -> None:

async def request_default_bus_name_async(
new_name: str,
flags: int = 0,) -> None:
allow_replacement: bool = False,
replace_existing: bool = False,
queue: bool = False,
) -> None:
default_bus = get_default_bus()
await default_bus.request_name_async(new_name, flags)


async def request_default_bus_name(
await default_bus.request_name_async(
new_name,
_prepare_request_name_flags(
allow_replacement,
replace_existing,
queue,
)
)


class _DeprecationAwaitable:
def __await__(self) -> Generator[Future[None], None, None]:
warn(
(
'Awaiting on request_default_bus_name'
'is deprecated and will be removed.'
),
DeprecationWarning,
)
f: Future[None] = Future()
f.set_result(None)
yield from f


def request_default_bus_name(
new_name: str,
flags: int = 0,) -> None:
allow_replacement: bool = False,
replace_existing: bool = False,
queue: bool = False,
) -> _DeprecationAwaitable:
default_bus = get_default_bus()
default_bus.request_name(new_name, flags)
default_bus.request_name(
new_name,
_prepare_request_name_flags(
allow_replacement,
replace_existing,
queue,
)
)
return _DeprecationAwaitable()


def _method_name_converter(python_name: str) -> Iterator[str]:
Expand Down
39 changes: 39 additions & 0 deletions test/test_deprecations.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# SPDX-License-Identifier: LGPL-2.1-or-later

# Copyright (C) 2023 igo95862

# This file is part of python-sdbus

# This library 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 2.1 of the License, or (at your option) any later version.

# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.

# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
from __future__ import annotations

from unittest import main

from sdbus.unittest import IsolatedDbusTestCase

from sdbus import request_default_bus_name


class TestDeprecations(IsolatedDbusTestCase):
async def test_await_on_blocking_request_name(self) -> None:
with self.assertWarnsRegex(
DeprecationWarning,
'Awaiting on request_default_bus_name'
):
await request_default_bus_name('org.example.test')


if __name__ == '__main__':
main()
59 changes: 53 additions & 6 deletions test/test_request_name.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,20 @@
SdBusRequestNameExistsError,
SdBusRequestNameInQueueError,
)
from sdbus.sd_bus_internals import NameQueueFlag
from sdbus.sd_bus_internals import NameAllowReplacementFlag, NameQueueFlag
from sdbus.unittest import IsolatedDbusTestCase

from sdbus import sd_bus_open_user
from sdbus import (
request_default_bus_name,
request_default_bus_name_async,
sd_bus_open_user,
)

TEST_BUS_NAME = 'com.example.test'
TEST_BUS_NAME_regex_match = TEST_BUS_NAME.replace('.', r'\.')


class TestRequestName(IsolatedDbusTestCase):
async def asyncSetUp(self) -> None:
await super().asyncSetUp()

class TestRequestNameLowLevel(IsolatedDbusTestCase):
def test_request_name_exception_tree(self) -> None:
# Test that SdBusRequestNameError is super class
# of other request name exceptions
Expand Down Expand Up @@ -158,5 +159,51 @@ def test_name_other_error_block(self) -> None:
extra_bus.request_name(TEST_BUS_NAME, 0)


class TestRequestNameBlock(IsolatedDbusTestCase):
def test_request_name_replacement(self) -> None:
extra_bus = sd_bus_open_user()
extra_bus.request_name(TEST_BUS_NAME, NameAllowReplacementFlag)

with self.assertRaises(SdBusRequestNameExistsError):
request_default_bus_name(TEST_BUS_NAME)

request_default_bus_name(
TEST_BUS_NAME,
replace_existing=True,
)


class TestRequestNameAsync(IsolatedDbusTestCase):
async def test_request_name_replacement(self) -> None:
extra_bus = sd_bus_open_user()
await extra_bus.request_name_async(
TEST_BUS_NAME,
NameAllowReplacementFlag,
)

with self.assertRaises(SdBusRequestNameExistsError):
await request_default_bus_name_async(TEST_BUS_NAME)

await request_default_bus_name_async(
TEST_BUS_NAME,
replace_existing=True,
)

async def test_request_name_queue(self) -> None:
extra_bus = sd_bus_open_user()
await extra_bus.request_name_async(TEST_BUS_NAME, 0)

with self.assertRaises(SdBusRequestNameInQueueError):
await request_default_bus_name_async(
TEST_BUS_NAME,
queue=True,
)

extra_bus.close()

with self.assertRaises(SdBusRequestNameAlreadyOwnerError):
await request_default_bus_name_async(TEST_BUS_NAME)


if __name__ == '__main__':
main()

0 comments on commit b246d56

Please sign in to comment.