8000 ServiceBrowser handler argument overwrites zeroconf name · Issue #1092 · python-zeroconf/python-zeroconf · GitHub
[go: up one dir, main page]

Skip to content

ServiceBrowser handler argument overwrites zeroconf name #1092

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
nils-werner opened this issue Sep 13, 2022 · 4 comments
Open

ServiceBrowser handler argument overwrites zeroconf name #1092

nils-werner opened this issue Sep 13, 2022 · 4 comments

Comments

@nils-werner
Copy link

In the default pattern

import zeroconf

instance = zeroconf.Zeroconf()
browser = zeroconf.ServiceBrowser(
    instance,
    ['_osc._udp.local.'],
    handlers=[handler]
)

def handler(zeroconf, service_type, name, state_change):
    # I cannot use zeroconf.ServiceStateChange.Added here, because zeroconf is not the import but the argument
    pass

we have the problem that handler() is receiving a named argument zeroconf that overloads import zeroconf and that we cannot change. If I defined

def handler(zc, service_type, name, state_change):
    if state_change is zeroconf.ServiceStateChange.Added:
        print(name)

I would receive

TypeError: handler() got an unexpected keyword argument 'zeroconf'

To avoid it I would have to alias the import, which is a bit ugly:

import zeroconf as imported_zeroconf

def handler(zeroconf, service_type, name, state_change):
    if state_change is imported_zeroconf.ServiceStateChange.Added:
        print(name)

It would be nice if the arguments were to be passed in as positional arguments, or named differently, so that the names didn't clash.

@maxtruxa
Copy link
maxtruxa commented Feb 1, 2023

Quick workaround using a decorator:

from functools import wraps

def zeroconf_handler(handler):
    # `wrapper`'s argument names are important!
    @wraps(handler)
    def wrapper(zeroconf, service_type, name, state_change):
        handler(zeroconf, service_type, name, state_change)
    return wrapper

# ...

@zeroconf_handler
def handler(zc, type_, name, new_state):
    pass

browser = zeroconf.ServiceBrowser(
    instance,
    ['_osc._udp.local.'],
    handlers=[handler]
)

Just for completeness sake, this can easily be extended to support async callbacks, which prevents incorrect usage of ensure_future()/create_task() demonstrated in all the examples:

import asyncio
from functools import wraps

_zeroconf_pending_handler_tasks = set()
def async_zeroconf_handler(handler):
    # `wrapper`'s argument names are important!
    @wraps(handler)
    def wrapper(zeroconf, service_type, name, state_change):
        # Keep a reference to the task around until it's done, to prevent it from being garbage collected.
        task = asyncio.create_task(handler(zeroconf, service_type, name, state_change))
        _zeroconf_pending_handler_tasks.add(task)
        task.add_done_callback(_zeroconf_pending_handler_tasks.discard)
    return wrapper

# ...

@async_zeroconf_handler
async def handler(zc, type_, name, new_state):
    await asyncio.sleep(1)

browser = zeroconf.ServiceBrowser(
    instance,
    ['_osc._udp.local.'],
    handlers=[handler]
)

@bdraco
Copy link
Member
bdraco commented Feb 18, 2025

Changing the name in the callback would be a breaking change.

@bdraco bdraco closed this as not planned Won't fix, can't repro, duplicate, stale Feb 18, 2025
@nils-werner
Copy link
Author

Not really, you could simply make them unnamed/positional arguments...

@bdraco bdraco reopened this Feb 18, 2025
@bdraco
Copy link
Member
bdraco commented Feb 18, 2025

I would be helpful if you could open a PR to do that as I can't figure out how to do it without it being a breaking change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants
0