<?xml version="1.0" encoding="utf-8"?>
<!-- generator="FeedCreator 1.7.2-ppt DokuWiki" -->
<?xml-stylesheet href="http://www.hodique.info/lib/exe/css.php?s=feed" type="text/css"?>
<rdf:RDF
    xmlns="http://purl.org/rss/1.0/"
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
    xmlns:dc="http://purl.org/dc/elements/1.1/">
    <channel rdf:about="http://www.hodique.info/feed.php">
        <title>Yann Hodique blog:2010</title>
        <description></description>
        <link>http://www.hodique.info/</link>
        <image rdf:resource="http://www.hodique.info/lib/images/favicon.ico" />
       <dc:date>2010-03-12T02:29:39+01:00</dc:date>
        <items>
            <rdf:Seq>
                <rdf:li rdf:resource="http://www.hodique.info/blog/2010/02/18/python_webservice_part_2_a_twistd_integration"/>
                <rdf:li rdf:resource="http://www.hodique.info/blog/2010/02/17/python_webservice_part_1_a_twisted_solution"/>
                <rdf:li rdf:resource="http://www.hodique.info/blog/2010/02/14/magit_extensions"/>
            </rdf:Seq>
        </items>
    </channel>
    <image rdf:about="http://www.hodique.info/lib/images/favicon.ico">
        <title>Yann Hodique</title>
        <link>http://www.hodique.info/</link>
        <url>http://www.hodique.info/lib/images/favicon.ico</url>
    </image>
    <item rdf:about="http://www.hodique.info/blog/2010/02/18/python_webservice_part_2_a_twistd_integration">
        <dc:format>text/html</dc:format>
        <dc:date>2010-02-19T00:01:46+01:00</dc:date>
        <dc:creator>Yann Hodique</dc:creator>
        <title>Python Webservice, part 2 : a twistd integration</title>
        <link>http://www.hodique.info/blog/2010/02/18/python_webservice_part_2_a_twistd_integration</link>
        <description>


&lt;div class=&quot;level1&quot;&gt;


&lt;div class=&quot;styler styler-float-left&quot;&gt;
&lt;p&gt;
&lt;span class=&quot;vcard&quot;&gt;&lt;img src=&quot;http://www.hodique.info/lib/exe/fetch.php?hash=15d77b&amp;amp;cache=recache&amp;amp;media=http%3A%2F%2Fwww.gravatar.com%2Favatar.php%3Fgravatar_id%3Dd9b955e7af49b0cbfd68c15947b25012%26default%3Dhttp%253A%252F%252Fwww.hodique.info%252Flib%252Fexe%252Ffetch.php%253Fhash%253Dd44619%2526cache%253Drecache%2526media%253Dhttp%25253A%25252F%25252Fwww.hodique.info%25252F%25252Flib%25252Fplugins%25252Favatar%25252Fmonsterid.php%25253Fseed%25253Dd9b955e7af49b0cbfd68c15947b25012%252526size%25253D40%252526.png%26size%3D40%26rating%3DR%26.jpg&quot; class=&quot;media photo fn&quot; title=&quot;&amp;#x79;&amp;#x61;&amp;#x6e;&amp;#x6e;&amp;#x2e;&amp;#x68;&amp;#x6f;&amp;#x64;&amp;#x69;&amp;#x71;&amp;#x75;&amp;#x65;&amp;#x40;&amp;#x67;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x6d;&quot; alt=&quot;&amp;#x79;&amp;#x61;&amp;#x6e;&amp;#x6e;&amp;#x2e;&amp;#x68;&amp;#x6f;&amp;#x64;&amp;#x69;&amp;#x71;&amp;#x75;&amp;#x65;&amp;#x40;&amp;#x67;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x6d;&quot; width=&quot;40&quot; height=&quot;40&quot; /&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;/div&gt;
&lt;!-- SECTION &quot;Python Webservice, part 2 : a twistd integration&quot; [1-126] --&gt;
&lt;h2&gt;&lt;a name=&quot;twistd&quot; id=&quot;twistd&quot;&gt;Twistd&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;
In my &lt;a href=&quot;http://www.hodique.info/blog/2010/02/17/python_webservice_part_1_a_twisted_solution&quot; class=&quot;wikilink1&quot; title=&quot;blog:2010:02:17:python_webservice_part_1_a_twisted_solution&quot;&gt;previous post&lt;/a&gt; I&amp;#039;ve explained how to generate a &lt;acronym title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/acronym&gt; service from a WSDL file, and how to implement the required methods properly. A solution to run such a service is to use the Twisted Daemon, aka &lt;code&gt;twistd&lt;/code&gt;.
Though not needed, strictly speaking, it provides a nice &lt;a href=&quot;http://twistedmatrix.com/documents/current/core/howto/basics.html&quot; class=&quot;urlextern&quot; title=&quot;http://twistedmatrix.com/documents/current/core/howto/basics.html&quot;  rel=&quot;nofollow&quot;&gt;set of features&lt;/a&gt; aimed at easing complex applications development.
&lt;/p&gt;

&lt;p&gt;
In particular, it allows to write so-called &lt;a href=&quot;http://twistedmatrix.com/documents/current/core/howto/tap.html&quot; class=&quot;urlextern&quot; title=&quot;http://twistedmatrix.com/documents/current/core/howto/tap.html&quot;  rel=&quot;nofollow&quot;&gt;plugins&lt;/a&gt; that make it possible to just launch services in the following way:

&lt;/p&gt;
&lt;pre class=&quot;code bash&quot;&gt;$ twistd &lt;span class=&quot;kw3&quot;&gt;echo&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
To achieve that, one has to create a file &lt;code&gt;twisted/plugins/echo.py&lt;/code&gt; accessible somewhere from the python path (that is, the &lt;code&gt;twisted&lt;/code&gt; directory should be a subdir of an element of the path).
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Twistd&quot; [127-1036] --&gt;
&lt;h2&gt;&lt;a name=&quot;manhole&quot; id=&quot;manhole&quot;&gt;Manhole&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

Twisted offers a nice service, that can be used to provide an inspection/debug interface for your main application. This is called &lt;a href=&quot;http://twistedmatrix.com/documents/9.0.0/api/twisted.manhole.html&quot; class=&quot;urlextern&quot; title=&quot;http://twistedmatrix.com/documents/9.0.0/api/twisted.manhole.html&quot;  rel=&quot;nofollow&quot;&gt;manhole&lt;/a&gt; and provides a python interpreter interface. This way you can just telnet/ssh the manhole, and execute appropriate commands to introspect the current state of the application, or put it in the desired state.
&lt;/p&gt;

&lt;p&gt;
A nice example of a really useful function to run from the manhole service is the &lt;a href=&quot;http://twistedmatrix.com/documents/9.0.0/api/twisted.python.rebuild.html&quot; class=&quot;urlextern&quot; title=&quot;http://twistedmatrix.com/documents/9.0.0/api/twisted.python.rebuild.html&quot;  rel=&quot;nofollow&quot;&gt;rebuild&lt;/a&gt; one. It tries very hard to provide in-place reloading of code (and corresponding objects). Don&amp;#039;t expect any wonder here, it will fail in some corner cases. Still, it proves really useful most of the time, and helps a lot not restarting the server every now and then.
&lt;/p&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Manhole&quot; [1037-1910] --&gt;
&lt;h2&gt;&lt;a name=&quot;example&quot; id=&quot;example&quot;&gt;Example&lt;/a&gt;&lt;/h2&gt;
&lt;div class=&quot;level2&quot;&gt;

&lt;p&gt;

Here is a fully working example of a twistd plugin for the Echo service, with a functional manhole service in addition.
&lt;/p&gt;
&lt;pre class=&quot;code python&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; zope.&lt;span class=&quot;me1&quot;&gt;interface&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; implements
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;python&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; usage
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;python&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;rebuild&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; rebuild
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;plugin&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; IPlugin
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;application&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;service&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; IServiceMaker, MultiService
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;application&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;internet&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; TCPServer
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;web&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;server&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; Site
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;web&lt;/span&gt;.&lt;span class=&quot;kw3&quot;&gt;resource&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; Resource
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; twisted.&lt;span class=&quot;me1&quot;&gt;conch&lt;/span&gt;.&lt;span class=&quot;me1&quot;&gt;manhole_tap&lt;/span&gt; &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; makeService &lt;span class=&quot;kw1&quot;&gt;as&lt;/span&gt; makeConsoleService
&amp;nbsp;
&lt;span class=&quot;kw1&quot;&gt;from&lt;/span&gt; EchoImpl &lt;span class=&quot;kw1&quot;&gt;import&lt;/span&gt; EchoService
&amp;nbsp;
&lt;span class=&quot;kw1&quot;&gt;class&lt;/span&gt; EchoOptions&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;usage.&lt;span class=&quot;me1&quot;&gt;Options&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
    optParameters = &lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;port&amp;quot;&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&amp;quot;p&amp;quot;&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;8080&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&amp;quot;main port&amp;quot;&lt;/span&gt;, &lt;span class=&quot;kw2&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;,
                     &lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;service-port&amp;quot;&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&amp;quot;s&amp;quot;&lt;/span&gt;, &lt;span class=&quot;nu0&quot;&gt;8081&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&amp;quot;service port&amp;quot;&lt;/span&gt;, &lt;span class=&quot;kw2&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;,
                     &lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;service-users&amp;quot;&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&amp;quot;u&amp;quot;&lt;/span&gt;, &lt;span class=&quot;st0&quot;&gt;&amp;quot;/etc/passwd&amp;quot;&lt;/span&gt;,
                      &lt;span class=&quot;st0&quot;&gt;&amp;quot;The path to a passwd-like authentication file&amp;quot;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;kw1&quot;&gt;class&lt;/span&gt; EchoServiceMaker&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;object&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
    implements&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;IServiceMaker, IPlugin&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    tapname = &lt;span class=&quot;st0&quot;&gt;&amp;quot;echo&amp;quot;&lt;/span&gt;
    description = &lt;span class=&quot;st0&quot;&gt;&amp;quot;Sample Echo service&amp;quot;&lt;/span&gt;
    options = EchoOptions
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; makeService&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;, options&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
        &lt;span class=&quot;co1&quot;&gt;# Create Service&lt;/span&gt;
        srv = EchoService&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        root = Resource&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        &lt;span class=&quot;co1&quot;&gt;# we'll serve Echo at http://&amp;lt;ip&amp;gt;:&amp;lt;port&amp;gt;/echo&lt;/span&gt;
        root.&lt;span class=&quot;me1&quot;&gt;putChild&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;'echo'&lt;/span&gt;, srv&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        siteFactory = Site&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;root&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        echo_service = TCPServer&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;options&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;'port'&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;, siteFactory&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        console_service = makeConsoleService&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;
            &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;telnetPort&amp;quot;&lt;/span&gt;: &lt;span class=&quot;kw2&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;options&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;'service-port'&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;,
             &lt;span class=&quot;st0&quot;&gt;&amp;quot;sshPort&amp;quot;&lt;/span&gt;: &lt;span class=&quot;kw2&quot;&gt;None&lt;/span&gt;,
             &lt;span class=&quot;st0&quot;&gt;&amp;quot;namespace&amp;quot;&lt;/span&gt;: &lt;span class=&quot;br0&quot;&gt;&amp;#123;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;&amp;quot;service&amp;quot;&lt;/span&gt;: srv,
                           &lt;span class=&quot;st0&quot;&gt;&amp;quot;rebuild&amp;quot;&lt;/span&gt;: rebuild&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;,
             &lt;span class=&quot;st0&quot;&gt;&amp;quot;passwd&amp;quot;&lt;/span&gt;: options&lt;span class=&quot;br0&quot;&gt;&amp;#91;&lt;/span&gt;&lt;span class=&quot;st0&quot;&gt;'service-users'&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#93;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#125;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        svc = MultiService&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        echo_service.&lt;span class=&quot;me1&quot;&gt;setServiceParent&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;svc&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        console_service.&lt;span class=&quot;me1&quot;&gt;setServiceParent&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;svc&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; svc
&amp;nbsp;
serviceMaker = EchoServiceMaker&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
The code is hopefully rather straightforward. It should be noted that the manhole service (created by the &lt;code&gt;makeConsoleService()&lt;/code&gt; call) needs to know about a set of objects (the “namespace” key). Those objects are the roots for everything accessible from the service. Here, the main service object (the &lt;code&gt;srv&lt;/code&gt; object) is available to the manhole under the name &lt;code&gt;service&lt;/code&gt;. Here is how it can be used:
&lt;/p&gt;
&lt;pre class=&quot;code shell&quot;&gt;$ telnet localhost 8081
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Username: yann
Password: x
&amp;nbsp;
&amp;gt;&amp;gt;&amp;gt; print service
&amp;lt;EchoImpl.EchoService object at 0x2fc8c10&amp;gt;
&amp;gt;&amp;gt;&amp;gt;&lt;/pre&gt;

&lt;p&gt;
Hint: the password is really &amp;#039;x&amp;#039;, as I&amp;#039;m using /etc/passwd by default, which contains &amp;#039;x&amp;#039; for every “password” field, since the real passwords are in /etc/shadow.
Convenient for a dev deployment ;)
&lt;/p&gt;
&lt;div class=&quot;tags&quot;&gt;&lt;span&gt;
	&lt;a href=&quot;http://www.hodique.info/tags/python&quot; class=&quot;wikilink1&quot; title=&quot;tags:python&quot; rel=&quot;tag&quot;&gt;python&lt;/a&gt;,
	&lt;a href=&quot;http://www.hodique.info/tags/code&quot; class=&quot;wikilink1&quot; title=&quot;tags:code&quot; rel=&quot;tag&quot;&gt;code&lt;/a&gt;,
	&lt;a href=&quot;http://www.hodique.info/tags/twisted&quot; class=&quot;wikilink1&quot; title=&quot;tags:twisted&quot; rel=&quot;tag&quot;&gt;twisted&lt;/a&gt;
&lt;/span&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;!-- SECTION &quot;Example&quot; [1911-] --&gt;&lt;span class=&quot;plugin_feedmod_comments&quot;&gt;
  &lt;a href=&quot;http://www.hodique.info/blog/2010/02/18/python_webservice_part_2_a_twistd_integration#discussion__section&quot; title=&quot;Read or add comments to this article&quot;&gt;Read or add comments to this article&lt;/a&gt;
&lt;/span&gt;
</description>
    </item>
    <item rdf:about="http://www.hodique.info/blog/2010/02/17/python_webservice_part_1_a_twisted_solution">
        <dc:format>text/html</dc:format>
        <dc:date>2010-02-17T20:20:16+01:00</dc:date>
        <dc:creator>Yann Hodique</dc:creator>
        <title>Python Webservice, part 1 : a Twisted solution</title>
        <link>http://www.hodique.info/blog/2010/02/17/python_webservice_part_1_a_twisted_solution</link>
        <description>


&lt;div class=&quot;level1&quot;&gt;


&lt;div class=&quot;styler styler-float-left&quot;&gt;
&lt;p&gt;
&lt;span class=&quot;vcard&quot;&gt;&lt;img src=&quot;http://www.hodique.info/lib/exe/fetch.php?hash=15d77b&amp;amp;cache=recache&amp;amp;media=http%3A%2F%2Fwww.gravatar.com%2Favatar.php%3Fgravatar_id%3Dd9b955e7af49b0cbfd68c15947b25012%26default%3Dhttp%253A%252F%252Fwww.hodique.info%252Flib%252Fexe%252Ffetch.php%253Fhash%253Dd44619%2526cache%253Drecache%2526media%253Dhttp%25253A%25252F%25252Fwww.hodique.info%25252F%25252Flib%25252Fplugins%25252Favatar%25252Fmonsterid.php%25253Fseed%25253Dd9b955e7af49b0cbfd68c15947b25012%252526size%25253D40%252526.png%26size%3D40%26rating%3DR%26.jpg&quot; class=&quot;media photo fn&quot; title=&quot;&amp;#x79;&amp;#x61;&amp;#x6e;&amp;#x6e;&amp;#x2e;&amp;#x68;&amp;#x6f;&amp;#x64;&amp;#x69;&amp;#x71;&amp;#x75;&amp;#x65;&amp;#x40;&amp;#x67;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x6d;&quot; alt=&quot;&amp;#x79;&amp;#x61;&amp;#x6e;&amp;#x6e;&amp;#x2e;&amp;#x68;&amp;#x6f;&amp;#x64;&amp;#x69;&amp;#x71;&amp;#x75;&amp;#x65;&amp;#x40;&amp;#x67;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x6d;&quot; width=&quot;40&quot; height=&quot;40&quot; /&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;


&lt;p&gt;
As mentioned &lt;a href=&quot;http://www.hodique.info/blog/2009/11/15/https_traffic_logger&quot; class=&quot;wikilink1&quot; title=&quot;blog:2009:11:15:https_traffic_logger&quot;&gt;previously&lt;/a&gt;
I&amp;#039;ve been spending some time recently working on a &lt;acronym title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/acronym&gt; server mock. For this I&amp;#039;ve used Python &lt;a href=&quot;http://twistedmatrix.com&quot; class=&quot;urlextern&quot; title=&quot;http://twistedmatrix.com&quot;  rel=&quot;nofollow&quot;&gt;Twisted&lt;/a&gt; and &lt;a href=&quot;http://pywebsvcs.sourceforge.net/zsi.html&quot; class=&quot;urlextern&quot; title=&quot;http://pywebsvcs.sourceforge.net/zsi.html&quot;  rel=&quot;nofollow&quot;&gt;ZSI&lt;/a&gt;. Since the interaction between the 2 seems rather poorly documented (even Google doesn&amp;#039;t know much about it), I thought I&amp;#039;d share what I&amp;#039;ve investigated and done.
&lt;/p&gt;

&lt;p&gt;
Disclaimer: you should be familiar with &lt;acronym title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/acronym&gt; and Python Twisted. I&amp;#039;ll not cover anything in these areas.
&lt;/p&gt;

&lt;p&gt;
For the sake of simplicity, I&amp;#039;ll take a classical minimal server: an Echo service.
&lt;/p&gt;

&lt;p&gt;
Let&amp;#039;s start from the definition of such a service, as a WSDL. This one was randomly picked from &lt;a href=&quot;http://www.ioncannon.net/programming/180/soap-on-the-google-app-engine-platform/&quot; class=&quot;urlextern&quot; title=&quot;http://www.ioncannon.net/programming/180/soap-on-the-google-app-engine-platform/&quot;  rel=&quot;nofollow&quot;&gt;there&lt;/a&gt;
Anyway the implementation details are not so important here.
&lt;/p&gt;
&lt;pre class=&quot;code xml&quot;&gt;&lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;?xml&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;version&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;1.0&amp;quot;&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;encoding&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;UTF-8&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;?&amp;gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;definitions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;    &lt;span class=&quot;re0&quot;&gt;xmlns&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/wsdl/&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;    &lt;span class=&quot;re0&quot;&gt;xmlns:soap&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/wsdl/soap/&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;    &lt;span class=&quot;re0&quot;&gt;xmlns:soapenc&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/soap/encoding/&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;    &lt;span class=&quot;re0&quot;&gt;xmlns:http&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/wsdl/http/&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;    &lt;span class=&quot;re0&quot;&gt;xmlns:xsd&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;    &lt;span class=&quot;re0&quot;&gt;xmlns:tns&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;urn:ZSI&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;    &lt;span class=&quot;re0&quot;&gt;targetNamespace&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;urn:ZSI&amp;quot;&lt;/span&gt; &lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;types&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;xsd:schema&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;elementFormDefault&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;qualified&amp;quot;&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;targetNamespace&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;urn:ZSI&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;xsd:element&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;Echo&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;xsd:complexType&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;xsd:sequence&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
            &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;xsd:element&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;value&amp;quot;&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;xsd:anyType&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
          &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/xsd:sequence&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/xsd:complexType&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/xsd:element&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/xsd:schema&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/types&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;message&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;EchoRequest&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;part&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;element&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;tns:Echo&amp;quot;&lt;/span&gt; &lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/message&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;message&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;EchoResponse&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;part&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;parameters&amp;quot;&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;element&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;tns:Echo&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/message&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;portType&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;EchoServer&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;operation&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;Echo&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;input&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;message&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;tns:EchoRequest&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;output&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;message&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;tns:EchoResponse&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/operation&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/portType&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;binding&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;EchoServer&amp;quot;&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;tns:EchoServer&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;soap:binding&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;style&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;document&amp;quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;sc3&quot;&gt;                  &lt;span class=&quot;re0&quot;&gt;transport&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/soap/http&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;operation&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;Echo&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;soap:operation&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;soapAction&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;Echo&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;input&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;soap:body&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;use&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;literal&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/input&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;output&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
        &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;soap:body&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;use&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;literal&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/output&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/operation&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/binding&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;service&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;EchoServer&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;port&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;name&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;EchoServer&amp;quot;&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;binding&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;tns:EchoServer&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;
      &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;soap:address&lt;/span&gt; &lt;span class=&quot;re0&quot;&gt;location&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://localhost:8080/echo&amp;quot;&lt;/span&gt;&lt;span class=&quot;re2&quot;&gt;/&amp;gt;&lt;/span&gt;&lt;/span&gt;
    &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/port&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
  &lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/service&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;sc3&quot;&gt;&lt;span class=&quot;re1&quot;&gt;&amp;lt;/definitions&lt;span class=&quot;re2&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
So really nothing fancy here. Just the definitions and shape of the
messages/operations (only trivial ones).
&lt;/p&gt;

&lt;p&gt;
ZSI offers the &lt;code&gt;wsdl2py&lt;/code&gt; tool, that can process such WSDL files, and produce client bindings and server stub. In this article, the server part is what we want. (note the &lt;code&gt;-w&lt;/code&gt; flag will trigger Twisted code generation)
&lt;/p&gt;
&lt;pre class=&quot;code bash&quot;&gt;$ wsdl2py &lt;span class=&quot;re5&quot;&gt;-w&lt;/span&gt; echo.wsdl&lt;/pre&gt;

&lt;p&gt;
&lt;code&gt;EchoServer_server.py&lt;/code&gt; now contains the code for the service stub. Not much in there, the main part being the following method:
&lt;/p&gt;
&lt;pre class=&quot;code python&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; soap_Echo&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;, ps, &lt;span class=&quot;sy0&quot;&gt;**&lt;/span&gt;kw&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
    request = ps.&lt;span class=&quot;me1&quot;&gt;Parse&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;EchoRequest.&lt;span class=&quot;me1&quot;&gt;typecode&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; request,EchoResponse&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
This is the one we should implement to make the service concrete. Here is a first attempt:
&lt;/p&gt;
&lt;pre class=&quot;code python&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;class&lt;/span&gt; EchoService&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;EchoServer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
        EchoServer.&lt;span class=&quot;kw4&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; soap_Echo&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;, ps, &lt;span class=&quot;sy0&quot;&gt;**&lt;/span&gt;kw&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
        request, _ = EchoServer.&lt;span class=&quot;me1&quot;&gt;soap_Echo&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;, ps, &lt;span class=&quot;sy0&quot;&gt;**&lt;/span&gt;kw&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; request, request&lt;/pre&gt;

&lt;p&gt;
That will work. If you register this Service as a Twisted Resource, it will provide a functional &lt;acronym title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/acronym&gt; Echo service, on which you can execute the following.
&lt;/p&gt;
&lt;pre class=&quot;code bash&quot;&gt;$ POST http:&lt;span class=&quot;sy0&quot;&gt;//&lt;/span&gt;localhost:8080&lt;span class=&quot;sy0&quot;&gt;/&lt;/span&gt;&lt;span class=&quot;kw3&quot;&gt;echo&lt;/span&gt;
Please enter content &lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;application&lt;span class=&quot;sy0&quot;&gt;/&lt;/span&gt;x-www-form-urlencoded&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt; to be POSTed:
&lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;soapenv:Envelope 
    xmlns:&lt;span class=&quot;re2&quot;&gt;soapenv&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/soap/envelope/&amp;quot;&lt;/span&gt; 
    xmlns:&lt;span class=&quot;re2&quot;&gt;xsd&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;/span&gt; 
    xmlns:&lt;span class=&quot;re2&quot;&gt;xsi&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;soapenv:Body xmlns:&lt;span class=&quot;re2&quot;&gt;ns1&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;urn:ZSI&amp;quot;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;ns1:Echo&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
      &lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;ns1:value xsi:&lt;span class=&quot;kw3&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;xsd:string&amp;quot;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;plop&lt;span class=&quot;sy0&quot;&gt;&amp;lt;/&lt;/span&gt;ns1:value&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;sy0&quot;&gt;&amp;lt;/&lt;/span&gt;ns1:Echo&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
  &lt;span class=&quot;sy0&quot;&gt;&amp;lt;/&lt;/span&gt;soapenv:Body&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sy0&quot;&gt;&amp;lt;/&lt;/span&gt;soapenv:Envelope&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
^D
&lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;soapenv:Envelope xmlns:&lt;span class=&quot;re2&quot;&gt;ZSI&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://www.zolera.com/schemas/ZSI/&amp;quot;&lt;/span&gt; xmlns:&lt;span class=&quot;re2&quot;&gt;soapenc&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/soap/encoding/&amp;quot;&lt;/span&gt; xmlns:&lt;span class=&quot;re2&quot;&gt;soapenv&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://schemas.xmlsoap.org/soap/envelope/&amp;quot;&lt;/span&gt; xmlns:&lt;span class=&quot;re2&quot;&gt;xsd&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://www.w3.org/2001/XMLSchema&amp;quot;&lt;/span&gt; xmlns:&lt;span class=&quot;re2&quot;&gt;xsi&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;http://www.w3.org/2001/XMLSchema-instance&amp;quot;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;
&lt;span class=&quot;sy0&quot;&gt;&amp;lt;&lt;/span&gt;soapenv:Header&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;soapenv:Header&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;soapenv:Body xmlns:&lt;span class=&quot;re2&quot;&gt;ns1&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;urn:ZSI&amp;quot;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;ns1:Echo&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&amp;lt;&lt;/span&gt;ns1:value xsi:&lt;span class=&quot;kw3&quot;&gt;type&lt;/span&gt;=&lt;span class=&quot;st0&quot;&gt;&amp;quot;xsd:string&amp;quot;&lt;/span&gt;&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;plop&lt;span class=&quot;sy0&quot;&gt;&amp;lt;/&lt;/span&gt;ns1:value&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;ns1:Echo&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;soapenv:Body&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;soapenv:Envelope&lt;span class=&quot;sy0&quot;&gt;&amp;gt;&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;
Still, this is not very Twisted… I mean we don&amp;#039;t take advantage of the asynchronous framework here, as the only method we wrote is definitely synchronous and we treat each call after one another. Would the &lt;code&gt;soap_Echo()&lt;/code&gt; take time for whatever reason, that would introduce unacceptable delays for the user.
Of course, there is no magic in the &lt;code&gt;Deferred&lt;/code&gt; objects, which means than simply returning a &lt;code&gt;Deferred&lt;/code&gt; in &lt;code&gt;soap_Echo()&lt;/code&gt; will absolutely not work.
&lt;/p&gt;

&lt;p&gt;
Digging a bit more in the ZSI Twisted glue, one can find a promising piece of code, appropriately named &lt;code&gt;DeferHandlerChain&lt;/code&gt;. This is an alternative to the &lt;code&gt;DefaultHandlerChain&lt;/code&gt; that&amp;#039;s used (by default) by &lt;code&gt;WSresource&lt;/code&gt; objects (hence &lt;code&gt;EchoServer&lt;/code&gt; ones). The nice property of this handler chain is to put in place a callback chain from &lt;code&gt;processRequest()&lt;/code&gt; to &lt;code&gt;processResponse()&lt;/code&gt;, actually supporting &lt;code&gt;Deferred&lt;/code&gt; objects returned by soap methods. In a word, what we need…
&lt;/p&gt;

&lt;p&gt;
The code can become something like:
&lt;/p&gt;
&lt;pre class=&quot;code python&quot;&gt;&lt;span class=&quot;kw1&quot;&gt;class&lt;/span&gt; EchoDeferHandlerChainFactory:
    protocol = DeferHandlerChain
&amp;nbsp;
    @&lt;span class=&quot;kw2&quot;&gt;classmethod&lt;/span&gt;
    &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; newInstance&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;cls&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
        &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; cls.&lt;span class=&quot;me1&quot;&gt;protocol&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;DefaultCallbackHandler, DataHandler&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
&lt;span class=&quot;kw1&quot;&gt;class&lt;/span&gt; EchoService&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;EchoServer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;kw4&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
        EchoServer.&lt;span class=&quot;kw4&quot;&gt;__init__&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        EchoServer.&lt;span class=&quot;me1&quot;&gt;factory&lt;/span&gt; = EchoDeferHandlerChainFactory
&amp;nbsp;
    &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; soap_Echo&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;, ps, &lt;span class=&quot;sy0&quot;&gt;**&lt;/span&gt;kw&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
        request, _ = EchoServer.&lt;span class=&quot;me1&quot;&gt;soap_Echo&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;kw2&quot;&gt;self&lt;/span&gt;, ps, &lt;span class=&quot;sy0&quot;&gt;**&lt;/span&gt;kw&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
&amp;nbsp;
        &lt;span class=&quot;kw1&quot;&gt;def&lt;/span&gt; _answer&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;:
            &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; request
&amp;nbsp;
        &lt;span class=&quot;co1&quot;&gt;# yeah, we have a very busy echo service... 5 seconds delay !&lt;/span&gt;
        d = deferLater&lt;span class=&quot;br0&quot;&gt;&amp;#40;&lt;/span&gt;reactor, 5, _answer&lt;span class=&quot;br0&quot;&gt;&amp;#41;&lt;/span&gt;
        &lt;span class=&quot;kw1&quot;&gt;return&lt;/span&gt; request, d&lt;/pre&gt;

&lt;p&gt;
You can now try triggering several parallel Echo calls, and see that they will not be treated in sequence !
&lt;/p&gt;
&lt;div class=&quot;tags&quot;&gt;&lt;span&gt;
	&lt;a href=&quot;http://www.hodique.info/tags/python&quot; class=&quot;wikilink1&quot; title=&quot;tags:python&quot; rel=&quot;tag&quot;&gt;python&lt;/a&gt;,
	&lt;a href=&quot;http://www.hodique.info/tags/code&quot; class=&quot;wikilink1&quot; title=&quot;tags:code&quot; rel=&quot;tag&quot;&gt;code&lt;/a&gt;,
	&lt;a href=&quot;http://www.hodique.info/tags/zsi&quot; class=&quot;wikilink1&quot; title=&quot;tags:zsi&quot; rel=&quot;tag&quot;&gt;zsi&lt;/a&gt;,
	&lt;a href=&quot;http://www.hodique.info/tags/twisted&quot; class=&quot;wikilink1&quot; title=&quot;tags:twisted&quot; rel=&quot;tag&quot;&gt;twisted&lt;/a&gt;
&lt;/span&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;span class=&quot;plugin_feedmod_comments&quot;&gt;
  &lt;a href=&quot;http://www.hodique.info/blog/2010/02/17/python_webservice_part_1_a_twisted_solution#discussion__section&quot; title=&quot;Read or add comments to this article&quot;&gt;Read or add comments to this article&lt;/a&gt;
&lt;/span&gt;
</description>
    </item>
    <item rdf:about="http://www.hodique.info/blog/2010/02/14/magit_extensions">
        <dc:format>text/html</dc:format>
        <dc:date>2010-02-14T13:05:08+01:00</dc:date>
        <dc:creator>Yann Hodique</dc:creator>
        <title>Magit extensions</title>
        <link>http://www.hodique.info/blog/2010/02/14/magit_extensions</link>
        <description>


&lt;div class=&quot;level1&quot;&gt;


&lt;div class=&quot;styler styler-float-left&quot;&gt;
&lt;p&gt;
&lt;span class=&quot;vcard&quot;&gt;&lt;img src=&quot;http://www.hodique.info/lib/exe/fetch.php?hash=15d77b&amp;amp;cache=recache&amp;amp;media=http%3A%2F%2Fwww.gravatar.com%2Favatar.php%3Fgravatar_id%3Dd9b955e7af49b0cbfd68c15947b25012%26default%3Dhttp%253A%252F%252Fwww.hodique.info%252Flib%252Fexe%252Ffetch.php%253Fhash%253Dd44619%2526cache%253Drecache%2526media%253Dhttp%25253A%25252F%25252Fwww.hodique.info%25252F%25252Flib%25252Fplugins%25252Favatar%25252Fmonsterid.php%25253Fseed%25253Dd9b955e7af49b0cbfd68c15947b25012%252526size%25253D40%252526.png%26size%3D40%26rating%3DR%26.jpg&quot; class=&quot;media photo fn&quot; title=&quot;&amp;#x79;&amp;#x61;&amp;#x6e;&amp;#x6e;&amp;#x2e;&amp;#x68;&amp;#x6f;&amp;#x64;&amp;#x69;&amp;#x71;&amp;#x75;&amp;#x65;&amp;#x40;&amp;#x67;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x6d;&quot; alt=&quot;&amp;#x79;&amp;#x61;&amp;#x6e;&amp;#x6e;&amp;#x2e;&amp;#x68;&amp;#x6f;&amp;#x64;&amp;#x69;&amp;#x71;&amp;#x75;&amp;#x65;&amp;#x40;&amp;#x67;&amp;#x6d;&amp;#x61;&amp;#x69;&amp;#x6c;&amp;#x2e;&amp;#x63;&amp;#x6f;&amp;#x6d;&quot; width=&quot;40&quot; height=&quot;40&quot; /&gt;&lt;/span&gt;
&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;
&lt;a href=&quot;http://zagadka.vm.bytemark.co.uk/magit/&quot; class=&quot;urlextern&quot; title=&quot;http://zagadka.vm.bytemark.co.uk/magit/&quot;  rel=&quot;nofollow&quot;&gt;Magit&lt;/a&gt; is a great emacs tool to help doing everyday&amp;#039;s operations on &lt;a href=&quot;http://git-scm.com/&quot; class=&quot;urlextern&quot; title=&quot;http://git-scm.com/&quot;  rel=&quot;nofollow&quot;&gt;Git&lt;/a&gt; repositories.
In particular, I really like the contextual approach, that splits the global status in sections, meaning that the same high-level command can have subtle semantics differences when applied to different objects.
As an example, the high-level `magit-discard-item&amp;#039; function obviously takes different steps when applied to an untracked file or to a staged hunk, or even to an entire branch.
&lt;/p&gt;

&lt;p&gt;
The only disadvantage I see in the current implementation is the lack of modularity in it: a heavy use of (really nice, btw) macros makes it mandatory to have the complete set of features available when magit is loaded, so that the generated code is complete.
&lt;/p&gt;

&lt;p&gt;
Still, Git has lots of contributed helpers, which means the only stable way of using them with Magit is to have them integrated upstream, which is not always possible (take the example of custom helpers that cannot be distributed) or does not even make sense (those helpers could be entirely bound to some specificities of a project).
&lt;/p&gt;

&lt;p&gt;
I&amp;#039;ve been working on an attempt to make Magit more modular, by allowing the registration of so-called “extensions”. See code here: &lt;a href=&quot;http://github.com/sigma/magit/tree/extensions&quot; class=&quot;urlextern&quot; title=&quot;http://github.com/sigma/magit/tree/extensions&quot;  rel=&quot;nofollow&quot;&gt;http://github.com/sigma/magit/tree/extensions&lt;/a&gt;
&lt;/p&gt;

&lt;p&gt;
As a POC, I&amp;#039;ve extracted 2 features from the mainstream Magit, and converted them to extensions: those are magit-svn and magit-topgit.
The way I see things, those 2 features are exactly the kind I&amp;#039;d like to add to magit for my daily work but that would not necessarily make sense as part of the core project. As far as I know, the current behavior when those 2 extensions are loaded is exactly the same as the regular upstream version (including placement of the various sections)
&lt;/p&gt;

&lt;p&gt;
The current code allows you to:
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; define new kind of sections (for example a “topic” kind)&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; define how and where to display them (for example, right after the core “stashes” section)&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; hook new behavior for existing commands for those new sections (for example a way to discard such an item)&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; define new top-level commands, and associate menus&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

I tried to stay very close from the Magit way of doing things, and in particular the way you express things in extensions is exactly the same as what you do in the core code. Once again, tricky macros are at play to make the code look the same.
&lt;/p&gt;

&lt;p&gt;
What I&amp;#039;d like to see in the future (though I don&amp;#039;t have much time to do it right now :():
&lt;/p&gt;
&lt;ul&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; new extensions, to ease my daily life.&lt;/div&gt;
&lt;ul&gt;
&lt;li class=&quot;level2&quot;&gt;&lt;div class=&quot;li&quot;&gt; a magit-p4 (perforce integration),&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level2&quot;&gt;&lt;div class=&quot;li&quot;&gt; maybe a magit-stgit (stgit in place of topgit for topic branches)&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level2&quot;&gt;&lt;div class=&quot;li&quot;&gt; something to integrate with VMware&amp;#039;s &lt;a href=&quot;http://www.reviewboard.org/&quot; class=&quot;urlextern&quot; title=&quot;http://www.reviewboard.org/&quot;  rel=&quot;nofollow&quot;&gt;ReviewBoard&lt;/a&gt;&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; code stabilization, and official proposal upstream (if there is an interest in this)&lt;/div&gt;
&lt;/li&gt;
&lt;li class=&quot;level1&quot;&gt;&lt;div class=&quot;li&quot;&gt; a way to activate those extensions on a per-project basis (I use both git-svn and git-p4 but never at the same time. same for topgit vs stgit)&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

An example being worth a thousand words, here is how to code the magit-topic extension. If you know the Magit code base, you should feel nearly at home.
&lt;script src=&quot;http://gist.github.com/303969.js?file=magit-topic.el&quot;&gt;&lt;/script&gt;
&lt;/p&gt;

&lt;p&gt;
Feel free to tell me what you think, any comment or advice is highly welcome !
&lt;/p&gt;
&lt;div class=&quot;tags&quot;&gt;&lt;span&gt;
	&lt;a href=&quot;http://www.hodique.info/tags/emacs&quot; class=&quot;wikilink1&quot; title=&quot;tags:emacs&quot; rel=&quot;tag&quot;&gt;emacs&lt;/a&gt;,
	&lt;a href=&quot;http://www.hodique.info/tags/git&quot; class=&quot;wikilink1&quot; title=&quot;tags:git&quot; rel=&quot;tag&quot;&gt;git&lt;/a&gt;,
	&lt;a href=&quot;http://www.hodique.info/tags/code&quot; class=&quot;wikilink1&quot; title=&quot;tags:code&quot; rel=&quot;tag&quot;&gt;code&lt;/a&gt;
&lt;/span&gt;&lt;/div&gt;

&lt;/div&gt;
&lt;span class=&quot;plugin_feedmod_comments&quot;&gt;
  &lt;a href=&quot;http://www.hodique.info/blog/2010/02/14/magit_extensions#discussion__section&quot; title=&quot;Read or add comments to this article&quot;&gt;Read or add comments to this article&lt;/a&gt;
&lt;/span&gt;
</description>
    </item>
</rdf:RDF>
