tag:blogger.com,1999:blog-56084552007-12-27T21:45:06.850+01:00Valentino Volonghi's WeblogValentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comBlogger13125tag:blogger.com,1999:blog-5608455.post-1133778760478638352005-12-05T10:58:00.000+01:002005-12-05T11:46:51.413+01:00A web server in twisted - Part 2Yesterday I wrote <a href="http://vvolonghi.blogspot.com/2005/12/web-server-in-twisted.html">this</a> post about how to write a very simple web server for a predefined content. Now I want to change it and discuss the solution a bit more in detail. First of all let's make it a real webserver, serving files from a known directory instead of serving some dummy content and avoid calling the browser which is not really needed.<br /><pre><code><br />from twisted.internet import reactor<br />from twisted.web2 import server, static, channel, http<br />PORT = 8080<br />DIRECTORY = '/Users/dialtone/'<br />s = server.Site(static.File(DIRECTORY))<br />reactor.listenTCP(PORT, channel.HTTPFactory(s))<br />reactor.run()<br /></pre></code><br />This is a better solution now. But how is it any good?<br /><br />As <a href="http://blog.boschin.it/articles/webserver1.aspx">this</a> post states, the HTTPListener solution of the .Net world is not really useful since it only supports Windows Server 2003 or Windows XP with SP2, not even SP1 or Windows 2000. The author then goes on explaining what will be done to rewrite a new webserver that will solve this problem and how hard it is to handle all the request parsing for HTTP.<br /><br />Mr. Andrea Boschin is very right in his statements, HTTP is not an easy protocol to implement given all the details that it comes with, especially considering that its RFC is sometimes contraddictory with itself. Fortunately the real advantage of Twisted Matrix is that all these details are already solved for you by the library author. In this case we are using the second version (which is currently under development but stable and used in many project, I use it myself in some of my projects) of the HTTP 1.1 protocol implementation.<br /><br />The Original Poster starts dealing with the first problems with the integration between the existing application and the new to-be-written web server, the solution proposed is threading, since he is running this webserver as a Windows service he is in the need of running a parallel thread to deal with HTTP requests. Being completely async allows you to already forget about this. You can easily run many different services in the same process (like an SMTP server, an HTTP server and an IMAP server) without the need of threading while still keeping a good request rate in the order of 900 requests fullfilled each second on an Opteron 2.4Ghz.<br /><br />The solution I came up with is already capable of adding a complete SMTP server to its features, in fact:<br /><pre><code><br />from twisted.internet import reactor<br />from twisted.web2 import server, static, channel, http<br />from twisted.mail import mail, maildir<br /><br />PORT = 8080<br />DIRECTORY = '/Users/dialtone/'<br />MAIL_PATH= '/Users/dialtone/mail/'<br />SMTP_PORT = 25<br />POP3_PORT = 110<br /><br />s = server.Site(static.File(DIRECTORY))<br />reactor.listenTCP(PORT, channel.HTTPFactory(s))<br /><br />mailservice = mail.MailService()<br />domain = maildir.MaildirDirdbmDomain(mailservice, os.path.abspath(MAIL_PATH))<br />domain.addUser('foo', 'bar')<br />mailservice.addDomain('localhost', domain)<br /><br />smtp = mailservice.getSMTPFactory()<br />pop3 = mailservice.getPOP3Factory()<br /><br />reactor.listenTCP(SMTP_PORT, smtp)<br />reactor.listenTCP(POP3_PORT, pop3)<br /><br />reactor.run()<br /></code></pre><br />This is that service with an HTTP server plus an SMTP server and a POP3 server. (Note: due to lack of time I haven't been able to completely test this piece of code, but it should serve as an idea about how to achieve the goal).<br /><br />What is all this post about then, besides writing something about twisted and how easily you can integrate different protocols without worrying too much about concurrency (since Twisted itself handles it for you)? This post was just made to show how the .Net platform is actually limiting its users not only in the features' 'space' (it's hard to write even simple services and it's even harder to integrate them) but also from the legacy point of view. This should serve as a good lesson about the strengths of Open Source against Proprietary Software too.Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1133657729888157122005-12-04T01:51:00.000+01:002005-12-04T11:29:42.513+01:00A Web server in TwistedStarting from <a href="http://www.oluyede.org/blog/2005/12/04/httplistener-net-vs-basehttpserver-python/trackback/">this</a> post that was triggered by <a href="http://blogs.ugidotnet.org/puntorete/archive/2005/11/30/30816.aspx">this</a> one I decided to do the same thing using <a href="http://www.twistedmatrix.com">Twisted Matrix</a>.<br /><br />Again the basic task is to write a webserver (the original poster was surprised in finding out how 'easy' it is to write a web server using .Net 2).<br /><br />This is my solution:<br /><pre><code><br />from twisted.internet import reactor<br />from twisted.web2 import server, resource, channel, http<br />import webbrowser<br />PORT = 8080<br /><br />class Page(resource.Resource):<br /> addSlash = True<br /> def render(self, ctx):<br /> return http.Response(stream="""<br /> &lt;html&gt;&lt;body&gt;&lt;h1&gt;This is the HTML body&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;<br /> """)<br /><br />s = server.Site(Page())<br />reactor.listenTCP(PORT, channel.HTTPFactory(s))<br />webbrowser.open("http://%s:%d" % ("localhost", PORT))<br />reactor.run()<br /></pre></code><br /><br />Easy isn't it?Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1133396080802276442005-12-01T01:00:00.000+01:002005-12-03T14:59:11.306+01:00Random image rotators everywhereAfter I came across <a href="http://hivelogic.com/articles/2005/11/30/random_image_rotation_in_rails">this</a> I decided that I should write something about the same thing but done in Nevow.<br />First of all the task is to write a random image rotation implementation for jpegs, gifs and pngs. This is easily accomplished by doing the following 3 things:<br /><br />1. Add this to the root Page of your web site. 'random/images/directory' is a directory in your HDD containing lots of images and other random data.<br /> <pre><code>child_random_images = static.File('random/images/directory')</code></pre><br />2. Add this to each of your Page objects that use the random image (or use a common base class to have this behaviour everywhere for free):<br /> <pre><code> <br />def render_random_image(self, ctx, data):<br /> files = [f for f in os.listdir('random/images/directory') <br /> if os.path.splitext(f)[1] in ['.jpg', '.gif', '.png']]<br /> return ctx.tag(src='/random_images/'+random.choice(files))<br /> </pre></code><br />3. Use the following tag wherever you want to have a randomly rotated image in your web app:<br /> <pre><code> &lt;img nevow:render="random_image" alt="Random Image" /&gt; </code></pre><br />Now you have a wonderfully randomly rotated image in your web browser and with 2 lines less than the Ruby On Rails counterpart without sacrifying readability too much.Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1114253662778361872005-04-23T11:50:00.000+02:002005-12-01T01:56:18.960+01:00Today I came across <a href="http://naeblis.cx/rtomayko/2005/04/22/on-http-abuse" title="Http Abuse">this</a> and I want to answer to Ryan since he deserves more than one answer.<br /><br />I strongly agree with Ryan but I notice he never tried using web2 (probably because it is not released yet) in Twisted Matrix. <br /><br /><blockquote>... have a sane mechanism for attaching different behavior to different verbs for a single resource?</blockquote><br /><br />In this near-to-be-released web server each renderable resource has a renderHTTP method that is used to dispatch the request to the right renderer method after looking at the request method. For example inside the resource you can have http_GET or http_POST or http_DELETE methods and so on.<br /><br /><blockquote>... help you use response status codes properly? (e.g. Nearly all dynamic content returns either a 200 or 500).</blockquote><br /><br />The result of each method call through renderHTTP must be a Response object which has the following signature:<br /><br /> def __init__(self, code=None, headers=None, stream=None):<br /><br />I don't think I need to tell what code is, but web2 contains a module that has all the HTTP response codes with a human-readable name (one of the main problems with response codes is that they are codes, and humans can't read them).<br /><br />headers is a simple dictionary of Headers:Values or directly an Headers object instance which will take care of header serialization and unserialization in an RFC compliant way.<br /><br /><blockquote>... make dealing with transfer encodings (gzip, compress, etc.) easy?</blockquote><br /><br />What's the stream argument in the signature above? It is a an object that allows you to handle input and output to and from the server (James Knight, the author, would say that it's an handy implementation of the Consumer/Producer model). There are many streams already available in Web2 like MemoryStream, FileStream (when sending a file to the clients), gzipstream, deflatestream and you can write your own if you like. The stream argument is the content you need to send if the stream doesn't support the Consumer logic or, alternatively, you can pass content to the stream using the write() method if it supports Consumer logic.<br /><br /><blockquote>... make dealing with media types easy?</blockquote><br /><br />MediaTypes are handled correctly with the MimeType object togheter with the corresponding serializer (which is handled transparently by web2, but you can provide your own).<br /><br /><blockquote>... provide facilities for implementing a smart caching strategy for dynamic content? (proper use of If-Modified-Since, Expires, Cache-Control, etc.)</blockquote><br /><br />It's not completely clear to me what this means. Caching dynamic content is very hard and the framework should never step-in IMHO. That is a completely user-driven feature but web2 allows you to put your headers in the response object, hence I believe this satisfies this point.<br /><br />What are my conclusions? Just give web2 a try. Come in #twisted.web on freenode to talk about future web2 and Nevow development (Nevow gave a lot of code to web2 resource handling mechanisms, but James Knight, web2 author, changed the original code enough to allow all the flexibility of the new model I just described in this post).<br /><br />As a Nevow developer I must say that I'm looking forward to the day when we move from twisted.web to twisted.web2 to enable all this new stuff, which I also need to handle from my software.<br /><br />To close everything: web2 already supports wsgi.Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1099478681713728692004-11-03T11:44:00.000+01:002004-11-03T11:47:48.980+01:00Some people are interested in my Gnus look, which you can find <a href="http://xoomer.virgilio.it/dialtone/Schermata.png" target="_parent">here</a>. <br /><br />Since it took me a lot of time to get it working I think I'll write down the steps I made:<br /><ul><br /><li>Installed Emacs-cvs with GTK2 support (it's pretty easy if you don't have any problem), here is the cvs address :ext:anoncvs@savannah.gnu.org:/cvsroot/emacs</li><br /><br /><li>Installed t-gnus (which is the multi-language Gnus version), FreeBSD5 has a port named t-gnus that will be installed under /usr/local/share/emacs/21.3/site-lisp, you should move it from 21.3 to 21.3.50 to use it under emacs-cvs. <a href="http://cvs.m17n.org/archives/gnus/" target="_parent">Here</a> you can find some versions like t-gnus-6_12_0-02 which I'm using</li><br /><br /><li>Then you are ready to use my .emacs with some stuff for python and Gnus. You can download it <a href="http://xoomer.virgilio.it/dialtone/my.emacs" target="_parent">here</a>.</li><br /></ul><br /><br />Hope This HelpsValentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1099053528632757212004-10-29T14:38:00.000+02:002004-10-29T14:38:48.633+02:00I'm a PDF!<br /><p><a href="http://www.bbspot.com/News/2004/10/extension_quiz.php"><img src="http://www.bbspot.com/Images/News_Features/2004/10/file_extensions/pdf.jpg" width="300" height="90" border="0" alt="You are .pdf No matter where you go you look the same. You are an acrobat. Nothing is more important to you than the printed word."><br>Which File Extension are You?</a></p><p><br />I'm a proprietary format. But I'm cross-platform anyway. I can get along with this ehe</p></p>Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1098298483509885432004-10-20T20:54:00.000+02:002004-10-20T20:54:43.510+02:00About "Seven Cool Mono Apps"<br /><p>I just read the last column on O'Reilly network <a href="http://www.oreillynet.com/pub/a/network/2004/10/18/mono.html">here</a> by Edd Dumbhill:</p><p><br /><blockquote></p><p><br />Because decoding audio itself isn't a simple process, there aren't any all-Mono ways of doing this yet. Instead, Muine uses the "p-invoke" facility of Mono to hook into the C-based multimedia library libxine. Calling C code from Mono doesn't require any supplemental C coding, unlike most other languages such as Perl or Python.</p><p><br /></blockquote></p><p><br />I would say that he is quite completely wrong. He maybe doesn't know anything about ctypes module, which is a rather complete and useful way to call functions inside compiled dynamic libraries.</p><p><br />You can find ctypes <a href="http://starship.python.net/crew/theller/ctypes/">here</a> with a little tutorial <a href="http://starship.python.net/crew/theller/ctypes/tutorial.html">here</a>. And now a little example, just to convince you about what I'm saying:</p><p><br /><blockquote> </p><p><br />>>> from ctypes import *</p><p><br />>>> print cdll.msvcrt.time(None)</p><p><br />1048777320</p><p><br />>>> print hex(windll.kernel32.GetModuleHandleA(None))</p><p><br />0x1d000000</p><p><br /></blockquote></p><p><br />See you to my next post</p>Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1088420942420060942004-06-28T13:02:00.000+02:002004-06-28T13:09:02.420+02:00Today, while surfing The Net, I bumped into <a href="http://blogs.devleap.com/DotNetBLog.aspx?PermaLink=07d18e81-ea20-4052-8eeb-3d737a4542e7">this</a> blog post from Marco Russo, a C# programmer. <br /> <br />Basically he is saying that generics are such a great feature because with them you can write stuff like this: <br /> <br />List integers = new List(); <br />for(int i=1; i<=10; i++) integers.Add(i); <br />int sum; <br />integers.ForEach(delegate(int i){ sum+=i; }); <br /> <br />Now, after reading that thing 3 times I realized that all it was doing was to sum the first 10 integers which can be done in this way using python: <br /> <br />sum([x for x in xrange(11)]) <br /> <br />Maybe times will come, when people will realize that such poor languages, like C# or java, are nowhere near highly dynamic ones like Python. And machine power is not giving them any reason to be learned.Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1085352746016281922004-05-24T00:52:00.000+02:002004-06-28T13:41:59.610+02:00Hi all, long time since my last posting. <br /> <br />As you probably know, I'm not a C++ expert, even if I can almost read C++ code without many problems. <br /> <br />One thing that I didn't know is that encapsulation is not that strong as it is belived to be, there are 2 techniques that enable you to access all attributes inside a class and I'm going to show you: <br /><blockquote> <br /> Technique 1: <br /> <br />class D { <br />public: <br /> int x; <br />}; <br /> <br /> C c; <br /> (reinterpret_cast&lt;D*&gt;(&c))->x = 1; <br /> <br /> Technique 2: <br /> <br />#define private public <br />#include &lt;C_definition.h&gt; <br />#undef private <br /> <br /> C c; <br /> c.x = 1; <br /></blockquote> <br /> <br />This is just to say that Python is not the only one that plays some tricks instead of having real private attributes/methods. But again who really needs private methods?Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1081367076099887872004-04-07T21:44:00.000+02:002004-04-07T21:50:21.640+02:00Today has been a busy day.<br /><br />My parents went to Creta, in the mediterranean sea, togheter with my brother. So I'm alone at home for Easter, good news for me and my girlfriend. But I had to bring them to the airport which is over an hour away from home.<br /><br />Then I had to answer some mails about my new rss aggregator. Alex Martelli proposed me to add it to the ActiveState cookbook, and maybe they'll add it to the next edition of the Python Cookbook.<br /><br />Then again Jan Alonzo, one of the Straw developers, mailed me about my rss-aggregator, telling that it was interesting and asking if I've already written a patch for straw. Unfortunately I haven't since Straw's code is not really clear to me, and I'll need a lot of help from them in order to integrate it correctly.<br /><br />And worst of all... In 20 days my University exams will start, I'll need to study a bit starting from tomorrow.<br /><br />So... This is going to be a tough month.Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1081276488192464972004-04-06T20:34:00.000+02:002004-05-28T18:27:04.343+02:00Lately I've been working on an rss aggregator made with python and Twisted. It's growing really fast, since twisted is marvellous. <br /> <br />Now the protocol supports a lot of things like: <br /><ul> <br /> <li> Arbitrary number of multiple simultaneus connections </li> <br /> <li> Request timeout </li> <br /> <li> Max age of each feed </li> <br /> <li> Memoizing of the feeds with a timestamp</li> <br /> <li> Multi-client modular design </li> <br /> <li> DOING: web interface, now I've only written a primitive one</li> <br /></ul> <br />I must say it. Twisted is a really impressive framework. <br /> <br />That's not the only thing I've been doing in the last days, as many of you know, on April 1st the GNOME team released their DE version 2.6, and today I've been busy searching for a good theme. Fortunately in the gentoo forums I've read of a project for making an official theme. <br /> <br />Here is how it looks: <br /><ul> <br /><li><a href="http://xoomer.virgilio.it/dialtone/screenshot.png" target="_parent">Full desktop</a></li> <br /><li><a href="http://xoomer.virgilio.it/dialtone/screenshot-1.png" target="_parent">Xmms Skin</a></li> <br /><li><a href="http://xoomer.virgilio.it/dialtone/Schermata-1.png" target="_parent">Old desktop</a></li> <br /><li><a href="http://xoomer.virgilio.it/dialtone/Schermata.png" target="_parent">My emacs GNUS screenshot</a></li> <br /></ul> <br />Cya next timeValentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1079626892499413592004-03-18T17:21:00.000+01:002004-03-18T17:23:56.576+01:00This is just a test posting, made to be sure that bloGTK is working to help me writing my blog.<br /><br />I think I'll start for real to write some good stuff on my blog. There are a lot of things to talk about and I would like to share them with you all.<br /><br />Cya next time :)Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.comtag:blogger.com,1999:blog-5608455.post-1058992494129250342003-07-23T22:34:00.000+02:002003-07-23T22:49:57.436+02:00Hi, all. This is my first post. I think this is the time for some presentations. I'm Valentino Volonghi, 20 years old and Italian. Proud linux user and fond of python. I think that anyone who works on python is a kind of a genius: Guido Von Rossum, Tim Peters and Alex Martelli (there are more and more but I have one thing to say about this last one). Today I decided to start this blog because of one thing: I need to say to anyone that I'll probably be working togheter with Alex Martelli... He is the best programmer I've ever known, we talked over an hour and a half and it was the best time spent in my life. <br /> <br />I hope to post some photograps in the future since I think I am very lucky :). <br /> <br />Obviously this is not my only passion, I also like mangas and anime a lot and I have a fairly big collection of mangas. <br />For this time it's all, I'm going to write again in the next days. <br /> <br />Oh, I forgot to say one thing: really thanks to a friend of mine: <a href="http://loluyede.blogspot.com">Lawrence Oluyede</a>. We both work for the same company and we both met Martelli. <br />Hi all.Valentinohttp://www.blogger.com/profile/13519795655711289924noreply@blogger.com