<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Lior Gradstein's Blog &#187; twisted</title>
	<atom:link href="http://www.gradstein.info/category/software/twisted/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.gradstein.info</link>
	<description></description>
	<lastBuildDate>Thu, 13 May 2010 09:46:29 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Videos of every presentation of Journée Python 2007 are now online!</title>
		<link>http://www.gradstein.info/python/videos-of-every-presentation-of-journee-python-2007-are-now-online/</link>
		<comments>http://www.gradstein.info/python/videos-of-every-presentation-of-journee-python-2007-are-now-online/#comments</comments>
		<pubDate>Tue, 12 Jun 2007 00:50:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[language]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/language/videos-of-every-presentation-of-journee-python-2007-are-now-online/</guid>
		<description><![CDATA[As the title says it, each presentation was filmed, and has just been uploaded for everyone&#8217;s pleasure! Here is the two-part video presentation of Twisted, done by Michael SCHERER.


Oh, by the way, please take a minute to vote for your favourite Internet Engine!



	Related posts
	
	No related posts.
	

]]></description>
			<content:encoded><![CDATA[<p>As the title says it, each <a href="http://journees.afpy.org/programme" class="liexternal">presentation was filmed</a>, and has just been uploaded for everyone&#8217;s pleasure! Here is the two-part video presentation of Twisted, done by Michael SCHERER.</p>
<p><object type="application/x-shockwave-flash" data="http://video.google.com/googleplayer.swf?docId=8739163173039026567" width="425" height="350" wmode="transparent"><param name="movie" value="http://video.google.com/googleplayer.swf?docId=8739163173039026567" /></object><br />
<object type="application/x-shockwave-flash" data="http://video.google.com/googleplayer.swf?docId=1837647658089311574" width="425" height="350" wmode="transparent"><param name="movie" value="http://video.google.com/googleplayer.swf?docId=1837647658089311574" /></object></p>
<p>Oh, by the way, please take a minute to vote for your favourite Internet Engine!</p>
<p align="center">
<iframe src="http://jyte.com/widget/claim/twistedmatrix.com-is-the-engine-of-your-internet" style="width:400px;height:60px;border:1px solid #777;" scrolling="no"></iframe></p>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/python/videos-of-every-presentation-of-journee-python-2007-are-now-online/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Troll of the day: Why Ruby sucks and why Python rocks!</title>
		<link>http://www.gradstein.info/python/troll-of-the-day-why-ruby-sucks-and-why-python-rocks/</link>
		<comments>http://www.gradstein.info/python/troll-of-the-day-why-ruby-sucks-and-why-python-rocks/#comments</comments>
		<pubDate>Wed, 25 Apr 2007 15:06:00 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[ruby]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/uncategorized/troll-of-the-day-why-ruby-sucks-and-why-python-rocks/</guid>
		<description><![CDATA[I found a nicely written article about the problems with Ruby, written by a Ruby user, and why he found Python to be really good. There&#8217;s even a quote about Twisted!
And, there are a bunch of things available to a Python guy that Ruby just canâ€™t compete with that are of particular interest to me. [...]]]></description>
			<content:encoded><![CDATA[<p>I found a <a href="http://blog.cbcg.net/articles/2007/04/22/python-up-ruby-down-if-that-runtime-dont-work-then-its-bound-to-drizzown" class="liexternal">nicely written article</a> about the problems with Ruby, written by a Ruby user, and why he found Python to be really good. There&#8217;s even a quote about Twisted!<br />
<blockquote>And, there are a bunch of things available to a Python guy that Ruby just canâ€™t compete with that are of particular interest to me. Two that come to mind immediately are <a href="http://twistedmatrix.com/trac/" class="liexternal">Twisted</a> and <a href="http://www.stackless.com/" class="liexternal">Stackless Python</a>. The former was used by others at TurnTide for creating a really powerful <span class="caps">SMTP</span> testing tool and the latter was used by TurnTideâ€™s competitor <a href="http://www.ironport.com/" class="liexternal">IronPort</a> to build one of the industryâ€™s best MTAs.</p></blockquote>
<p>I didn&#8217;t knew that IronPort was done in Python, even in Stackless Python!</p>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/python/troll-of-the-day-why-ruby-sucks-and-why-python-rocks/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Extension for Twisted AMP to support dictionaries and lists</title>
		<link>http://www.gradstein.info/python/extension-for-twisted-amp-to-support-dictionaries-and-lists/</link>
		<comments>http://www.gradstein.info/python/extension-for-twisted-amp-to-support-dictionaries-and-lists/#comments</comments>
		<pubDate>Thu, 08 Feb 2007 09:28:00 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/uncategorized/extension-for-twisted-amp-to-support-dictionaries-and-lists/</guid>
		<description><![CDATA[Henrik Thostrup Jensen announced on the Twisted Users mailing list he made two extensions for the Twisted AMP protocol.
Currently there are two types: A dictionary and a list. The types of the element must be specified (key and value can be different in the dictionary), otherwise they are free form, i.e., the keys in the [...]]]></description>
			<content:encoded><![CDATA[<p>Henrik Thostrup Jensen announced on the Twisted Users mailing list he made two extensions for the Twisted AMP protocol.<br />
<blockquote>Currently there are two types: A dictionary and a list. The types of the element must be specified (key and value can be different in the dictionary), otherwise they are free form, i.e., the keys in the dictionary can have any name, and the list can be of any size. The types can be nested, e.g., you can create a list of list of strings. I use (or will) the latter to return a query result, for which I do not know the row size. This is currently impossible (AFAICT), in the otherwise excellent AMP protocol.</p></blockquote>
<p>You can get them on <a href="http://www.cs.aau.dk/%7Ehtj/code/amptypes-0.1.tar.gz" class="lizip">http://www.cs.aau.dk/~htj/code/amptypes-0.1.tar.gz</a></p>
<p>For people that live under a rock, AMP is a new communication protocol for Twisted (added in Twisted 2.5) much lighter/simpler than PB. It is just a request/response protocol over a persistent connection.</p>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/python/extension-for-twisted-amp-to-support-dictionaries-and-lists/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Deploying Twisted Python on Windows</title>
		<link>http://www.gradstein.info/software/twisted/deploying-twisted-python-on-windows/</link>
		<comments>http://www.gradstein.info/software/twisted/deploying-twisted-python-on-windows/#comments</comments>
		<pubDate>Mon, 20 Jun 2005 08:34:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[linux]]></category>
		<category><![CDATA[software]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=334</guid>
		<description><![CDATA[Making and deploying a Twisted project as a service under Windows
1. What is the objective?
The goal is to implement a program in Python+Twisted (using PB for network access) under Windows XP or 2000+, that can be run before a user logs on, so it has to be a windows service, launched automatically, at boot. Another [...]]]></description>
			<content:encoded><![CDATA[<p>Making and deploying a Twisted project as a service under Windows</p>
<p>1. What is the objective?</p>
<p>The goal is to implement a program in Python+Twisted (using PB for network access) under Windows XP or 2000+, that can be run before a user logs on, so it has to be a windows service, launched automatically, at boot. Another goal is to show some developement patterns in Twisted. You will find a lot of &#8216;theoretical&#8217; patterns about how to make singletons/borgs, proxy, etc. stuffs, but I never found patterns about &#8216;Twisted code&#8217;, except for the wonderful &#8216;finger tutorial&#8217; by squishy moshez. This tutorial can be split in two parts: The first one is about writing a good skeleton for your Twisted development. The second part is about making a Windows service.</p>
<p>Note that these instructions (the service building part) will not work under Windows 95 or 98 or below.<br />
2. Required packages</p>
<p>On the Windows machine, we can separate the required stuff in two:</p>
<ul>
<li>The required stuff for generating the files: To do so, we need ActiveState Python 2.3+ (because it includes the latest version of the modules pywin32), Twisted 1.3+, and py2exe 0.5+, and eventually gvim for editing the files.</li>
<li>The required stuff when we have generated all the required files: nothing, as we&#8217;ll have a compiled program which includes all the required DLLs.</li>
</ul>
<p>3. Installation of the required packages</p>
<p>Nothing special here, just click, except that I needed (found necessary) to add the path to the scripts (twistd) in Python2.3 (installation path to Python and path to scripts directory).<br />
4. Writing the program</p>
<p>In our program, we don&#8217;t need anything specific that will require the use of the specially made reactor for win32, in fact, there&#8217;s not really any reason to use it anyway. There&#8217;s just the case if you want to use the utils.getProcessValue() method of twisted which doen&#8217;t work if you use the default select recator. That&#8217;s not really a problem, as you can use the win32pipe.popen() from the pywin32 modules which works perfectly in Twisted (at least for me).</p>
<p>Here, our program is a simple one that just listens on port 1234 using PB, making the method getFoo() available to the outside. This method just returns the current time.<br />
4.1. Simple, Fast and short code</p>
<p>Here is the simplest code, without using tricks to shorten the code making it unreadable (Myprog1.py):</p>
<div class="python" style="font-family: monospace;color: #000066; border: 1px solid orange; margin: 5px; padding: 5px; background-color: #ffffff;"><span style="color: #808080; font-style: italic;"># -*- coding: latin-1 -*-</span><br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> reactor,defer,app<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">application</span> <span style="color: #ff7700;font-weight:bold;">import</span> service,internet<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">internet</span> <span style="color: #ff7700;font-weight:bold;">import</span> defer<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">spread</span> <span style="color: #ff7700;font-weight:bold;">import</span> pb<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">python</span> <span style="color: #ff7700;font-weight:bold;">import</span> log,logfile<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">cred</span> <span style="color: #ff7700;font-weight:bold;">import</span> portal,checkers,credentials<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">manhole</span>.<span style="color: black;">telnet</span> <span style="color: #ff7700;font-weight:bold;">import</span> ShellFactory<br />
<span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">cred</span>.<span style="color: black;">portal</span> <span style="color: #ff7700;font-weight:bold;">import</span> IRealm</p>
<p><span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">time</span></p>
<p><span style="color: #ff7700;font-weight:bold;">class</span> SimpleRealm:<br />
&nbsp; &nbsp; __implements__ = IRealm</p>
<p>&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> requestAvatar<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, avatarId, mind, *interfaces<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">if</span> pb.<span style="color: black;">IPerspective</span> <span style="color: #ff7700;font-weight:bold;">in</span> interfaces:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; p = Presence<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> pb.<span style="color: black;">IPerspective</span>, p, <span style="color: #ff7700;font-weight:bold;">lambda</span> : <span style="color: #008000;">None</span><br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">else</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">raise</span> <span style="color: #008000;">NotImplementedError</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;no interface&quot;</span><span style="color: black;">&#41;</span></p>
<p><span style="color: #ff7700;font-weight:bold;">class</span> Presence<span style="color: black;">&#40;</span>pb.<span style="color: black;">Avatar</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">def</span> perspective_getFoo<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, data<span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; &nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #dc143c;">time</span>.<span style="color: #dc143c;">time</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></p>
<p><span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">cred</span>.<span style="color: black;">portal</span> <span style="color: #ff7700;font-weight:bold;">import</span> Portal<br />
&nbsp; &nbsp; <span style="color: #ff7700;font-weight:bold;">from</span> twisted.<span style="color: black;">cred</span>.<span style="color: black;">checkers</span> <span style="color: #ff7700;font-weight:bold;">import</span> InMemoryUsernamePasswordDatabaseDontUse</p>
<p>&nbsp; &nbsp; portal = Portal<span style="color: black;">&#40;</span>SimpleRealm<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; checker = InMemoryUsernamePasswordDatabaseDontUse<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; checker.<span style="color: black;">addUser</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;foo&quot;</span>, <span style="color: #483d8b;">&quot;bar&quot;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; portal.<span style="color: black;">registerChecker</span><span style="color: black;">&#40;</span>checker<span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; reactor.<span style="color: black;">listenTCP</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1234</span>, pb.<span style="color: black;">PBServerFactory</span><span style="color: black;">&#40;</span>portal<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><br />
&nbsp; &nbsp; reactor.<span style="color: black;">run</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><br />
&nbsp;<br />
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">&#8216;__main__&#8217;</span>:<br />
&nbsp; &nbsp; main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></div>
<p>Myprog1.py</p>
<p>How to run this code: Simply type python Myprog1.py.</p>
<p>The method requestAvatar of the class SimpleRealm is called whenever a user (a pb client here) has been authenticated. This method associates him to a class (here Presence) which contains the allowed remotely callable methods (identified by perspective_*). Here, there is just one method that can be called: getFoo. A PB factory is created to respond to requests from outside, and map successful requests to the SimpleRealm class.</p>
<p>To test this code, you can write a simple PB client that will ask for the getFoo method and get the result. I&#8217;ve done it for you in the file miniclient.py:</p>
<p>Toggle line numbers</p>
<p>   1 # -*- coding: latin-1 -*-<br />
   2 from twisted.spread import pb<br />
   3 from twisted.internet import reactor,stdio,defer<br />
   4 from twisted.python.util import println<br />
   5 from twisted.cred import credentials<br />
   6 from twisted.python import log,logfile<br />
   7 from twisted.protocols import basic<br />
   8<br />
   9 import sys,time,os,ConfigParser<br />
  10<br />
  11<br />
  12 class Client(pb.Referenceable, pb.Broker):<br />
  13     def __init__(self):<br />
  14         pb.Broker.__init__(self, isClient=1)<br />
  15         self.presence = None<br />
  16<br />
  17     # Low LEVEL methods<br />
  18<br />
  19     def run(self):<br />
  20         self.connect()<br />
  21<br />
  22     def connect(self):<br />
  23         user = &#8216;foo&#8217;<br />
  24         password = &#8216;bar&#8217;<br />
  25         log.msg(&#8216;Attempting to connect to server as user %s&#8230;&#8217; % user)<br />
  26<br />
  27         self.factory = pb.PBClientFactory()<br />
  28         reactor.connectTCP(&#8220;localhost&#8221;, 1234, self.factory)<br />
  29         def1 = self.factory.login(credentials.UsernamePassword(user, password),<br />
  30                                 client=self)<br />
  31         def1.addCallbacks(callback=self.connected, errback=self.noLogin)<br />
  32         def1.addCallback(callback=self.action)<br />
  33         def1.addErrback(errback=self.genericError)<br />
  34<br />
  35     def genericError(self, ref) :<br />
  36         log.msg( &#8220;Generic error: %s.&#8221; % ref.getErrorMessage() )<br />
  37<br />
  38     def noLogin(self, reason):<br />
  39         print &#8220;Got rejected, will try in 5 seconds&#8221;, reason<br />
  40         reactor.callLater(5, self.connect)<br />
  41         self.factory.disconnect()<br />
  42         return defer.fail(reason)<br />
  43<br />
  44     def connected(self, perspective):<br />
  45         print &#8220;Connected, got perspective ref:&#8221;, perspective<br />
  46         self.presence = perspective<br />
  47         perspective.notifyOnDisconnect(self.server_disconnected)<br />
  48<br />
  49     def server_disconnected(self, ref):<br />
  50         &#8220;&#8221;" &#8220;&#8221;"<br />
  51         #print &#8220;Server has disconnected, trying to reconnect in 5 seconds&#8221;<br />
  52         #reactor.callLater(5, self.connect)<br />
  53<br />
  54     def shutdown(self):<br />
  55         reactor.stop()<br />
  56<br />
  57     # High LEVEL methods<br />
  58     def action(self,data):<br />
  59         &#8220;&#8221;" &#8220;&#8221;"<br />
  60         log.debug(&#8220;Executing action&#8221;)<br />
  61         df1 = self.presence.callRemote(&#8216;getFromCommon&#8217;,'hello&#8217;)<br />
  62         df1.addCallback(lambda x: println(&#8220;>>>>>>>>> Result: %s&#8221; % x))<br />
  63         df1.addCallback(lambda x: reactor.stop())<br />
  64<br />
  65 if __name__ == &#8216;__main__&#8217;:<br />
  66     log.startLogging(sys.stdout, 0)<br />
  67     c = Client()<br />
  68     c.run()<br />
  69<br />
  70     reactor.run()</p>
<p>miniclient.py</p>
<p>If you have problems understanding deferred, you can read the corresponding HOWTO on http://twistedmatrix.com/projects/core/documentation/howto/defer.html.<br />
4.2. Cleaner, more open, but more verbose code</p>
<p>For a cleaner, more &#8216;Production grade&#8217; source, you can look at this one: Myprog2.py</p>
<p>Toggle line numbers</p>
<p>   1 # -*- coding: latin-1 -*-<br />
   2<br />
   3 from twisted.internet import reactor,defer,app<br />
   4 from twisted.application import service,internet<br />
   5 from twisted.internet import defer<br />
   6 from twisted.spread import pb<br />
   7 from twisted.python import log,logfile<br />
   8 from twisted.cred import portal,checkers,credentials<br />
   9 from twisted.manhole.telnet import ShellFactory<br />
  10<br />
  11 from twisted.cred.portal import Portal,IRealm<br />
  12 from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse<br />
  13 import time,sys<br />
  14<br />
  15 class SimpleRealm:<br />
  16     __implements__ = IRealm<br />
  17<br />
  18     def requestAvatar(self, avatarId, mind, *interfaces):<br />
  19         if pb.IPerspective in interfaces:<br />
  20             p = Presence()<br />
  21             return pb.IPerspective, p, lambda : None<br />
  22         else:<br />
  23             raise NotImplementedError(&#8220;no interface&#8221;)<br />
  24<br />
  25 class Presence(pb.Avatar):<br />
  26     def perspective_getFoo(self):<br />
  27         log.msg(&#8216;getFoo is called&#8217;)<br />
  28         return time.time()<br />
  29<br />
  30 class Agent(service.Service,pb.Referenceable):<br />
  31     def __init__(self, *args, **kw):<br />
  32         self.realm = None<br />
  33<br />
  34     def getRealmResource(self):<br />
  35         self.realm = SimpleRealm()<br />
  36<br />
  37         checker = InMemoryUsernamePasswordDatabaseDontUse()<br />
  38         checker.addUser(&#8220;foo&#8221;, &#8220;bar&#8221;)<br />
  39<br />
  40         p = Portal(self.realm)<br />
  41         p.registerChecker(checker)<br />
  42         return pb.PBServerFactory(p)<br />
  43<br />
  44 if __name__ == &#8216;__main__&#8217;:<br />
  45     log.startLogging(sys.stdout, 0)<br />
  46<br />
  47     application = service.Application(&#8216;Agent&#8217;)<br />
  48     serviceCollection = service.IServiceCollection(application)<br />
  49<br />
  50     pSvc = Agent(&#8216;Agent&#8217;, application)<br />
  51     pSvc.setName(&#8216;Agent&#8217;)<br />
  52     pSvc.setServiceParent(serviceCollection)<br />
  53<br />
  54     shellF = ShellFactory()<br />
  55     shellF.setService(pSvc)<br />
  56     shellF.username = &#8216;admin&#8217;<br />
  57     shellF.password = &#8216;test&#8217;<br />
  58     reactor.listenTCP(8789,shellF)<br />
  59<br />
  60     reactor.listenTCP(1234, pSvc.getRealmResource())<br />
  61     reactor.run()</p>
<p>Myprog2.py</p>
<p>How to run this code: Simply type python Myprog2.py.</p>
<p>The difference with the previous Myprog1.py_ program is that a new class Agent is created, a subclass of service.Service. The reason for doing this is multiple:</p>
<p>    *</p>
<p>      It allows us to have a &#8220;central class&#8221; where you can store your common<br />
          o</p>
<p>            methods to all your eventual different Presences and other methods. You could store them in SimpleRealm (and you&#8217;d be right if your program is really small) but I don&#8217;t think it&#8217;s really clean. For me, the class related to realms is just supposed to contain classes related to user management.<br />
    *</p>
<p>      If you want to use twistd, .tac and other fun Twisted stuff, you have to get an application<br />
          o</p>
<p>            defined. The first child of this application would be an instance of the Agent class.</p>
<p>This code is much cleaner, but longer, but allows to continue developping without barriers like communication between services, etc. This version is launched just by running python and the .py file.<br />
4.3. Code shaped for usage with twistd</p>
<p>In Twisted you have the possibility to launch a .py file with a wrapper, named twistd (note the absence of &#8216;e&#8217;). But to do this, you need to initialize things differently from the method shown in Myprog2.py. Here&#8217;s the code: Myprog3.py</p>
<p>Toggle line numbers</p>
<p>   1 # -*- coding: latin-1 -*-<br />
   2<br />
   3 from twisted.internet import reactor,defer,app<br />
   4 from twisted.application import service,internet<br />
   5 from twisted.internet import defer<br />
   6 from twisted.spread import pb<br />
   7 from twisted.python import log,logfile<br />
   8 from twisted.cred import portal,checkers,credentials<br />
   9 from twisted.manhole.telnet import ShellFactory<br />
  10<br />
  11 from twisted.cred.portal import Portal,IRealm<br />
  12 from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse<br />
  13 import time, sys<br />
  14<br />
  15 class SimpleRealm:<br />
  16     __implements__ = IRealm<br />
  17<br />
  18     def requestAvatar(self, avatarId, mind, *interfaces):<br />
  19         if pb.IPerspective in interfaces:<br />
  20             p = self.getPerspectiveNamed(avatarId)<br />
  21             p.attached(mind)<br />
  22             return (pb.IPerspective, p, lambda p=p, mind=mind: p.detached(mind))<br />
  23         else:<br />
  24             raise NotImplementedError(&#8220;no interface&#8221;)<br />
  25<br />
  26     def getPerspectiveNamed(self, name):<br />
  27         log.msg(&#8216;getPerspective() called for perspective named: %s&#8217; % name)<br />
  28         presence = OnePresence(perspectiveName=name)<br />
  29         presence.setRealm(self)<br />
  30         return presence<br />
  31<br />
  32<br />
  33 class Presence(pb.Avatar):<br />
  34     def __init__(self, perspectiveName, identityName=&#8217;Nobody&#8217;):<br />
  35         self.identity = perspectiveName<br />
  36         self.remote = None<br />
  37         self.realm = None<br />
  38<br />
  39     def setRealm(self, realm): self.realm = realm<br />
  40<br />
  41     def success(self, message): log.msg(&#8216;Success: %s&#8217; % message)<br />
  42     def failure(self, error): log.msg(&#8220;Failure: error received: %s&#8221; % error)<br />
  43<br />
  44     def attached(self, mind):<br />
  45         &#8220;&#8221;" Called when a client connects to this Presence &#8220;&#8221;"<br />
  46         log.msg(&#8216;Attached: mind: %s&#8217; % (mind))<br />
  47         self.remote = mind<br />
  48         return self<br />
  49<br />
  50     def detached(self, remote):<br />
  51         &#8220;&#8221;" Called when a client disconnects from his Presence &#8220;&#8221;"<br />
  52         log.msg(&#8216;Detached: mind: %s&#8217; % (remote))<br />
  53         self.remote = None<br />
  54<br />
  55     def perspective_test(self, text):<br />
  56         log.msg(&#8216;Presence received: %s&#8217; % text)<br />
  57         if self.remote:<br />
  58             return text<br />
  59         else:<br />
  60             print &#8216;no remote?!&#8217;<br />
  61             return None<br />
  62<br />
  63<br />
  64 def OnePresence(Presence):<br />
  65     def perspective_getFoo(self):<br />
  66         log.msg(&#8216;getFoo is called&#8217;)<br />
  67         return time.time()<br />
  68<br />
  69     def perspective_getFromCommon(self, data):<br />
  70         pass<br />
  71<br />
  72<br />
  73 class Agent(service.Service, pb.Referenceable):<br />
  74     def __init__(self, *args, **kw):<br />
  75         self.realm = None<br />
  76<br />
  77     def getRealmResource(self):<br />
  78         self.realm = SimpleRealm()<br />
  79<br />
  80         checker = InMemoryUsernamePasswordDatabaseDontUse()<br />
  81         checker.addUser(&#8220;foo&#8221;, &#8220;bar&#8221;)<br />
  82<br />
  83         p = Portal(self.realm)<br />
  84         p.registerChecker(checker)<br />
  85         return pb.PBServerFactory(p)<br />
  86<br />
  87 ###############################################<br />
  88 application = service.Application(&#8216;Agent&#8217;)<br />
  89 serviceCollection = service.IServiceCollection(application)<br />
  90<br />
  91 pSvc = Agent(&#8216;Agent&#8217;, application)<br />
  92 pSvc.setName(&#8216;Agent&#8217;)<br />
  93 pSvc.setServiceParent(serviceCollection)<br />
  94<br />
  95 shellF = ShellFactory()<br />
  96 shellF.setService(pSvc)<br />
  97 shellF.username = &#8216;admin&#8217;<br />
  98 shellF.password = &#8216;test&#8217;<br />
  99<br />
 100 shell = internet.TCPServer(8789,shellF)<br />
 101 shell.setName(&#8217;shell&#8217;)<br />
 102 shell.setServiceParent(serviceCollection)<br />
 103<br />
 104 tcpServer = internet.TCPServer(1234, pSvc.getRealmResource())<br />
 105 tcpServer.setServiceParent(serviceCollection)</p>
<p>Myprog3.py</p>
<p>How to run this code: use twistd -noy Myprog3.py.</p>
<p>Here, what happens is that twistd looks for an object named application and uses it. So you ABSOLUTELY need to have that object named application. There are some modifications compared to Myprog2.py, where SimpleRealm is more verbose and allows to create different presences.<br />
4.4. Dispatching code in different files/modules</p>
<p>The code is a little longer, making it more difficult to read. So I made another version, where code is split in two files: Myprog4.py and Myprog4Presences.py</p>
<p>Toggle line numbers</p>
<p>   1 # -*- coding: latin-1 -*-<br />
   2<br />
   3 from twisted.internet import reactor,defer,app<br />
   4 from twisted.application import service,internet<br />
   5 from twisted.internet import defer<br />
   6 from twisted.spread import pb<br />
   7 from twisted.python import log,logfile<br />
   8 from twisted.cred import portal,checkers,credentials<br />
   9 from twisted.manhole.telnet import ShellFactory<br />
  10<br />
  11 from twisted.cred.portal import Portal,IRealm<br />
  12 from twisted.cred.checkers import InMemoryUsernamePasswordDatabaseDontUse<br />
  13 import time, sys<br />
  14<br />
  15 from Myprog4Presences import OnePresence<br />
  16<br />
  17 class SimpleRealm:<br />
  18     __implements__ = IRealm<br />
  19<br />
  20     def __init__(self, refServer):<br />
  21         self.refServer = refServer<br />
  22<br />
  23     def requestAvatar(self, avatarId, mind, *interfaces):<br />
  24         if pb.IPerspective in interfaces:<br />
  25             p = self.getPerspectiveNamed(avatarId)<br />
  26             p.attached(mind)<br />
  27             return (pb.IPerspective, p, lambda p=p, mind=mind: p.detached(mind))<br />
  28         else:<br />
  29             raise NotImplementedError(&#8220;no interface&#8221;)<br />
  30<br />
  31     def getPerspectiveNamed(self, name):<br />
  32         log.msg(&#8216;getPerspective() called for perspective named: %s&#8217; % name)<br />
  33         presence = OnePresence(perspectiveName=name)<br />
  34         presence.setRealm(self)<br />
  35         return presence<br />
  36<br />
  37 class Agent(service.Service, pb.Referenceable):<br />
  38     def __init__(self, *args, **kw):<br />
  39         self.realm = None<br />
  40<br />
  41     def getRealmResource(self):<br />
  42         self.realm = SimpleRealm(refServer=self)<br />
  43<br />
  44         checker = InMemoryUsernamePasswordDatabaseDontUse()<br />
  45         checker.addUser(&#8220;foo&#8221;, &#8220;bar&#8221;)<br />
  46<br />
  47         p = Portal(self.realm)<br />
  48         p.registerChecker(checker)<br />
  49         return pb.PBServerFactory(p)<br />
  50<br />
  51     ## Specific code ##########################<br />
  52     def doSomething(self, data):<br />
  53         return &#8220;Hello %s&#8221; % data<br />
  54<br />
  55<br />
  56 ###############################################<br />
  57 application = service.Application(&#8216;Agent&#8217;)<br />
  58 serviceCollection = service.IServiceCollection(application)<br />
  59<br />
  60 pSvc = Agent(&#8216;Agent&#8217;, application)<br />
  61 pSvc.setName(&#8216;Agent&#8217;)<br />
  62 pSvc.setServiceParent(serviceCollection)<br />
  63<br />
  64 # Manhole installation for DEBUGGING only<br />
  65 # Faire &#8220;import __main__&#8221; puis &#8220;service&#8221;, &#8220;service.parent&#8221;  pour voir ce qu&#8217;il y a.<br />
  66 shellF = ShellFactory()<br />
  67 shellF.setService(pSvc)<br />
  68 shellF.username = &#8216;admin&#8217;<br />
  69 shellF.password = &#8216;test&#8217;<br />
  70<br />
  71 shell = internet.TCPServer(8789,shellF)<br />
  72 shell.setName(&#8217;shell&#8217;)<br />
  73 shell.setServiceParent(serviceCollection)<br />
  74<br />
  75 tcpServer = internet.TCPServer(1234, pSvc.getRealmResource())<br />
  76 tcpServer.setServiceParent(serviceCollection)</p>
<p>Myprog4.py</p>
<p>And the file Myprog4Presences.py:</p>
<p>Toggle line numbers</p>
<p>   1 # -*- coding: latin-1 -*-<br />
   2 from twisted.internet import reactor, defer<br />
   3 from twisted.spread import pb<br />
   4 from twisted.python import log<br />
   5<br />
   6 import time<br />
   7<br />
   8 class Presence(pb.Avatar):<br />
   9     def __init__(self, perspectiveName, identityName=&#8217;Nobody&#8217;):<br />
  10         self.identity = perspectiveName<br />
  11         self.remote = None<br />
  12         self.realm = None<br />
  13<br />
  14     def setRealm(self, realm): self.realm = realm<br />
  15<br />
  16     def success(self, message): log.msg(&#8216;Success: %s&#8217; % message)<br />
  17     def failure(self, error): log.msg(&#8220;Failure: error received: %s&#8221; % error)<br />
  18<br />
  19     def attached(self, mind):<br />
  20         &#8220;&#8221;" Called when a client connects to this Presence &#8220;&#8221;"<br />
  21         log.msg(&#8216;Attached: mind: %s&#8217; % (mind))<br />
  22         self.remote = mind<br />
  23         return self<br />
  24<br />
  25     def detached(self, remote):<br />
  26         &#8220;&#8221;" Called when a client disconnects from his Presence &#8220;&#8221;"<br />
  27         log.msg(&#8216;Detached: mind: %s&#8217; % (remote))<br />
  28         self.remote = None<br />
  29<br />
  30     def perspective_test(self, text):<br />
  31         log.msg(&#8216;Presence received: %s&#8217; % text)<br />
  32         if self.remote:<br />
  33             return text<br />
  34         else:<br />
  35             print &#8216;no remote?!&#8217;<br />
  36             return None<br />
  37<br />
  38<br />
  39 class OnePresence(Presence):<br />
  40     def perspective_getFoo(self):<br />
  41         log.msg(&#8216;getFoo is called&#8217;)<br />
  42         return time.time()<br />
  43<br />
  44     def perspective_getFromCommon(self, data):<br />
  45         return self.realm.refServer.doSomething(data)</p>
<p>Myprog4Presences.py</p>
<p>How to run this code: use twistd -noy Myprog4.py.</p>
<p>Besides splitting the classes in different files, I added an example of perspective (perspective_getFromCommon) that goes to the &#8220;main application&#8221; (in fact the root of the tree where you have the app, then the simulation realm, and then the presences) to execute a &#8216;common&#8217; method. Note: This code uses the ex-manhole stuff (now ShellFactory) to allow connection to the program while running. I&#8217;ll make a small tutorial on this later.<br />
4.5. Using .tac file to finish the skeleton</p>
<p>Finally, we&#8217;re at the last step of achieving our &#8216;perfect pattern program&#8217; in Twisted. The last thing to do, is to create a .tac file. Why? Well, it&#8217;s not useful, but it&#8217;s a requirement for building a service under Windows. A .tac is really simple: it&#8217;s just the &#8216;main&#8217; part of the program put in a separate file with an extension &#8216;.tac&#8217;: Myprog5.py, Myprog5Presences.py and Myprog5.tac</p>
<p>from twisted.internet import reactor<br />
from twisted.application import service,internet<br />
from twisted.manhole.telnet import ShellFactory</p>
<p>from Myprog5 import Agent</p>
<p>application = service.Application(&#8216;Agent&#8217;)<br />
serviceCollection = service.IServiceCollection(application)</p>
<p>pSvc = Agent(&#8216;Agent&#8217;, application)<br />
pSvc.setName(&#8216;Agent&#8217;)<br />
pSvc.setServiceParent(serviceCollection)</p>
<p># Manhole installation for DEBUGGING only<br />
# Faire &#8220;import __main__&#8221; puis &#8220;service&#8221;, &#8220;service.parent&#8221;  pour voir ce qu&#8217;il y a.<br />
shellF = ShellFactory()<br />
shellF.setService(pSvc)<br />
shellF.username = &#8216;admin&#8217;<br />
shellF.password = &#8216;test&#8217;</p>
<p>shell = internet.TCPServer(8789,shellF)<br />
shell.setName(&#8217;shell&#8217;)<br />
shell.setServiceParent(serviceCollection)</p>
<p>Myprog5.tac</p>
<p>How to run this code: use twistd -noy Myprog5.tac.<br />
4.6. Final note and update</p>
<p>As you surely know, Twisted is a fast moving target, it seems it is now the usage not to use internet.TCP/UDP* anymore, but the method strports.service(), which will surely allows in the future to pass the information on the twistd command-line.</p>
<p>As an example, now you just need to replace the following code:<br />
Toggle line numbers</p>
<p>   1 tcpServer = internet.TCPServer(1234, pSvc.getRealmResource())<br />
   2 tcpServer.setServiceParent(serviceCollection)</p>
<p>With:<br />
Toggle line numbers</p>
<p>   1 from twisted.application import strports<br />
   2 [...]<br />
   3 tcpServer = strports.service(&#8216;tcp:1234&#8242;,pSvc.getRealmResource())<br />
   4 tcpServer.setServiceParent(serviceCollection)</p>
<p>5. Making a service of the program</p>
<p>This section is now specific to Windows.</p>
<p>How to create a service, having a python program? The only way I know is to use the py2exe_ program whose initial goal is to find all the dependencies (modules and libraries), make an archive of it, and create an executable of the main program. The goal is to be able to easily distribute some python program without having requirements like &#8216;python must be installed, wxPython and wax modules have to be present on version >x.y&#8217;. Another advantage of py2exe is to allow the developer to choose how your program is compiled. It can be of three formats: console, window, com_server or service. For testing purposes, it is best to use &#8216;console&#8217; mode, which, when your program will be launched, will open a Windows shell and run your program inside, making it easy to see any exception or other error.</p>
<p>To use py2exe, we&#8217;ll have to create a setup.py file because py2exe uses the nice distutils module which should always be installed with python by default on ANY distribution.</p>
<p>We&#8217;ll first try to compile our program as a console app. Normally, for a normal python program the setup.py file would be as simple as running python setup.py build:<br />
Toggle line numbers</p>
<p>   1 from distutils.core import setup<br />
   2 import py2exe<br />
   3<br />
   4 setup(console=["myscript.py"])</p>
<p>When this works correctly, you can continue (the hard part) to transform your program into a Windows service. Now that your program runs in a console, we&#8217;ll make it a service. What are the advantages of making of your program a service? Simple, you can launch your service before anyone logs on, at the machine boot, that means you&#8217;re not attached to the presence of a user logged on. That allows you to secure a little more you application by setting the owner/runner of the service a least privileged user. Another reason is that you can easily start/stop/restart your service graphically by clicking in the Windows Service Manager.</p>
<p>For a normal python program that&#8217;s not really a problem, here&#8217;s the corresponding setup.py file:<br />
Toggle line numbers</p>
<p>   1 from distutils.core import setup<br />
   2 import py2exe<br />
   3<br />
   4 setup(service=["MyService"])</p>
<p>Here, you&#8217;ll need to have an attribute _svc_name_ in a module named MyService.</p>
<p>OK. That&#8217;s easy, you say, and you&#8217;re right. The only problem is that **this doesn&#8217;t work if you&#8217;re using Twisted**. The main reason is that that class containing the _svc_name_ has to be a loop, where you have a start, a stop, etc. That means you&#8217;ll be stuck running this loop, and not the reactor :-(</p>
<p>Moreover, we want to be able to run our program which is in a .tac, and with twistd. So we&#8217;ll have to use a supplementary module, written by Moonfallen, available in his svn sandbox (svn co svn://svn.twistedmatrix.com/svn/Twisted/sandbox/moonfallen). You can view it using the web interface on http://svn.twistedmatrix.com/cvs/sandbox/moonfallen/ . You&#8217;ll get the following files::</p>
<p>lstep@nefesh moonfallen $ ll<br />
total 92<br />
drwxr-xr-x  4 lstep users   280 Jun 20 17:49 ./<br />
drwxr-xr-x  4 lstep users   112 Jun 20 17:49 ../<br />
drwxr-xr-x  7 lstep users   296 Jun 20 17:49 .svn/<br />
-rw-r&#8211;r&#8211;  1 lstep users  3163 Jun 20 17:49 README.txt<br />
-rwxr-xr-x  1 lstep users   772 Jun 20 17:49 TODO.txt*<br />
-rw-r&#8211;r&#8211;  1 lstep users 49833 Jun 20 17:49 modulegraph.zip<br />
drwxr-xr-x  3 lstep users   200 Jun 20 17:49 ntsvc/<br />
-rwxr-xr-x  1 lstep users   766 Jun 20 17:49 pysvc.ico*<br />
-rw-r&#8211;r&#8211;  1 lstep users   799 Jun 20 17:49 serviceinfo.ini<br />
-rw-r&#8211;r&#8211;  1 lstep users 21751 Jun 20 17:49 tpusage.py</p>
<p>Install them in the directory where you put your setup.py file. and unzip modulegraph.zip in your site-packages directory (follow the instructions in the README).<br />
6. Bug in Py2exe 0.5.4</p>
<p>If you just installed Py2exe without patching it, you will certainly end-up with an error when you&#8217;ll try to run your program (a can&#8217;t find module linecache or os). As written in moonfallen&#8217;s README, you have to patch the boot_service.py file which should be in C:\Python24\site-packages\py2exe::</p>
<p>&#8212; boot_service.py     2004-11-03 11:02:31.147398500 -0800<br />
+++ boot_service.py.new 2004-11-03 11:02:19.522844900 -0800<br />
@@ -9,7 +9,11 @@<br />
service_klasses = []<br />
try:<br />
   for name in service_module_names:<br />
      mod = __import__(name)<br />
    + # Use the documented fact that when a fromlist is present,<br />
    + # __import__ returns the innermost module in &#8220;name&#8221;.<br />
    + # This makes it possible to have a dotted name work the<br />
    + # way you would expect.<br />
    + mod = __import__(name, globals(), locals(), ["DUMMY"])<br />
      for ob in mod.__dict__.values():<br />
          if hasattr(ob, &#8220;_svc_name_&#8221;):<br />
             service_klasses.append(ob)</p>
<p>7. How to write the setup.py file</p>
<p>Modify the setup.py to use ntsvc:<br />
Toggle line numbers</p>
<p>   1 from distutils.core import setup<br />
   2 import py2exe<br />
   3 import os,sys,glob<br />
   4 import ntsvc<br />
   5<br />
   6 data_files = [<br />
   7     ('', ['afile.conf']),<br />
   8     ]<br />
   9<br />
  10 setup(appconfig=&#8217;Myprog5.tac&#8217;, options =<br />
  11   {&#8216;twistedservice&#8217;:<br />
  12        {&#8216;dll_excludes&#8217;: ['tk84.dll','tcl84.dll'],<br />
  13        },<br />
  14        &#8216;py2exe&#8217;: {&#8216;optimize&#8217;:2,},<br />
  15   },<br />
  16   data_files = data_files<br />
  17   )</p>
<p>And then run python setup.py twistedservice. You should have an output that looks like this:</p>
<p>    running twistedservice<br />
    I: finding modules imported by agent.tac<br />
    *** searching for required modules ***<br />
    *** parsing results ***<br />
    creating python loader for extension &#8216;py2exe.py2exe_util&#8217;<br />
    creating python loader for extension &#8217;servicemanager&#8217;<br />
    creating python loader for extension &#8216;win32pipe&#8217;<br />
    creating python loader for extension &#8216;_tkinter&#8217;<br />
    creating python loader for extension &#8216;win32service&#8217;<br />
    creating python loader for extension &#8216;win32api&#8217;<br />
    [...]<br />
    creating python loader for extension &#8216;perfmon&#8217;<br />
    *** finding dlls needed ***<br />
    *** create binaries ***<br />
    *** byte compile python files ***<br />
    skipping byte-compilation of C:\Python24\lib\ConfigParser.py to ConfigParser.pyc<br />
    skipping byte-compilation of C:\Python24\lib\Queue.py to Queue.pyc<br />
    [...]<br />
    *** copy extensions ***<br />
    *** copy dlls ***<br />
    *** copy data files ***<br />
    setting sys.winver for &#8216;C:\TAL\agent-windows\dist\python24.dll&#8217; to &#8216;py2exe&#8217;<br />
    copying C:\Python24\lib\site-packages\py2exe\run.exe -> C:\TAL\agent-windows\dist\agentctl.exe<br />
    The following modules appear to be missing<br />
    ['Crypto.Cipher', 'FCNTL', 'OpenSSL', '_ssl', 'hexdump', 'resource']</p>
<p>The missing libraries at the end of the generation is not a problem if you don&#8217;t use them (they&#8217;re mostly crypto related).<br />
8. What you get</p>
<p>What python setup.py twistedservice does is:</p>
<p>    *</p>
<p>      Create a directory named dist (and build, but less important)<br />
    *</p>
<p>      Analyzes all the dependencies of your python code<br />
    *</p>
<p>      Copy all the dependent modules and dependent libraries to that dist directory<br />
    *</p>
<p>      Generate a library.zip with all the libraries.<br />
    *</p>
<p>      In our case (because we chose to use &#8217;service&#8217; in the setup.py file), we got an executable with the name of our .tac with ctl appended to it.</p>
<p>Here&#8217;s an example of the content of the dist directory:</p>
<p>    Le volume dans le lecteur C n&#8217;a pas de nom.</p>
<p>    Repertoire de C:\TAL\AGENT\dist</p>
<p>    24/06/2005  11:25    <REP>          .<br />
    24/06/2005  11:25    <REP>          ..<br />
    07/06/2005  12:46               295 Agent.conf<br />
    07/06/2005  16:24             2461 agent.tac<br />
    24/06/2005  11:25            13312 agentctl.exe<br />
    24/06/2005  11:25         4053167 library.zip<br />
    07/06/2005  15:23               107 ntsvc.cfg<br />
    30/03/2005  09:51            12288 perfmon.pyd<br />
    22/10/2004  20:00             9728 py2exe_util.pyd<br />
    30/03/2005  09:51           135168 pyexpat.pyd<br />
    30/03/2005  09:51         1867776 python24.dll<br />
    30/03/2005  09:51           311296 pythoncom24.dll<br />
    30/03/2005  09:51            98304 pywintypes24.dll<br />
    30/03/2005  09:51             8192 select.pyd<br />
    30/03/2005  09:51            23552 servicemanager.pyd<br />
    24/06/2005  11:23    <REP>          tcl<br />
    30/03/2005  09:51           405504 unicodedata.pyd<br />
    30/03/2005  09:51             4608 w9xpopen.exe<br />
    30/03/2005  09:51            69632 win32api.pyd<br />
    30/03/2005  09:51            15872 win32pipe.pyd<br />
    30/03/2005  09:51            26624 win32process.pyd<br />
    30/03/2005  09:51            29696 win32service.pyd<br />
    30/03/2005  09:51           651264 win32ui.pyd<br />
    30/03/2005  09:51            65536 zlib.pyd<br />
    30/03/2005  09:51            49152 _socket.pyd<br />
    30/03/2005  09:51            40960 _tkinter.pyd<br />
    27/05/2005  14:07            11264 _zope_interface_coptimizations.pyd</p>
<p>For example, if our .tac file was agent.tac, we would end up with an executable named agentctl.exe. if we run it, we see that it&#8217;s a &#8220;control program&#8221; to add/remove our newly made service:</p>
<p>      Services are supposed to be run by the system after they have been installed.<br />
    These command line options are available for (de)installation:<br />
            -help<br />
            -install<br />
            -remove<br />
            -auto<br />
            -disabled<br />
            -interactive<br />
            -user: <arg><br />
            -password: <arg></p>
<p>    Connecting to the Service Control Manager</p>
<p>If you run agentctl.exe -install, and then look in the Windows Service GUI, you should see a new line:</p>
<p>[attachment:service.png]</p>
<p>You&#8217;ll just have to right-click on it and click on Start Service.<br />
9. Add-on: how to make an installation file</p>
<p>OK, now you have a directory that you can distribute, without having to require Python, Twisted and other dependencies. But it&#8217;s a directory. You can zip it, but it&#8217;s not very efficient, especially if you have to be able to remove it later, or deploy it on several machines.</p>
<p>What I recommend is to use the new installation format, used by the official Python package too, that is, MSI.<br />
9.1. Generating an MSI package</p>
<p>Generating an MSI file is really easy, especially if you&#8217;re using Windows XP, as the kit is already included, otherwise you&#8217;ll have to download it from Microsoft&#8217;s website.</p>
<p>To summarize: to generate an MSI you&#8217;ll have to create **an xml file** where you have quite a lot of variables (program path, name of program, files to copy, etc.). This is quite long, and, without a GUI that does it for you, it&#8217;s nearly impossible. That&#8217;s why I recommend you Installer2Go_. It&#8217;s a really nice freeware (there&#8217;s a registered version if you want support) that allows you to build your .msi all by just clicking:</p>
<p>[attachment:i2g2.png]</p>
<p>You can even define the automatic registration and the removal of you service:</p>
<p>[attachment:i2g1.png]</p>
<p>That&#8217;s all for now. It&#8217;s the first release of this document, so there may be some typo errors. I checked all the Myprog*.py, they all work on my machine (Python2.3 or Python2.4, Twisted 1.3 or Twisted 2.0.1). Don&#8217;t hesitate to comment/correct/update by writing an email to luc <dot> stepniewski <at> adelux.fr<br />
10. References</p>
<p>    *</p>
<p>http://starship.python.net/crew/theller/moin.cgi/Py2Exe</p>
<p>    *</p>
<p>http://svn.twistedmatrix.com/cvs/sandbox/moonfallen/</p>
<p>    *</p>
<p>http://twistedmatrix.com/~moonfallen/</p>
<p>    *</p>
<p>http://svn.twistedmatrix.com/cvs/sandbox/moonfallen/README.txt?view=auto</p>
<p>    *</p>
<p>http://www.installsite.org/pages/en/msi/authoring.htm</p>
<p>    *</p>
<p>http://www.dev4pc.com/installer2go.html</p>
<p>    *</p>
<p>http://www.qwerty-msi.com/</p>
<p>    *</p>
<p>http://www.aksdb.org/downloads.php</p>
<p>    *</p>
<p>http://msi2xml.sourceforge.net/</p>
<p>    *</p>
<p>http://desktopengineer.com/index.php?topic=0070MSI</p>
<p>    *</p>
<p>      py2exe<br />
    *</p>
<p>      Installer2Go</p>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/software/twisted/deploying-twisted-python-on-windows/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twisted Weekly News #11</title>
		<link>http://www.gradstein.info/software/twisted/twisted-weekly-news-11/</link>
		<comments>http://www.gradstein.info/software/twisted/twisted-weekly-news-11/#comments</comments>
		<pubDate>Tue, 17 Feb 2004 16:53:24 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=309</guid>
		<description><![CDATA[Twisted Weekly News #11
Author: 	Lior Gradstein
Contact: 	lior@gradstein.info
Revision: 	1.0
Date: 	2004/2/17 14:13:20
Copyright: 	© The Twisted Community
Contents

The Twisted Weekly News
Discussions
Articles/Sites related to Twisted
Cool Things of the Week
New/Updated Cool Software
Current releases


So many announcements and new Twisted based software! This week&#8217;s TWN (especially because it is merged with previous week) is full of really cool news/articles/software that will keep you [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Twisted Weekly News #11<br />
Author: 	Lior Gradstein<br />
Contact: 	lior@gradstein.info<br />
Revision: 	1.0<br />
Date: 	2004/2/17 14:13:20<br />
Copyright: 	© The Twisted Community</strong></p>
<p><strong>Contents</strong></p>
<ul>
<li>The Twisted Weekly News</li>
<li>Discussions</li>
<li>Articles/Sites related to Twisted</li>
<li>Cool Things of the Week</li>
<li>New/Updated Cool Software</li>
<li>Current releases</li>
</ul>
<p><span id="more-309"></span><br />
So many announcements and new Twisted based software! This week&#8217;s TWN (especially because it is merged with previous week) is full of really cool news/articles/software that will keep you busy for at least two months.</p>
<p>If you have any new information, ideas, announcements for the next TWN, please write to me,
<lior@gradstein.info>. TWN is also available as HTML formated ReST on <a href="http://gradstein.info/articles/twisted_news/twn11" class="liinternal">http://gradstein.info/articles/twisted_news/twn11</a><br />
The Twisted Weekly News</p>
<p>11th Issue. Tuesday, February 17, 2004</p>
<p>QOTW:</p>
<p><moshez> Twisted: Just Because It&#8217;s Not Documented and Unstable Doesn&#8217;t Mean You Shouldn&#8217;t Use It</p>
<p><strong>Discussions</strong></p>
<ul>
<li><a href="http://twistedmatrix.com/pipermail/twisted-python/2003-December/006856.html" class="liexternal">David Bolen</a> asked if there was a way to keep the references to the remote PB object when a disconnect happened, and reconnect all automatically. <a href="http://twistedmatrix.com/pipermail/twisted-python/2003-December/006869.html" class="liexternal">Jp Calderone replied</a> that, in its current shape, it is not possible, because the references are reinitialized when the connection is re-enabled. But he said this would not be too hard to implement.</li>
<li><a href="http://twistedmatrix.com/pipermail/twisted-python/2004-February/007039.html" class="liexternal">Stephen Waterbury</a> posted a code example on how to interface twisted.cred with a database where the user/pass is stored. A few days later, Stephen <a href="http://twistedmatrix.com/pipermail/twisted-python/2004-February/007063.html" class="liexternal">posted another example</a>, less trivial, showing web auth against a db.</li>
<li><a href="http://twistedmatrix.com/pipermail/twisted-python/2004-February/007057.html" class="liexternal">Martin Stenhard</a> asked how to get the remote ip address of a connecting client, if the connection is made using PB.</li>
<li><a href="http://twistedmatrix.com/pipermail/twisted-python/2004-February/007074.html" class="liexternal">David A. Leedom</a> asked for some advice on how he should design a remote backup architecture using Twisted. Michal Pasternak replied that he should pay a lot of attention on the size of transmitted data, as PB limits paramaters to 640KB max.</li>
</ul>
<p><strong>Articles/Sites related to Twisted</strong></p>
<ul>
<li><strong>Nevow</strong>: A Web Application Construction Kit (http://soundfarmer.com/content/nevow.html) fzZzy wrote a proposal to give a talk on nevow at this year&#8217;s PyCon. It turns out to be a good overview of what nevow is about.</li>
<li><a href="http://planet.twistedmatrix.com/" class="liexternal">Planet Twisted</a> A new website which is a blog of all the Twisted developers blogs.</li>
<li><a href="http://www.onlamp.com/pub/a/python/2004/01/15/twisted_intro.html" class="liexternal">Article about Twisted Networking</a> Itamar wrote an introductory article about Twisted networking.</li>
<li><a href="http://www.onlamp.com/pub/a/python/2004/02/12/advanced_nio.html" class="liexternal">Understanding Network I/O, Part 2</a> Article by George Belotsky, on how to achieve network asynchronous I/O with examples of code in asyncore,twisted,threads, etc.</li>
</ul>
<p><strong>Cool Things of the Week</strong></p>
<ul>
<li>Rebirth of <a href="http://ulaluma.com/pyx/" class="liexternal">pyx/fzZzy blog</a>  fzZzy has renewed his blog, with information about nevow and the successor to LivePage named liveevil. A first (very) impressive example is a chat application, located on http://soundfarmer.com/content/code/chatola/ .</li>
<li><a href="http://divmod.org/users/slyphon.twistd/nevow/moin.cgi/" class="liexternal">Nevow Wiki</a> A survey is online showing who&#8217;s doing what with Nevow today. There are many really interesting projects going on!</li>
<li>Beyond2 (http://www.asbahr.com/beyond.html) Beyond 2 builds upon the Twisted server and extends it to enable arbitrary 3D clients to connect to a common simulation framework. Twisted provides object persistence, remote method invocation, database integration, and more. The project seems to restart/continue, with the help of Nafai and lstep. A Wiki has been set up on http://www.beyond2.org/</li>
<li>Twisted Forum (http://twisted.banquise.org/) Some new sections have been added to the forum (Snippets, PB)</li>
</ul>
<p><strong>New/Updated Cool Software</strong></p>
<ul>
<li><a href="http://sourceforge.net/projects/upstage" class="liexternal">UpStage</a> A complex chat application that allows streaming of video.</li>
<li><a href="http://freshmeat.net/redir/beepy/31931/url_homepage/beepy.sourceforge.net" class="liexternal">BEEP protocol</a> The BEEPy Python BEEP Library is an implementation of the Blocks Extensible Exchange Protocol (RFC3080), written as a Python library. The difference with the previous version, is that it is now implemented with Twisted! (&#8220;It is now implemented using the Twisted framework for fast, asynchronous network communications&#8221;).</li>
<li><a href="http://shtoom.sourceforge.net/" class="liexternal">Shtoom</a> Shtoom is a pure python implementation of a Voice over IP software phone.</li>
<li><a href="http://thorne.ath.cx/~stephen/software.html" class="liexternal">Trash</a> &#8216;Trash&#8217; a pastebin application written using the Twisted framwork (using woven).</li>
<li><a href="http://www.stranex.com/~perspex/gosiege/" class="liexternal">GoSiege</a> A game on the Go game model, but in a online multiplayer (MMOG) mode. The code is really a very good example of well written code (at least from my point of view). I recommend it if you&#8217;re looking for PB example code.</li>
<li><a href="http://slarty.polito.it:8069/~sciasbat/wiki/moin.cgi/twibber" class="liexternal">Twibber</a> Version 0.2.0pre1, twibber is a Python package aimed at handling the Jabber &#8211; XMMP protocol in a completely asynchronous way.</li>
<li>Crow&#8217;s Nest (http://crowsnest.sourceforge.net/) Crow&#8217;s Nest is a project designed to help collect log information from various sources and to apply some filter to them in a very modular way.</li>
<li><a href="http://petmail.lothar.com/" class="liexternal">PETMail</a> PETMail is a permission-based anti-spam replacement for SMTP, using recipient-defined CAPTCHA challenges for new senders, automatic (but revocable) permission-granting for most correspondents, encrypted and signed (but pseudonymous) messages, and provisions for easily changing addresses or transports (including a mechanism to publish remailer SURBs as a destination).</li>
<li><a href="http://peak.telecommunity.com/" class="liexternal">PEAK 0.5a2</a> (Not directly related to Twisted, but allows the developer to use the twisted reactor). The third alpha is available. That version includes a new framework (peak.events) that allows the developer to make his programs more event-driven (in the sense of subscribers/observers). The event loop, as usual, can be set to be Twisted&#8217;s reactor.</li>
</ul>
<p><strong>Current releases</strong></p>
<ul>
<li>Twisted: 1.1.1 (released 2003-12-10) (devel version: 1.1.2alpha2)</li>
<li>Quotient: 0.8.8 (released 2003-12-12)</li>
<li>Twisted Java: 0.6.1 (released 2003-12-02)</li>
<p>Ok, that&#8217;s it for this week. Thanks for reading!</p>
<p>Lior Gradstein
<lior@gradstein.info>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/software/twisted/twisted-weekly-news-11/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twisted Weekly News #9</title>
		<link>http://www.gradstein.info/software/twisted/twisted-weekly-news-9/</link>
		<comments>http://www.gradstein.info/software/twisted/twisted-weekly-news-9/#comments</comments>
		<pubDate>Sun, 14 Dec 2003 17:24:44 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=325</guid>
		<description><![CDATA[Twisted Weekly News #9
Author: 	Lior Gradstein
Contact: 	lior@gradstein.info
Revision: 	1.0
Date: 	2003-12-14
Copyright: 	© The Twisted Community
Contents
    * The Twisted Weekly News
    * Discussions
    * Progress
    * Cool Thing of the Week
    * Current releases
If you have any new information, ideas, announcements for the [...]]]></description>
			<content:encoded><![CDATA[<p>Twisted Weekly News #9<br />
Author: 	Lior Gradstein<br />
Contact: 	lior@gradstein.info<br />
Revision: 	1.0<br />
Date: 	2003-12-14<br />
Copyright: 	© The Twisted Community</p>
<p>Contents</p>
<p>    * The Twisted Weekly News<br />
    * Discussions<br />
    * Progress<br />
    * Cool Thing of the Week<br />
    * Current releases</p>
<p>If you have any new information, ideas, announcements for the next TWN, please write to me,
<lior@gradstein.info>. TWN is also available as HTML formated ReST on http://gradstein.info/articles/twisted_news/twisted_news/twn9<br />
The Twisted Weekly News</p>
<p>9th Issue. Sunday, December 14, 2003</p>
<p>QOTW:</p>
<p><moshez> dash: being squishy is pleasant for everyone always<br />
<dash> moshez: i demand proof<br />
<moshez> dash: it is an AXIOM!!<br />
<moshez> dash: squishing is part of the basic axiom set<br />
<moshez> like DeCartes said &#8220;I squish therefore I am&#8221;</p>
<p>Discussions</p>
<p>        * http://twistedmatrix.com/pipermail/twisted-python/2003-December/006692.html RodrigoB suggested to use Twisted for the refactoring of The Circle, a P2P app.<br />
        * http://twistedmatrix.com/pipermail/twisted-python/2003-December/006705.html Last week, someone asked for an example of a Jabber client using Twisted libs, darryl posted a reply this week. darryl posted another example using PEAK too (http://randomthoughts.vandorp.ca/syncato/WK/blog/671?t=projects)<br />
        * http://twistedmatrix.com/pipermail/twisted-python/2003-December/006723.html Cinober explains his discoveries on debugging Twisted code within Emacs. Itamar gave a more generic explanation on how to debug general python code (http://twistedmatrix.com/pipermail/twisted-python/2003-December/006724.html)<br />
        * http://twistedmatrix.com/pipermail/twisted-python/2003-December/006745.html Richard Livsey asked why his IRC bot gets disconnected without any possibility of reconnection after sending too much data to the server. Timothee Besset replied he should read the IRC RFCs, that explains that his IRC bot was banned (flooding protection) and that he should use a rate limiting algorithm which doesn&#8217;t yet exist in Twisted IRCClient implementation. Andrew Bennetts answered that, actually, there is a rate limiting method, but it is more a delay than a rate limitation (http://twistedmatrix.com/pipermail/twisted-python/2003-December/006749.html) which solved Richard&#8217;s problem.</p>
<p>Progress</p>
<p>        * Twisted 1.1.1: Itamar announced Twisted 1.1.1 as the official new stable release (http://twistedmatrix.com/pipermail/twisted-python/2003-December/006731.html). The changes are mainly bugfixes and minor improvements. MSN8P support in the MSN protocol has been updated and Conch SSH agent client now supports SSH auth agent.<br />
        * Quotient 0.8.8: A new version (0.8.8) of Quotient (http://www.divmod.org/) has been released. The pace of releases is getting faster each week. In this release (except from bugfixes), the database has been simplified and throttling tools have been added. To show that Quotient can be used as a framework not just for email, a project planning tool has been started (Anvil).</p>
<p>Cool Thing of the Week</p>
<p>        * Twisted-web split A new mailing list (http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-web and stored on NNTP gmane.org) as well as a new IRC channel (irc://irc.freenode.net/#twisted.web) who focus on twisted.web and woven/nevow part of Twisted.</p>
<p>Current releases</p>
<p>        * Twisted: 1.1.1 (released 2003-12-10)<br />
        * Quotient: 0.8.8 (released 2003-12-12)<br />
        * Twisted Java: 0.6.1 (released 2003-12-02)</p>
<p>Ok, that&#8217;s it for this week. Thanks for reading!</p>
<p>Lior Gradstein
<lior@gradstein.info>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/software/twisted/twisted-weekly-news-9/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twisted Weekly News #10</title>
		<link>http://www.gradstein.info/software/twisted/twisted-weekly-news-10/</link>
		<comments>http://www.gradstein.info/software/twisted/twisted-weekly-news-10/#comments</comments>
		<pubDate>Sun, 23 Nov 2003 17:25:27 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=327</guid>
		<description><![CDATA[Twisted Weekly News #10
Author: 	Lior Gradstein
Contact: 	lior@gradstein.info
Revision: 	1.0
Date: 	2003-11-23
Copyright: 	© The Twisted Community
Contents
    * The Twisted Weekly News
    * Discussions
    * Cool Thing of the Week
    * Current releases
There wasn&#8217;t too much mail this week, so I merged the previous TWN with the [...]]]></description>
			<content:encoded><![CDATA[<p>Twisted Weekly News #10<br />
Author: 	Lior Gradstein<br />
Contact: 	lior@gradstein.info<br />
Revision: 	1.0<br />
Date: 	2003-11-23<br />
Copyright: 	© The Twisted Community</p>
<p>Contents</p>
<p>    * The Twisted Weekly News<br />
    * Discussions<br />
    * Cool Thing of the Week<br />
    * Current releases</p>
<p>There wasn&#8217;t too much mail this week, so I merged the previous TWN with the current, as I was ill last week.</p>
<p>If you have any new information, ideas, announcements for the next TWN, please write to me,
<lior@gradstein.info>. TWN is also available as HTML formated ReST on http://gradstein.info/articles/twisted_news/twisted_news/twn10<br />
The Twisted Weekly News</p>
<p>9&#038;10th Issue. Sunday, December 28, 2003</p>
<p>QOTW::</p>
<p>    http://twistedmatrix.com/pipermail/twisted-python/2003-December/006789.html From a mail by Alan McIntyre: &#8220;I just wanted to thank the Twisted developers for making such a cool piece of software. [...] Thanks to Twisted and Python, I was able to start from scratch and put together a server to present some of this data via XML-RPC in about 2 or 3 hours (and that includes looking up a lot of stuff in the documentation).&#8221;</p>
<p>Discussions</p>
<p>        * http://twistedmatrix.com/pipermail/twisted-python/2003-December/006786.html Jonathan Simms asked for help on his new (new) ftp server code which is currently in sandbox. He asks for help to resolve some problems with authentication on the Windows side.<br />
        * http://twistedmatrix.com/pipermail/twisted-python/2003-December/006828.html More and more people are becoming interested in integrating Twisted stuff into their projects. Last week, RodrigB asked about The Circle. This week, Valentino Volonghi asks about the possibility (wish) to replace the pygame event loop with a Twisted reactor.<br />
        * http://twistedmatrix.com/pipermail/twisted-python/2003-December/006820.html Michal Pasternak made some tests on Twisted, and noticed some performance degradation after 40 simultaneous connections. Itamar replied there wasn&#8217;t anything hardcoded that would change Twisted behaviour above 40 simultaneous connections.</p>
<p>Cool Thing of the Week</p>
<p>        * Treasure of code examples and tutorials for nevow (http://www.livejournal.com/users/fzzzy/) fzZzy updated his new blog on LiveJournal with a lot of code samples he wrote for people who asked questions on irc. The second lecture he gave on irc is also available (http://soundfarmer.com/content/logs/NevowLecture2-121503.txt). With these docs and the previous more &#8220;in-depth&#8221; documentation from justinj (http://stewstuff.com/doc/nevow.xhtml) you do not any excuse for not learning nevow!<br />
        * SFTP support in Zope (using Twisted!) (http://twistedmatrix.com/pipermail/twisted-python/2003-December/006839.html) Fred L. Drake, Jr. wrote some support (http://cvs.zope.org/Packages/SFTPGateway/)for the sftp protocol to be included in Zope. The result may be available as a separate product in a near future.<br />
        * Impacket (http://oss.corest.com/projects/impacket.html) Not related to Twisted, but interesting anyway.Itamar recommended us to take a look at this python library which provides low-level programmatic access to network packets (tcp, udp, etc.). There is also a python pcap implementation on their web site.<br />
        * Reminder about the web forum (http://twisted.banquise.org/) May I remind you that a web interface exists for those that prefer reading informations online? We&#8217;re barely 8 now, but nobody posts anything which can be discussed :-(</p>
<p>Current releases</p>
<p>        * Twisted: 1.1.1 (released 2003-12-10)<br />
        * Quotient: 0.8.8 (released 2003-12-12)<br />
        * Twisted Java: 0.6.1</p>
<p>Ok, that&#8217;s it for this week. Thanks for reading!</p>
<p>Lior Gradstein
<lior@gradstein.info>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/software/twisted/twisted-weekly-news-10/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twisted Weekly News #8</title>
		<link>http://www.gradstein.info/software/twisted/twisted-weekly-news-8/</link>
		<comments>http://www.gradstein.info/software/twisted/twisted-weekly-news-8/#comments</comments>
		<pubDate>Sun, 23 Nov 2003 17:23:46 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=323</guid>
		<description><![CDATA[Twisted Weekly News #8
Author: 	Lior Gradstein
Contact: 	lior@gradstein.info
Revision: 	1.0
Date: 	2003-11-23
Copyright: 	© The Twisted Community
Contents
    * The Twisted Weekly News
    * Discussions
    * Progress
    * Cool Thing of the Week
If you have any new information, ideas, announcements for the next TWN, please write to me,
.
The [...]]]></description>
			<content:encoded><![CDATA[<p>Twisted Weekly News #8<br />
Author: 	Lior Gradstein<br />
Contact: 	lior@gradstein.info<br />
Revision: 	1.0<br />
Date: 	2003-11-23<br />
Copyright: 	© The Twisted Community</p>
<p>Contents</p>
<p>    * The Twisted Weekly News<br />
    * Discussions<br />
    * Progress<br />
    * Cool Thing of the Week</p>
<p>If you have any new information, ideas, announcements for the next TWN, please write to me,
<lior@gradstein.info>.<br />
The Twisted Weekly News</p>
<p>8th Issue. Sunday, December 7, 2003</p>
<p>QOTW:</p>
<p><moshez> dash: ok I wrote something<br />
<moshez> dash: do you want to review and comment?<br />
<dash> moshez: i would but my mouse battery is dead!! so i cannot paste it<br />
<dash> moshez: yes, but today is a traditional american holiday<br />
<dash> on which we make lame excuses</p>
<p>Discussions</p>
<p>        * Moshe Zadka wrote a article (http://www.livejournal.com/users/moshez/5536.html), about the usefulness to change the page-file paradigm, and use class-page instead.</p>
<p>Progress</p>
<p>        * A new version (0.8.6) of Quotient (http://www.divmod.org/) has been released (Editing of preferences via FreeForm, Tests,Improved table sorting,People and contacts,Inbox manager,Trash Manager,Compose and send messages with attachments, Password recovery,Thumbnailing,STUN server,Numerous tweaks and fixes).</p>
<p>Cool Thing of the Week</p>
<p>        * Draft of documentation for nevow (http://stewstuff.com/doc/nevow.xhtml): A first start at a documentation for the new web piece of Twisted.</p>
<p>Ok, that&#8217;s it for this week. Thanks for reading!</p>
<p>Lior Gradstein
<lior@gradstein.info>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/software/twisted/twisted-weekly-news-8/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twisted Weekly News #7</title>
		<link>http://www.gradstein.info/software/twisted/twisted-weekly-news-7/</link>
		<comments>http://www.gradstein.info/software/twisted/twisted-weekly-news-7/#comments</comments>
		<pubDate>Sun, 23 Nov 2003 17:22:46 +0000</pubDate>
		<dc:creator>Lior Gradstein</dc:creator>
				<category><![CDATA[software]]></category>
		<category><![CDATA[twisted]]></category>

		<guid isPermaLink="false">http://www.gradstein.info/?p=321</guid>
		<description><![CDATA[Twisted Weekly News #7
Author: 	Lior Gradstein
Contact: 	lior@gradstein.info
Revision: 	1.0
Date: 	2003-11-23
Copyright: 	© The Twisted Community
Contents
    * The Twisted Weekly News
    * Discussions
    * Progress
    * Cool Thing of the Week
I&#8217;ll try to keep the pace with the TWN, continuing the work of Chris Armstrong. Thanks [...]]]></description>
			<content:encoded><![CDATA[<p>Twisted Weekly News #7<br />
Author: 	Lior Gradstein<br />
Contact: 	lior@gradstein.info<br />
Revision: 	1.0<br />
Date: 	2003-11-23<br />
Copyright: 	© The Twisted Community</p>
<p>Contents</p>
<p>    * The Twisted Weekly News<br />
    * Discussions<br />
    * Progress<br />
    * Cool Thing of the Week</p>
<p>I&#8217;ll try to keep the pace with the TWN, continuing the work of Chris Armstrong. Thanks to Noa Harvey who is correcting my english as it is not my primary language.<br />
The Twisted Weekly News</p>
<p>7th Issue. Sunday, November 23, 2003</p>
<p>QOTW:</p>
<p><radix> scripts are just usually short programs that do a very specific thing<br />
<radix> that&#8217;s why a lot of us people who use interpreted languages hate it<br />
when someone calls our language a &#8220;Scripting language&#8221; ;)<br />
<radix> (I mean, look at Twisted and call it a &#8220;script&#8221; with a straight face)</p>
<p>Discussions</p>
<p>XXXX<br />
Progress</p>
<p>        * A new version (0.8.0) of Quotient (http://www.divmod.org/) has been released (Editing of preferences via FreeForm, Tests,Improved table sorting,People and contacts,Inbox manager,Trash Manager,Compose and send messages with attachments, Password recovery,Thumbnailing,STUN server,Numerous tweaks and fixes).</p>
<p>Cool Thing of the Week</p>
<p>        * TouRSSt, by Tv (http://toursst.sourceforge.net/): TouRSSt tours the web so you don&#8217;t have to. Run frequently, it pulls new RSS news items from a number of channels and puts them where you want. The project existed for a long time, but it was revived on November, 2.<br />
        * Informant, by Nafai (http://www.travishartwell.net/projects/informant/): First version of Informant, an graphical event logger that makes notifications (Gnome based, but a standalone version is possible).<br />
        * Twibbler (http://slarty.polito.it:8069/~sciasbat/wiki/moin.cgi/twibber): Twibber is a Python package aimed at handling the Jabber/XMMP protocol in a completely asynchronous way, with no need of threads.<br />
        * Web Forum: A web forum has been created to allow people that like clicking to discuss more about Twisted! Its url is http://twisted.banquise.org/</p>
<p>Ok, that&#8217;s it for this week. Thanks for reading!</p>
<p>Lior Gradstein
<lior@gradstein.info>

	<h4>Related posts</h4>
	<ul class="st-related-posts">
	<li>No related posts.</li>
	</ul>

]]></content:encoded>
			<wfw:commentRss>http://www.gradstein.info/software/twisted/twisted-weekly-news-7/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
