Looking into pydispatcher, getting pubsub behavior in pydispatcher is
more work than getting pydispatcher behavior in pubsub. Further,
pubsub's ability to define topics for sources and destinations are
actually a publish-subscribe architecture, where as with pydispatcher,
Can you elaborate a bit what you mean when you say "define topics for
sources and destinations"?
I was typing too fast . What I meant to type was that pubsub's
ability to have subscribers subscribe to a topic without knowing about
the sender, and the sender to send messages to a topic without knowing
about the subscribers, is a publish-subscribe architecture. It can't
get much more loosely-coupled than not needing to know at all (other
than the shared topic node).
Agreed. pydispatcher does support this though. See the _Any and _Anonymous
senders. This allows you to omit the sender alltogether.
Just to make sure I understand you correctly, Node x has a transform
property. When x.transform has changed, x is notified by the
publishing of a message by x.transform . (as an aside, subscriber ==
recipient, I think you mean "subscriber knows about the 'sender'".
Right. I was also typing too fast
Indeed, there is nothing *wrong* with x knowing about x.transform, and
there is no need to remove the coupling. But there is also no
inherent benefit to using pydispatcher over pubsub for this example.
Node x can easily subscribe to a particular topic, and receive
messages from that topic when x.transform sends the message.
Yes.
Now say the Node class wants to be informed about all the kinds of
messages
that transform produces. Right now this is not possible if I postpend the
id. Prepending the id allows me to register for all messages from that
object, but then again I cannot register to all messages of a specific
kind,
regardless of sender. Because of this putting the sender into the
topic-tree
is a bad idea imo. The sender is not associated with the topic, it's
orthogonal to it. So mingling its id into the topic is bad.
Indeed, if you prepend the id, you can subscribe to all events from
one object, or you can also create a new Publisher instance, let the
transform property know about it (so that it knows which publisher to
send messages to), and you guarantee locality.
If you want the ability to send messages to all objects of a
particular type, well, it turns out that is easy too :).
If all of your publish/subscribe messages are of the form:
[<type>.]<topic>[|.<None>|.<id>]
And when you publish from an object, you send to:
1. <topic>.<None> and <None>.<topic>
or
2. <topic>.<id> and <type>.<topic>.<id>
Then you can handle "give me stuff from objects of type X", "give me
stuff from objects with id X", "give me stuff from objects of type X
and id Y", etc.
Yes. But then I have to send two messages manually and people listening for
None.None or None or ALL_TOPICS will receive the same message twice. With
pydispatcher you'd send the message once and then can register on id and/or
topic. Of course you could write something like that for pubsub too, but
then it doesn't benefit from the hierarchy structure anymore as it's more or
less processing flat messages. That's why I was arguing a bit in favour of
pydispatcher, because it only deals with arbitrary (see below)/flat topics
on top of which you could implement a hierarchy like pubsub has. The basis
of an event dispatcher as a python standard library module should be as slim
as possible imo and the hierarchy is more work and code if you're mostly
processing flat topics in the end.
How often is it that you have *one* receiver taking both "give me a
message from any anonymous sender" and "give me any anonymous message
on topic X"? Because those are the specific use-cases for this. Of
course, I don't have a use for either, so...
It turns out that without re-implementing the tree structure that
pubsub uses, getting the same behavior with respect to the topic
hierarchy and subscriber calling is expensive (or you have to keep
cycling within pydispatcher to get what you want). Where as when you
have the tree structure already, you can fit pydispatcher in without
much difficulty.
Additionally pubsub doesn't support arbitrary topics, whereas
pydispatcher
does. Fitting this onto pubsub is probably also some work I guess. I
think
pubsub has gone one step too far by implementing a topic-tree. Maybe this
"deal with topics" part should be abstracted and made pluggable somehow.
Arbitrary topics? I don't know precisely what you mean. If you mean
that topics are of a hierarchical tree structure, then yes. But
that's actually a *good* feature.
I mean pubsub supports only strings (or tuples thereof) as topics. In
pydispatcher any hashable object can be a topic. I do agree that a hierarchy
is a good feature and quite powerful.
Technically speaking, pydisptcher uses id(object), which pubsub can
also use. Also, technically, pubsub doesn't actually do typechecks on
objects passed as the contents of the tuple...
import wx.lib.pubsub
def fcn(msg):
... print msg.topic, msg.data
...
wx.lib.pubsub.Publisher.subscribe(fcn, (1, 'is', 'my', 'topic'))
wx.lib.pubsub.Publisher.sendMessage((1, 'is', 'my', 'topic'), "data")
(1, 'is', 'my', 'topic') data
Of course it doesn't do weak referencing of the keys, but that isn't
terribly difficult to support...
import weakref
d = weakref.WeakKeyDictionary()
class foo:
... pass
...
e = foo()
def killtopic(topic):
... class kt:
... def __del__(self):
... print "would have killed topic", topic
... return kt()
...
e = foo()
d[e] = killtopic('some random topic')
del e
would have killed topic some random topic
Now, if we explicitly disallow anything except strings and non-builtin
types, then integer keys can represent id(object), and with the
killtopic mechanism, we can clear out topics if the objects in the
topics no longer exist.
Maybe we are just experiencing what I mentioned before, my expectations
are
varying wildly from yours (at least until we've come to a conclusion of
this
discussion)
Oh, I'm sure our expectations are vastly different; I've never come
across an application where it actually mattered substantially where a
message came from. And when it did, you just pass where it came from
as part of the data.
Yes, this is always possible. I tend to register with senders sometimes and
then it's nice to have an explicit mechanism for that. Of course if I wanted
to do the whole of type.topic.id thing, then pydispatcher would need a
helper function too.
It seems there are many points of view on this topic. It seems that pubsub
(with some helper functions) and pydispatcher (with helpers for hierarchy)
can do the same things. In the end it probably boils down to taste which to
use as the basis for an event module. Pubsub would greatly benefit from some
helper functions (judging from my taste) which make common tasks work out of
the box. If I have to start thinking like type.topic.id it's getting too
much work and the module gets a lot less attractive.
Oh of course, the users of the module shouldn't have to consider how
it's internally represented, just that during subscription they can
say, "subscribe to topic X and it's descendants", plus the variants
with specific sender instances, types, etc. (though in my opinion the
latter shouldn't be quite so obvious). And with a little bit of
magic, you can also guarantee that during the wrapper's multi-call to
handle all of the options (in the case of the type/instance, etc.),
you don't send the same message to the same subscriber twice.
So in conclusion I wouldn't mind which module will get included in python as
long as one of them actually does.
Thanks for explaining your point of view so thoroughly,
No problem :), thank you for not yelling and screaming at me .
- Josiah
···
On Thu, Jul 24, 2008 at 5:27 PM, Nitro <nitro@dr-code.org> wrote:
Am 25.07.2008, 01:39 Uhr, schrieb Josiah Carlson <josiah.carlson@gmail.com>:
On Thu, Jul 24, 2008 at 3:29 PM, Nitro <nitro@dr-code.org> wrote:
Am 24.07.2008, 23:31 Uhr, schrieb Josiah Carlson >>> <josiah.carlson@gmail.com>: