Skip to main content

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [List Home]
Re: [paho-dev] Python Client inheritance

Le 19/04/2016 17:14, Jason Swails a écrit :
Hi,
Hi Jason.
To be fair, the current class structure doesn't prevent inheritance -- just like the base class, you need to explicitly attach any callbacks as an attribute to the class.  Anything that's not the on_<action> callback is implemented directly as a method attribute, and can be overridden just fine in a subclass.
Of course the current structure doesn't prevent inheritance. Nevertheless I think that explicitly attach callbacks is not a very straightforward method. Moreover, this imply that your callbacks are not named on_{connect,message,...} in which case they will be overridden by the initialization of the Client class.
But this is definitely a strange pattern in my experience with Python.  Most instance attributes are assigned when the class definition is defined and is an unbound instance attribute on the class (rather than something that is bound at instance initialization).  A more natural API (to me, of course!) would be to either leave the on_* callbacks not implemented and rely on subclassing to implement it -or- have a function where you can register the callbacks.  The former would be a substantial break in the API.  The latter could be implemented in a fully backwards-compatible way by making the on_<action> callbacks descriptors (via the @property decorator)... but that's really the same thing that we already have from a functional perspective... it would just allow overriding to work in subclasses.
I agree with your first proposal, but to prevent API break, you can define on_* callbacks as just empty functions in the base Client() class, for example :

class Client:
	...

	def on_connect(self, client, userdata, flag, rc):
        	"""Called when the broker responds to our connection request.
        	This function may be overridden by sub-classes.
	
	        client:     the client instance for this callback
        	userdata:   the private user data as set in Client() or userdata_set()
	        flags:      response flags sent by the broker
	        rc:         the connection result
	        """
	        pass

	...

The second proposal seems more complicated, and as I understand it you will have to do a lot of self.register_callback('calback_name', self.callback_name_function) in you subclass initialization.
If it is decided that the callback registry approach is the one most liked, it will *allow* subclasses to override that behavior, but in such cases I would consider that approach to be a bit of an anti-pattern (why would a subclass swap out a flexible register service with a hard-coded function?  It changes the whole interface of the object...).
I started to implement the first proposal. I will open an Issue an PR on Github to follow the discussion.
As an aside, one of the reasons to avoid doing fancy stuff like that in the initializer in my experience is that I don't think it plays nicely with serialization -- you'll need to do a bit of work to get pickling/unpickling to work correctly for these types, I think.

All the best,
Jason

Jason Swails
Project Software Engineer
Ext. 1680
Kind regards,
Alexis

-----Original Message-----
From: paho-dev-bounces@xxxxxxxxxxx [mailto:paho-dev-
bounces@xxxxxxxxxxx] On Behalf Of Roger Light
Sent: Tuesday, April 19, 2016 6:46 AM
To: General development discussions for paho project <paho-
dev@xxxxxxxxxxx>
Subject: Re: [paho-dev] Python Client inheritance

Hi Alexis,

That sounds like a good idea. I confess that inheritance isn't something I
really use so it may have been possible in the past and I've broken it.

I'd be happy to accept a patch for this, please base it on the fixes branch, add
an entry to the changelog and make sure you have signed the Eclipse CLA.

Thanks,

Roger



On Tue, Apr 19, 2016 at 9:38 AM, Alexis BRENON <alexis.brenon@xxxxxxx>
wrote:
Hi guys,

I'm using the Python implementation of MQTT through the paho-mqtt
package.
The documentation says that you can inherit from the Client class to
create your own MQTT_client. Nevertheless, inheriting from the client
doesn't allow you to define some on_* functions directly in the class
because they are overridden by the __init__ call of the base class...

So, there is any particular reason the define Client.on_* to None in
the __init__ instead of using classical member functions like this :

class Client(object):
     def __init__(self, ...):
         ...
         # Nothing about self.on_*

     def on_*(self, ...):
         pass


An implementation like this would not break the actual behavior (you
can redefine function, using mqttc.on_connect =
my_new_connect_function), and it would be easier to inherit, defining
overriding on_* functions in the sub-class.

If this seems a good idea, I propose myself to do the patch.

Kind regards,
Alexis BRENON

--
Doctorant sur le projet CASSIE (alexisbrenon.github.io) Équipe GETALP
(getalp.imag.fr) Laboratoire d'Informatique de Grenoble (liglab.fr)

_______________________________________________
paho-dev mailing list
paho-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or
unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/paho-dev
_______________________________________________
paho-dev mailing list
paho-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe
from this list, visit https://dev.eclipse.org/mailman/listinfo/paho-dev
_______________________________________________
paho-dev mailing list
paho-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/paho-dev

--
Doctorant sur le projet CASSIE (alexisbrenon.github.io)
Équipe GETALP (getalp.imag.fr)
Laboratoire d'Informatique de Grenoble (liglab.fr)



Back to the top