Provide VIN to callback(s) registered with subscribe_updates()#502
Provide VIN to callback(s) registered with subscribe_updates()#502Giermann wants to merge 8 commits intoskodaconnect:mainfrom
Conversation
|
Thanks for your contribution! Couple of notes if we change this:
In |
I'm no python expert at all, but isn't the code backward compatible, if existing callbacks simply ignore the now provided parameter?
Same here: if registering a callback that takes no parameter is still working, nothing needs to be changed... |
No, python enforces the parameter to be of type Vin now.
Same answer :) |
Okay, then it might be easier to introduce a separate subscribe_vehicle_updates(). It's currently not clear to me, why this design is different to subscribe_events(). An event containing the VIN is being passed to a global list of callbacks there. For updates there are different callback lists for each vehicle that do not receiving any reference to the VIN that issued the call. I guess this needs some discussion to find the best solution. |
|
After looking deeper into the current implementation and thinking about possible solutions and namings, I'd prefer the following: As I still not know, why there are VIN-specific callback lists, one solution would be to report vehicle updates the same way, as MQTT Events are being reported. One global list of callbacks, that receive some "BaseEvent" as parameter. In future the same infrastructure could be used to report an instance of UpdateEvent or more specifically VehicleUpdateEvent. For backward compatibility, VIN specific lists could still be registered with subscribe_updates(). |
|
I had a look at this piece of the code, since it's been a while :) (please disregard my previous remark) We keep more information than what we can obtain from mqtt, so that's the root of the difference. Now, to address your issue. If i understand correctly, you are missing information when processing the callback, as it could be related to multiple Why not let the called function handle that like this? myskoda.subscribe_updates(myvin, myasyncfunc(vin=myvin)) |
I don't think that works because def make_callback(vin: str):
async def callback():
await your_vin_specific_callback_function(vin)
return callback
for vin in list_of_vins:
myskoda.subscribe_updates(vin, make_callback(vin))That being said, I think it might make sense for the callback to include the VIN for which there is an update. Again in homeassistant-myskoda we don't have this problem because we have a dedicated coordinator object per VIN, so it already knows which VIN the update is for. But it's reasonable to have myskoda clients which handle multiple VINs from the same place. And then it makes sense for the callback to include the actual VIN it is for as an argument. So the current change LGTM - it's just that we need to document it as a breaking change and update the usage in homeassistant-myskoda accordingly. |
|
Or we can set up def _notify_callbacks(self, vin: Vin) -> None:
"""Execute registered callback functions for the vin."""
for callback in self._callbacks.get(vin, []):
try:
result = callback(vin)
except TypeError:
result = callback() |
|
@Giermann would you be willing to update your pr? |
1 similar comment
|
@Giermann would you be willing to update your pr? |
|
Thanks, @dvx76! |
|
Still, I am not sure wheter we should really simply provide the VIN to the callbacks. WebSpider wrote (although he later revised this comment): But if the callbacks are interested in the trigger of that change, we could exented _notify_callbacks() to receive and publish that information too. If this is required (in the future?), we should introduce a BaseEvent parameter now instead of a simple VIN, which could be extended later. But I am fine with both - as long as the callback receives any information about the affected VIN. |
Yes it is, but it is a rather simple one: |
|
I overlooked that, only noticed the now still present "Expected 1 more positional argument (reportCallIssue)", which is by design. |
I see, this pyright message will likely disappear when you make the new Also, when you add |
Fixes "Expected 1 more positional argument (reportCallIssue)" from previous change
|
Thanks, but still failing - must be something I don't understand... |
I suspect it's due to the type hint for Callable[[Vin | None], Coroutine[Any, Any, None]That means "a callable (function) with one argument: either a Untested: Callable[[Vin | None], Coroutine[Any, Any, None] | Callable[[], Coroutine[Any, Any, None]]Which isn't very pretty, but correctly expresses what we would now be allowing.
The idea of |
|
Sorry for the garbage, but I did not manage to run Lint locally. |
|
It's just a missing square bracket Callable[[Vin], Coroutine[Any, Any, None]] | Callable[[], Coroutine[Any, Any, None]]But the type checker is still upset because it doesn't know what the 'right' signature for the callback function is. I'll work on an alternative. Or maybe we just always include the vin and make it a breaking change. It makes sense to the vin as an argument and the required change in home assistant is minimal. |
|
Right. It's doable but it's fiddly, especially with the type checker. And in retrospect I don't like the ambiguity of supporting both callback signatures. If it's fine for @WebSpider I'd vote to just add the VIN and mark the change as breaking (we can do that when merging and releasing a new package, don't worry about it here). So this version: https://github.com/skodaconnect/myskoda/pull/502/changes/BASE..bff6966d30e5a869e2f494ff01e401db264fc017 Either that, or make no change at all and handle it fully on the client side, using something like this which bakes the vin into the function passed into def make_callback(vin: str):
async def callback():
await your_vin_specific_callback_function(vin)
return callback
for vin in list_of_vins:
myskoda.subscribe_updates(vin, make_callback(vin)) |
|
Totally fine by me. Since we're doing a breaking change then, i'll plan some cleanup PRs to remove some deprecated code. |
|
Maybe it would be better to release this breaking change in two stages. Then, after a few days or weeks, release the new version that provides the VIN to the callback and simplify the example. |
|
This would require to change homeassistant-myskoda before the change here: |
homeassistant-myskoda is pinned to a specific version of this library. We would have to change this when we update the library version in the integration. We made it this way so we can release them both independently 👍 |
See issue #501 for details.