Hi again Kristian,

If you don't already have a deferred handy, you need to create one
(which is obviously what you're doing) to return properly from a method
that is expected to return a deferred.
There are shortcut to do that, which are
twisted.internet.defer.succeed() and .fail() (see
http://twistedmatrix.com/documents/current/api/twisted.internet.defer.html#succeed).

In your case, since you do not seem to do anything asynchronous, you do
not need to create that "play_uri()" subfunction. You can implement what
it does idrectly in node_clicked() and return something with
defer.succeed() in the end, typically:
  return defer.succeed(None)
Ensuring you have imported the defer module from twisted.internet.

Guillaume


Le vendredi 06 février 2009 à 22:04 +0100, Kristian Lippert a écrit :
> Hi Olivier
> With your help it was easy to make some code that python liked:
> 
>     def node_clicked(self, widget, item):
> 
>         def play_uri(self=dfr_self, station=dfr_station):
>             player =
> self.frontend.retrieve_controllers('/poblesec/music_player')[0]
>             player.player.play_model(station)
>             main = self.frontend.retrieve_controllers('/poblesec')[0]
>             main.show_music_player()
>             self.stop_loading_animation()
> 
>          dfr = defer.Deferred().addCallback(play_uri, self, item)
>          return dfr
> 
> But the play is not called (and you stated there is no magic :-)
> But when looking into the shoutcast play-method that is called
> implicit using some sort of Elisa command pattern I see the following:
> 
>     def play_station(self, station):
>         resource, dfr =
> application.resource_manager.get(station.get_playable, station)
> 
>         def play(station):
>             player =
> self.frontend.retrieve_controllers('/poblesec/music_player')[0]
>             player.player.play_model(station)
> 
>             main = self.frontend.retrieve_controllers('/poblesec')[0]
>             main.show_music_player()
>             self.stop_loading_animation()
> 
>         dfr.addCallback(play)
> 
> As seen a deferred comes "magically" (:-) in hand and the method
> "play" is added.
> I would like to do the same but have no resource in the resource
> manager (I think??)
> 
> Please Advice!
> 
> Best Regards,
> Kristian
> > Date: Wed, 4 Feb 2009 09:50:22 +0100
> > From: [email protected]
> > To: [email protected]
> > CC: [email protected]
> > Subject: Re: [Elisa] Problems with deferred and Elisa
> > 
> > Hi Kristian,
> > 
> > Kristian Lippert a écrit :
> > > Hi
> > > I have a play-method in my own stream-player and it works:
> > > 
> > > def node_clicked(self, widget, item):
> > > def play_uri(self, station):
> > > # We already know the real URL of the playable audio stream, no
> > > # need to query the resource manager
> > > # get player and start playing
> > > player =
> > > self.frontend.retrieve_controllers('/poblesec/music_player')[0]
> > > player.player.play_model(station)
> > > main = self.frontend.retrieve_controllers('/poblesec')[0]
> > > main.show_music_player()
> > > self.stop_loading_animation()
> > > 
> > > pdb.set_trace()
> > > if isinstance(item, Action):
> > > item.run()
> > 
> > Side note: this test is useless if you know that your list contains
> only
> > PlayableModels.
> > 
> > > elif isinstance(item, PlayableModel):
> > > play_uri(self, item)
> > > 
> > > It works fine but if there are problems with the stream it will
> hang for
> > > a while, so I thought I could use a deferred, like:
> > > 
> > > def node_clicked(self, widget, item):
> > > 
> > > def play_uri(self, station):
> > > # We already know the real URL of the playable audio stream, no
> > > # need to query the resource manager
> > > # get player and start playing
> > > player =
> > > self.frontend.retrieve_controllers('/poblesec/music_player')[0]
> > > player.player.play_model(station)
> > > 
> > > main = self.frontend.retrieve_controllers('/poblesec')[0]
> > > main.show_music_player()
> > > self.stop_loading_animation()
> > > 
> > > pdb.set_trace()
> > > if isinstance(item, Action):
> > > item.run()
> > > elif isinstance(item, PlayableModel):
> > > dfr = defer.Deferred().addCallback(play_uri)
> > > return dfr(self, item)
> > > 
> > > My problem is that I am not sure:
> > > 1) Do I create the deferred in the right manner?
> > 
> > Not really, see my explanation below.
> > 
> > > 2) How does the binding of the parameters happen?
> > 
> > Simply pass extra arguments to the addCallback method, they are
> going to
> > be passed to the callback after the result argument.
> > 
> > > 3) Do I need to activate the deferred my self or will this happen
> by
> > > magic by it self?
> > 
> > If you instantiate a deferred with defer.Deferred(), then nothing
> won't
> > happen until someone/something invokes its callback() method, that
> will
> > in turn trigger the chained callbacks to be called.
> > 
> > One simple example:
> > 
> > def cb(result, arg1, arg2):
> > print result, arg1, arg2
> > 
> > dfr = defer.Deferred()
> > dfr.addCallback(cb, 'hello', 'world')
> > dfr.callback()
> > 
> > If you want to try it out as is in a python shell, you'll have to
> import
> > twisted.internet.reactor, and call reactor.run().
> > 
> > > As far as I can read the deferred can be compared to the .NET
> > > asynchronous delegates or boost::thread. Boost::thread is much
> simpler
> > > but they share the problem regarding binding variables.
> > 
> > Unfortunately deferreds won't magically make synchronous code
> > asynchronous. They are a tool to help you write asynchronous code,
> but
> > in that case the underlying methods you are calling
> > (player.player.play_model, main.show_music_player,
> > self.stop_loading_animation) are all synchronous (in the sense that
> they
> > don't return a deferred). You could mock asynchrony by calling them
> in a
> > thread, but that's highly discouraged so I'm not giving you the link
> to
> > the doc of the method that allows that ;)
> > 
> > > Please help me fix the code!
> > > 
> > > Best Regards,
> > > Kristian
> > 
> > I hope this helps.
> > 
> > Olivier
> 
> 
> ______________________________________________________________________
> Invite your mail contacts to join your friends list with Windows Live
> Spaces. It's easy! Try it!

Reply via email to