<?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>mFabrik - mobile sites, apps, HTML5 and CMS software development &#187; python</title>
	<atom:link href="http://blog.mfabrik.com/tag/python/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.mfabrik.com</link>
	<description>Freedom delivered.</description>
	<lastBuildDate>Wed, 03 Aug 2011 09:47:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>AJAX proxy view with Python, urllib and Plone</title>
		<link>http://blog.mfabrik.com/2011/08/02/ajax-proxy-view-with-python-urllib-and-plone/</link>
		<comments>http://blog.mfabrik.com/2011/08/02/ajax-proxy-view-with-python-urllib-and-plone/#comments</comments>
		<pubDate>Tue, 02 Aug 2011 08:26:42 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[javascript]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[access control]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[allow-access-origin]]></category>
		<category><![CDATA[cors]]></category>
		<category><![CDATA[cross domain]]></category>
		<category><![CDATA[getjson]]></category>
		<category><![CDATA[grok]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[restful]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1365</guid>
		<description><![CDATA[Old web browsers do not support Allow-acces-origin HTTP header needed to do cross-domain AJAX requests (IE6, IE7). Below is an example how to work around this for jQuery getJSON() calls by Detecting browsers which do not support this using jQuery.support API Doing an alternative code path through a local website proxy view which uses Python [...]]]></description>
			<content:encoded><![CDATA[<div class="body">
<p>Old web browsers do not support <a class="reference external" href="https://developer.mozilla.org/en/HTTP_access_control">Allow-acces-origin HTTP header</a> needed to do cross-domain AJAX requests (IE6, IE7).</p>
<p>Below is an example how to work around this for jQuery getJSON() calls by</p>
<ul class="simple">
<li>Detecting browsers which do not support this using jQuery.support API</li>
<li>Doing an alternative code path through a local website proxy view which uses Python <tt class="docutils literal">urllib</tt> to make server-to-server call and return it as it would be a local call, thus working around cross-domain restriction</li>
</ul>
<p>This example is for Plone/Grok, but the code is easily port to other Python web frameworks.</p>
<div class="note">
<p class="last"><em>Note: This is not a full example code. Basic Python and Javascript skills are needed to interpret and adapt the code for your use case.</em></p>
</div>
<p>Javascript example</p>
<pre class="literal-block">/**
 * Call a RESTful service vie AJAX
 *
 * The final URL is constructed by REST function name, based
 * on a base URL from the global settings.
 *
 * If the browser does not support cross domain AJAX calls
 * we'll use a proxy function on the local server. For
 * performance reasons we do this only when absolutely needed.
 *
 * @param {String} functionName REST function name to a call
 *
 * @param {Object} Arguments as a dictionary like object, passed to remote call
 */
function callRESTful(functionName, args, callback) {

    var src = myoptions.restService + "/" +functionName;

    // set to true to do proxied request on every browser
    // useful if you want to use Firebug to debug your server-side proxy view
    var debug = false;

        console.log("Doing remote call to:" + src)

        // We use jQuery API to detect whether a browser supports cross domain AJAX calls
        // http://api.jquery.com/jQuery.support/
        if(!jQuery.support.cors || debug) {
                // http://alexn.org/blog/2011/03/24/cross-domain-requests.html
                // Opera 10 doesn't have this feature, neither do IExplorer &lt; 8, Firefox &lt; 3.5

                console.log("Mangling getJSON to go through a local proxy")

                // Change getJSON to go to our proxy view on a local server
                // and pass the orignal URL as a parameter
                // The proxy view location is given as a global JS variable
                args.url = src;
                src = myoptions.portalUrl + "/@@proxy";
        }

        // Load data from the server
        $.getJSON(src, args, function(data) {
                // Parse incoming data and construct Table rows according to it
                console.log("Data succesfully loaded");
                callback(data, args);

     });

}</pre>
<p>The server-side view:</p>
<pre class="literal-block">import socket
import urllib
import urllib2
from urllib2 import HTTPError

from five import grok
from Products.CMFCore.interfaces import ISiteRoot
from mysite.app import options

class Proxy(grok.CodeView):
    """
    Pass a AJAX call to a remote server. This view is mainly indended to be used
    with jQuery.getJSON() requests.

    This will work around problems when a browser does not support Allow-Access-Origin HTTP header (IE).

    Asssuming only HTTP GET requests are made.s
    """

    # This view is available only at the root of Plone site
    grok.context(ISiteRoot)

    def isAllowed(self, url):
        """
        Check whether we are allowed to call the target URL.

        This prevents using your service as an malicious proxy
        (to call any internet service).
        """

        allowed_prefix = options.REST_SERVICE_URL

        if url.startswith(allowed_prefix):
            return True

        return False

    def render(self):
        """
        Use HTTP GET ``url`` query parameter for the target of the real request.
        """

        # Make sure any theming layer won't think this is HTML
        # http://stackoverflow.com/questions/477816/the-right-json-content-type
        self.request.response.setHeader("Content-type", "application/json")

        url = self.request.get("url", None)
        if not url:
            self.request.response.setStatus(500, "url parameter missing")

        if not self.isAllowed(url):
            # The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeate
            self.request.response.setStatus(403, "proxying to the target URL not allowed")
            return

        # Pass other HTTP GET query parameters direclty to the target server
        params = {}
        for key, value in self.request.form.items():
            if key != "url":
                params[key] = value

        # http://www.voidspace.org.uk/python/articles/urllib2.shtml
        data = urllib.urlencode(params)

        full_url = url + "?" + data
        req = urllib2.Request(full_url)

        try:

            # Important or if the remote server is slow
            # all our web server threads get stuck here
            # But this is UGLY as Python does not provide per-thread
            # or per-socket timeouts thru urllib
            orignal_timeout = socket.getdefaulttimeout()
            try:
                socket.setdefaulttimeout(10)

                response = urllib2.urlopen(req)
            finally:
                # restore orignal timeoout
                socket.setdefaulttimeout(orignal_timeout)

            # XXX: How to stream respone through Zope
            # AFAIK - we cannot do it currently

            return response.read()

        except HTTPError, e:
            # Have something more useful to log output as plain urllib exception
            # using Python logging interface
            # http://docs.python.org/library/logging.html
            logger.error("Server did not return HTTP 200 when calling remote proxy URL:" + url)
            for key, value in params.items():
                logger.error(key + ": "  + value)

            # Print the server-side stack trace / error page
            logger.error(e.read())

            raise e</pre>
</div>
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/08/02/ajax-proxy-view-with-python-urllib-and-plone/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Generic Python validation frameworks?</title>
		<link>http://blog.mfabrik.com/2011/07/07/generic-python-validation-frameworks/</link>
		<comments>http://blog.mfabrik.com/2011/07/07/generic-python-validation-frameworks/#comments</comments>
		<pubDate>Thu, 07 Jul 2011 14:48:15 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[validation]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1308</guid>
		<description><![CDATA[All Python ORM and form frameworks love to define own field/schema model. This seems to lead to a situation where they define their own validation functions too. Some examples: Django local flavour defines phone number validations for different countries Misc. regular expression validators in Plone&#8217;s Archetypes content type subsystem Every framework define their own email [...]]]></description>
			<content:encoded><![CDATA[<p>All Python ORM and form frameworks love to define own field/schema model. This seems to lead to a situation where they define their own validation functions too.</p>
<p>Some examples:</p>
<ul>
<li><a href="https://docs.djangoproject.com/en/dev/ref/contrib/localflavor/">Django local flavour defines phone number validations for different countries</a></li>
<li><a href="http://svn.plone.org/svn/archetypes/Products.validation/trunk/Products/validation/validators/BaseValidators.py">Misc. regular expression validators in Plone&#8217;s Archetypes content type subsystem</a></li>
<li>Every framework define their own email validator, with various regular expressions</li>
</ul>
<p>Isn&#8217;t writing one&#8217;s own validation code a bit redundant and exactly &#8220;reinventing the wheel&#8221; what open source principles so hard try to avoid? Could validation be a low hanging fruit to share among fellow Python projects? As I see it, for the simple data validation, like email and URL, the core code could be easily shared and different Python projects. You basically want just method is_valid_phonenumber(str) and then framework specific way to raise the error to the user.</p>
<p>Do such frameworks already exist? At least I haven&#8217;t seen one being used in any big Python project yet <img src='http://blog.mfabrik.com/wp-includes/images/smilies/icon_sad.gif' alt=':(' class='wp-smiley' /> </p>
<p>&#8230; or is validation so complex thing, so that validation functions must be tightly integrated with the parent framework and I am missing some big things (like locales, etc.) here?</p>
<p>&nbsp;
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/07/07/generic-python-validation-frameworks/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>Making Plone easy again (and Sauna Sprint topics)</title>
		<link>http://blog.mfabrik.com/2011/06/08/making-plone-easy-again-and-sauna-sprint-topics/</link>
		<comments>http://blog.mfabrik.com/2011/06/08/making-plone-easy-again-and-sauna-sprint-topics/#comments</comments>
		<pubDate>Wed, 08 Jun 2011 08:14:28 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[sauna sprint]]></category>
		<category><![CDATA[sphinx]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1274</guid>
		<description><![CDATA[This blog post is about making Plone CMS to accessible for more developers. This is a major topic on which we are working on in Sauna Sprint 2011 (see the previous blog post about Sauna Sprint and motivation to come to Finland). Preface Please do not take this post too seriously if I am ranting [...]]]></description>
			<content:encoded><![CDATA[<p>This blog post is about making <a href="http://plone.org">Plone CMS</a> to accessible for more developers. This is a major topic on which we are working on in Sauna Sprint 2011 (<a href="http://blog.mfabrik.com/2011/06/08/sauna-sprint-2011-motivational-blog-post-%E8%9A%8A%E3%81%8C%E6%A5%BD%E3%81%97%E3%81%84%E3%81%A7%E3%81%99/">see the previous blog post about Sauna Sprint and motivation to come to Finland</a>).</p>
<h2>Preface</h2>
<p>Please do not take this post too seriously if I am ranting tongue-in-cheek. This thinking does not reflect the official opinion of Sauna Sprint team any way, it is just my personal rambling.</p>
<h2>Background</h2>
<p>Plone is having popularity issues. This can be deducted by:</p>
<ul>
<li>PHP CMS are more popular (Google trends and so on)</li>
<li><a href="http://amplicate.com/love/plone">Plone lacks love</a></li>
<li>By discussing with Python programmers outside Plone community: they see Plone as monster</li>
</ul>
<p>Plone is a superior CMS product (feature wise, polish wise, tech wise, and so on). So how did this happen?</p>
<p>My theory, you are free to disagree, is that the community has been driving &#8220;wrong&#8221; ideologies</p>
<ul>
<li>Plone&#8217;s &#8220;buyers&#8221; are not users, but developers</li>
<li>There has been no driving community factor to make Plone accessible for more developers. Plone community has been working to make Plone work for the existing community members, not new members. The consulting companies have been too busy to extract money from their existing big clients. It might even be that it&#8217;s the best interest of these companies to keep the barrier of entry high, as this way they protect the Plone business for themselves. Note that this strategy will fail in the point there is no longer Plone business.</li>
</ul>
<p>The big boys are telling that customers are abandoning Plone, because there are no developers. I know a lot of Plone developers, looking for more Plone work.  I&#8217;ll translate this that there are not enough affordable Plone developers entering the market.</p>
<p>I am also not buying arguments like</p>
<ul>
<li>&#8220;don&#8217;t compare apples to oranges (Django vs. Plone)&#8221;</li>
<li>&#8220;its history and evolved that way&#8221;</li>
<li>&#8220;big tool must be complex&#8221;</li>
</ul>
<h2>The result</h2>
<p>Plone is easy to use, but hard to develop. <strong>If you need to use code generators and boiler-plate in Python code, you are doing it wrong.</strong></p>
<p>Plone is a soup of different, non-mainstream, technologies. To be a Plonista you need master: Python (ok docs), Plone user mode (good docs),  Zope component architecture (some docs), ZCML (no useful docs), GenericSetup  (no docs), TAL (some docs), Archetypes (basically no docs), buildout  (aaaaaarghs) &#8230; You have too much to learn from material which does not exist. Today the material effectively does not exist if it&#8217;s not your first Google hit &#8211; I am against book.</p>
<p>New developers are not getting in. It is easier to duplicate basic Plone functionality in a hacky in-house Django CMS than customize Plone for your use case. Plone does not give any more added value to the new developers. There is no business motivation to adapt Plone as a technology platform in new ventures.</p>
<h2>The quest</h2>
<p>Let&#8217;s fix it, as I see the developer acceptance the most crucial challenge Plone community is facing if the community wants to survive.</p>
<p>What we can do here is</p>
<ul>
<li>Make Plone easier for developers</li>
<li>Make more, better, learning material available</li>
<li>Eliminate and protect against factors in Plone which hinder the goals of two above bullets (do not include new technologies or modules to core if they make developers sad)</li>
</ul>
<p>To accomplish this we can</p>
<ol>
<li>Promote &#8220;easy&#8221; technologies inside and outside Plone community (Dexterity over Archetypes, Grok over ZCML)</li>
<li>Making a standard workflow available for them (Django style tutorial that do 1, 2, 3 and you are a certified Plone developer)</li>
<li>Kill technologies which make the stack unnecessary complex and are not necessarily needed in newbie use cases (buildout, I am looking at you)</li>
<li>Replace old, badly documented and difficult solutions with easier ones  (could we actually replace TAL with something more popular?)</li>
</ol>
<h2>Operational plan</h2>
<p>Here are some concrete tasks what we could tackle in Sauna Sprint.</p>
<p>Make it easy department</p>
<ul>
<li>Plone auto-restart team: provide working and fast auto-restart á la Django or Tornado (hint: plone.reload doesn&#8217;t cut it &#8211; you need real restarts process-wise)</li>
<li>Default custom product team: ship Plone with a file-system based custom product skeleton, so that when you need to include your first custom Python module you don&#8217;t need to learn about buildout and paster first . You actually can copy-paste in Python code and it just works.</li>
<li>Through-the-web is happy again team: Make it possible to code and execute Python through-the-web so that it actually works.: a working replacement for RestrictedPython</li>
</ul>
<p>Fix user-wise broken things department</p>
<ul>
<li>Buildout team: make buildout more user friendly: spit out error messages which are actually useful, have newbie buildout tutorial from the developer perspective. Nothing bad should happen when buildout is run. Make buildout to confirm version updates, etc.</li>
<li>Anti-buildout team: how to install eggs without buildout. Why did we need the buildout in the first place?</li>
</ul>
<p>This is how you do it department</p>
<ul>
<li>Tutorial team: Make &#8220;gapless&#8221; hand-holding tutorial for creating your first view, form and content-type. Make it so that you do not need to look outside the tutorial or learn anything unnecessary (don&#8217;t make me think)</li>
<li>Picture team: draw big pictures of Plone architecture, how different parts are connected, so that new developers get hang on things easily</li>
<li>Document generator team: Integrate collective.developermanual with Sphinx tool that generate the reference  documentation from the source code: views, viewlets, templates, CSS classes, portlets, etc.</li>
</ul>
<p>Hasta la vista babe department</p>
<ul>
<li>Kill it with fire team: Hunt down all bad learning material and make it redirect to new learning material (no ExternalMethods, no Install.py, no plone_skins, etc.)</li>
<li>Nuke it from orbit team: I am not sure what this team could do, but I like the feeling of the name</li>
</ul>
<p>We hope that novice  developers attend the sprint. This way we can use you as guinea pigs and document the pain points on a road to become Plone developer. Don&#8217;t worry &#8211; we&#8217;ll inject you with proper medicine to numb the pain and forget bad memories.
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/06/08/making-plone-easy-again-and-sauna-sprint-topics/feed/</wfw:commentRss>
		<slash:comments>19</slash:comments>
		</item>
		<item>
		<title>Python Interest Group Finland &#8211; official constitutive meeting (+DjangoCon)</title>
		<link>http://blog.mfabrik.com/2011/04/26/python-interest-group-finland-official-constitutive-meeting-djangocon/</link>
		<comments>http://blog.mfabrik.com/2011/04/26/python-interest-group-finland-official-constitutive-meeting-djangocon/#comments</comments>
		<pubDate>Tue, 26 Apr 2011 08:23:26 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[djangocon]]></category>
		<category><![CDATA[doodle]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1252</guid>
		<description><![CDATA[Python users in Finland are organizing and we have booked a meeting for establishing an association. In this meeting, we&#8217;ll create an official papers for registering our association in National Boards of Patents and Registrations of Finland. The rules for the association are accepted The rules include the purpose of the association: the main purpose [...]]]></description>
			<content:encoded><![CDATA[<p>Python users in Finland are organizing and we have booked a meeting for establishing an association. In this meeting, we&#8217;ll create an official papers for registering our association in National Boards of Patents and Registrations of Finland.</p>
<ul>
<li>The rules for the association are accepted</li>
<li>The rules include the purpose of the association: the main purpose is to arrange yearly Pycon Finland event</li>
<li>The association will have its own bank account to deal with Pycon expenses and tickets</li>
<li>Naturally, the association will also further promote Python in Finland</li>
</ul>
<p>The meeting is held in 7.5.2011 <a href="http://djangocon.fi/">at the same time with DjangoCom Finland</a>.</p>
<p>If you want to participate our Python group activity please read the note below. Unfortunately it&#8217;s in Finnish, but I can provide translation if there are English speaking people who want to partipate:</p>
<div>
<div><a href="http://groups.google.com/group/pigfi/browse_thread/thread/1f0c1aeffdd1013">Python Suomi ry perustamiskokous 7.5.2010 10:00 Espoo &#8211; myös ETÄYHTEYS</a></div>
</div>
<p>Klara vappen!
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/04/26/python-interest-group-finland-official-constitutive-meeting-djangocon/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Including widget specific Javascripts in Plone using Python conditions</title>
		<link>http://blog.mfabrik.com/2011/04/13/including-widget-specific-javascripts-in-plone-using-python-conditions/</link>
		<comments>http://blog.mfabrik.com/2011/04/13/including-widget-specific-javascripts-in-plone-using-python-conditions/#comments</comments>
		<pubDate>Wed, 13 Apr 2011 09:27:51 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[behavior]]></category>
		<category><![CDATA[compress]]></category>
		<category><![CDATA[content type]]></category>
		<category><![CDATA[dexterity]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[minimize]]></category>
		<category><![CDATA[static media]]></category>
		<category><![CDATA[widget]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1215</guid>
		<description><![CDATA[Here is described a way to include Javascript for certain widgets or certain pages only in Plone CMS Javascripts are processed through portal_javascripts utility automatically, making them suitable for production deployment (minimized, cached). Plone does all this for you. Also the same rules apply for CSS and portal_css tool. A special condition is created in [...]]]></description>
			<content:encoded><![CDATA[<p>Here is described a way to include Javascript for certain widgets or certain pages only in <a href="http://plone.org">Plone</a> CMS</p>
<ul>
<li>Javascripts are processed through <em>portal_javascripts</em> utility automatically, making them suitable for production deployment (minimized, cached). Plone does all this for you. Also the same rules apply for CSS and <em>portal_css</em> tool.</li>
<li>A special condition is created in Python code to determine whether to include the script or not on a page: it checks whether we are on a page needing the script and then signals portal_javascript which in turn puts the script to HTML &lt;head&gt; section</li>
<li>Javascripts are served from a <em>static</em> media folder in a Plone add-on utilizing <a href="http://grok.zope.org">Grok</a> framework. Static media folder is mapped to unique <em>resource</em> names spaces (++resource++yourpythonmodule.name), so that there are no file conflicts between different add-ons.</li>
<li>These instructions mainly are designed for <a href="http://plone.org/products/dexterity">Dexterity content type subsystem</a>, but can be used with any content types by replacing the behavior check with a marker interface check</li>
</ul>
<p>Dexterity content types can use Dexterity <em>behaviors </em>control panel to add new behaviors on your content types. One such a behavior is to include certain Javascript files when these content types are viewed or edited.</p>
<p>The example here shows how to include a Javascript if the following conditions are met</p>
<ul>
<li>You are developing a Plone add-on as a Python package (as oppose, to say, edit files directly through-the-web)</li>
<li>Content type has a certain Dexterity behavior applied on it</li>
<li>Different files are served for view (visitors) and edit modes (content editing interface)</li>
</ul>
<div>
<p><em>Note: There is no easy way currently directly check whether a certain widget and widget mode is active on a particular view. Thus, we do some assumptions and checks manually if we are on &#8220;edit&#8221; view.</em></p>
<p>Plone <em>portal_javascripts </em>is a site specific registry. Available javascripts are kept in the site database, so that you can fine-tune their settings on-line, through-the-web through Zope application server management interface. When Plone add-on is installed, a subsystem called GenericSetup can import database setting changes on XML based profiles. There is a tool called portal_setup which allows you easily to export, import or put parts of this setting updates to your add-on installer.<em><br />
</em></p>
</div>
<p>We import Javascript files to portal_javascripts using GenericSetup file jsregistry.xml:</p>
<pre>&lt;?xml version="1.0"?&gt;
&lt;object name="portal_javascripts"&gt;

        &lt;!-- View mode javascript --&gt;
        &lt;javascript
                id="++resource++yourcompany.app/integration.js"
                authenticated="False"
                cacheable="True" compression="safe" cookable="True"
                enabled="True" expression="context/@@integration_javascript"
                inline="False"
                /&gt;

        &lt;!-- Edit mode javascript --&gt;
        &lt;javascript
                id="++resource++yourcompany.app/integration.edit.js"
                authenticated="False"
                cacheable="True" compression="safe" cookable="True"
                enabled="True" expression="context/@@edit_integration_javascript"
                inline="False"
                /&gt;

&lt;/object&gt;</pre>
<p>Then we create the special conditions using Grok views and Python code. This code would go to <em>yourcompany/app/browser/views.py</em> Python module:</p>
<pre># Zope imports
from Acquisition import aq_inner
from zope.interface import Interface
from five import grok
from zope.component import getMultiAdapter

from yourcompany.app.behavior.lsmintegration import IYourWidgetIntegration

class IntegrationJavascriptHelper(grok.CodeView):
    """ Used by portal_javascripts to determine when to include our
        custom Javascript integration code.

    This view is referred from the expression in jsregistry.xml.
    """

    # The view is available on every content item type
    grok.context(Interface)
    grok.name("integration_javascript")

    def render(self):
        """ Check if we are in a specific content type.

        Check that the Dexerity content type has a certain
        behavior set on it through Dexterity settings panel.

        Alternative, just check for a marker interface here.
        """

        # render() methot is a the only traversable
        # Grok CodeView method. It can be used for rendering
        # HTML code, but also for utility views
        # to return raw Python data

        try:
            # Check if a Dexterity behavior is available on the current context object
            # - if it is not, behavior adapter will raise TypeError
            avail = IYourWidgetIntegration(self.context)
        except TypeError:
            return False

        # If called directly from the browser like
        # http://localhost:8080/Plone/integration_javascript
        # will return HTTP 204 No Content

        return True

class EditModeIntegrationJavascriptHelper(IntegrationJavascriptHelper):
    """ Used by portal_javascripts to determine when to include our custom Javascript
        integration code *on edit pages* only.

    Subclass the existing checked and add more limiting conditions.
    """
    grok.name("edit_integration_javascript")

    def render(self):
        """
        @return True: If this template is rendered "Edit view" of the item
        """

        if not IntegrationJavascriptHelper.render(self):
            # We are not even on the correct content type
            return False

        # This is a hacked together as Plone does not provide a real
        # mechanism to separate edit views to other views.
        # We simply check if the current view URI ends with "edit"

        path = self.request.get("PATH_INFO", "")

        if path.endswith("/edit") or path.endswith("/@@edit"):
            return True

        return False</pre>
<p>Question: how much Grok is included with Plone 4.1: at least parts of its are, but would this example work with vanilla Plone 4.01 without including five.grok manually as a dependency?
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/04/13/including-widget-specific-javascripts-in-plone-using-python-conditions/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Reducing MySQL memory usage on Ubuntu / Debian Linux</title>
		<link>http://blog.mfabrik.com/2011/03/31/reducing-mysql-memory-usage-on-ubuntu-debian-linux/</link>
		<comments>http://blog.mfabrik.com/2011/03/31/reducing-mysql-memory-usage-on-ubuntu-debian-linux/#comments</comments>
		<pubDate>Thu, 31 Mar 2011 10:56:46 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[mysql]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[debian]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[memory]]></category>
		<category><![CDATA[mtop]]></category>
		<category><![CDATA[ram]]></category>
		<category><![CDATA[res]]></category>
		<category><![CDATA[top]]></category>
		<category><![CDATA[ubuntu]]></category>
		<category><![CDATA[virt]]></category>
		<category><![CDATA[virtual memory]]></category>
		<category><![CDATA[Wordpress]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1149</guid>
		<description><![CDATA[If you are running your services on a low end virtual hosting every byte of memory you can save is important. The memory is often the limiting factor of how many applications you can run on VPS: CPUs are shared, memory not, on the same physical host. Low-end VPS come with 512 MB memory or [...]]]></description>
			<content:encoded><![CDATA[<p>If you are running your services on a low end virtual hosting every byte of memory you can save is important. The memory is often the limiting factor of how many applications you can run on VPS: CPUs are shared, memory not, on the same physical host.</p>
<ul>
<li>Low-end VPS come with 512 MB memory or less</li>
<li>Front front-end server Apache / Nginx / Varnish takes &gt; 100 MB +  min. 20 MB for each child process</li>
<li>Memecached takes its toll</li>
<li>MySQL takes 200 &#8211; 400 MB</li>
<li>Each Python / PHP process takes at least 15 MB and you need parallel processes for paraller HTTP requests (FCGI, pre-fork, others&#8230; )</li>
<li>Operating system processes need some memory (SSH, cron, sendmail)</li>
</ul>
<p>As you can see it gets very crowded in 512 MB.</p>
<p>It&#8217;s especially troublesome since the memory is allocated lazily and the memory usage builds up slowly. In some point caches are no longer caches, but swapped to a disk &#8211; virtual memory usage grows beyond available RAM. To keep the server response, everything time critical should fit to RAM once and if the processes themselves don&#8217;t know how to release memory in this situation you need to tune a memory cap for them.</p>
<h2>MySQL memory consumption</h2>
<p>MySQL can be a greedy bastard what comes to memory consumption. Here on this server MySQL seems to take 417M virtual memory which seems to be little excessive for just running two WordPress instances and one Django / Python application:</p>
<pre>1310 mysql     20   0  417M 21100  2776 S  0.0  1.2  0:00.00 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=mysql --pid-file=/v</pre>
<p>After some tuning I was able to bring it down a bit</p>
<pre>3354 mysql     20   0  276m  19m 2848 S    0  1.2   3:41.19 mysqld</pre>
<p>A reduction of 130 MB, or 1/4 of the server total memory. Not bad.</p>
<p><a href="http://ubuntu-snippets.blogspot.com/2009/02/mtop-mysql-monitor.html">Use mtop to monitor running MySQL</a>, its querieries, etc. so you know what&#8217;s going on. As you can see this MySQL has very good cache rate meaning that basically it is keeping everything in memory. If the content of the sites is less than 10 MBytes total, 400 MB contains plenty of space to cache the content:</p>
<pre>load average: 0.05, 0.08, 0.16 mysqld 5.0.51a-3ubuntu5.8-log up 1 day(s), 19:47 hrs                                                             
2 threads: 1 running, 6 cached. Queries/slow: 187.1K/0 Cache Hit: 99.39%</pre>
<h2>What eats memory</h2>
<p>I am not an expert on MySQL, so I hope someone with more insight could post comments regarding how to tune MySQL for low memory situations and how it is expected to behave.</p>
<p>Some ideas I run through my head</p>
<ul>
<li>MySQL default cache settings are not too tight on Ubuntu/Debian, making it suitable for moderate loads, not low loads. If you don&#8217;t have much content, everything is just kept in memory (even if not needed)</li>
<li>MySQL uses round robin for connections and if there is 100 max connections it will allocate a thread stack for each connection (someone please confirm this &#8211; I found contracting infos).</li>
</ul>
<h2>Configuring MySQL</h2>
<p>Here are listed some methods how to reduce the memory usage. This is what I done on this little box</p>
<p>MySQL is mostly configured in <em>/etc/mysql/my.cnf</em> on Ubuntu / Debian.</p>
<ul>
<li>Let&#8217;s halve key_buffer from 16M to 8M. <a href="http://dev.mysql.com/doc/refman/5.0/en/myisam-key-cache.html">It is used by MyISAM table cache</a>.</li>
<li>Halve <a href="http://techgurulive.com/2010/10/20/query_cache_size-tuning-optimizing-my-cnf-file-for-mysql/">query_cache_size</a>. query_cache_size  = 8M. Also, decrease query_cache_limit to 512 K.</li>
<li><a href="http://www.mysqlperformanceblog.com/2006/05/17/mysql-server-memory-usage/">Each connection, even if idle, will have 256 KB buffer</a>. Decrease the number of max. connections. (XXX: not sure about this). Drop max connections from 100 -&gt; 30, as we do not have that many concurrent visitors on the site. Also, set less aggressive thread_stack size.</li>
</ul>
<p>The final adjustments</p>
<pre>key_buffer              = 8M
max_connections         = 30
query_cache_size        = 8M
query_cache_limit       = 512K
thread_stack            = 128K</pre>
<h2>More info</h2>
<ul>
<li><a href="http://www.zimbio.com/Linux/articles/692/Fine+Tuning+MYSQL+Reducing+Memory+Usage">Fine-tuning MySQL</a></li>
<li><a href="http://www.electrictoolbox.com/mysql-table-storage-engine/">Showing what database engine MySQL tables are using</a></li>
<li><a href="http://www.mysqlperformanceblog.com/2006/05/17/mysql-server-memory-usage/">MySQL server memory usage</a></li>
<li><a href="http://www.lowendbox.com/blog/reducing-mysql-memory-usage-for-low-end-boxes/">Reducing MySQL memory usage for low end boxes</a></li>
</ul>
<p>Send in more tips please! Is 32-bit better than 64-bit for low end VPS, how much this affects MySQL?
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/03/31/reducing-mysql-memory-usage-on-ubuntu-debian-linux/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>When Python sucks: how you call a function and document it</title>
		<link>http://blog.mfabrik.com/2011/03/29/when-python-sucks-how-you-call-a-function-and-document-it/</link>
		<comments>http://blog.mfabrik.com/2011/03/29/when-python-sucks-how-you-call-a-function-and-document-it/#comments</comments>
		<pubDate>Tue, 29 Mar 2011 09:11:38 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[django]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[epytext]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[zope]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1175</guid>
		<description><![CDATA[Though maybe written tongue-in-cheek, this Python Makes Me Nervous article has some excellent points. Because of duck-typing, you should rigorously document how methods should be called (try epytext and its fields). Most open source Python projects do the exact opposite Even Python standard library is poorly documented and sets a very bad example (missing manual [...]]]></description>
			<content:encoded><![CDATA[<p>Though maybe written tongue-in-cheek, this <a href="http://teddziuba.com/2008/12/python-makes-me-nervous.html">Python Makes Me Nervous article</a> has some excellent points.</p>
<ul>
<li>Because of duck-typing, you should rigorously document how methods should be called (try <a href="http://epydoc.sourceforge.net/epytext.html">epytext</a> and its fields).</li>
<li>Most open source Python projects do the exact opposite</li>
<li>Even Python standard library is poorly documented and sets a very bad example (<a href="http://www.voidspace.org.uk/python/articles/urllib2.shtml">missing manual</a> ???)</li>
<li>Thus, programming in Python becomes nightmare of grepping through source code (the implementation) or stepping into it in pdb just to figure out how APIs should work (<a href="http://collective-docs.plone.org/security/permission_lists.html#listing-different-available-permissions">Plone/Zope,</a> anyone?)</li>
</ul>
<p>Should Python community stop in some point to focus on delivering better documentation instead of focusing on new features and goodies (like the syntax moratorium which was recently lifted)?</p>
<p>﻿﻿From my personal experience</p>
<ul>
<li>The best, and the only, person to document the code adequately is the person how originally wrote it</li>
<li>Because the author already knows how to use the code he doesn&#8217;t need to care about the fact how to enable the code for other users.  Many libraries and projects are driven by &#8220;scratching your own need&#8221; mentality, not by &#8220;let&#8217;s make this a happy community&#8221; mentality. The exception is something like Facebook or Google whose sole purpose is to attract new users their platform bringing in new €€€.</li>
<li>If you are developing a framework or community project make the documentation a requirement for deliverable and stick with it. If you let one person to skip one hour of writing documentation you are making 10 persons spending one hour figuring out how to use the damn thing.</li>
<li>Doctests are not documentation. They are tests. They are extremely unreadable way to say &#8220;how I should use this thing&#8221;, because doctests are often executed in the context of test stubs which do not reflect connections to the other parts of the framework or real contexts.</li>
<li>&#8220;Buy a book &#8211; it tells you everything&#8221; business model is not feasible in long run. Books get old. Books are not searchable. People don&#8217;t buy books.</li>
</ul>
<p>The good documentation is a way to differentiate, and win, in the situation where there are competing frameworks. I believe the success of Django was mostly driven by its good documentation.</p>
<p>This points could be applied to other duck-typed, open source driven programming languages (PHP anyone?). With good documentation we can reduce the need of Valium recipes for everyone of us.</p>
<p>&nbsp;
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/03/29/when-python-sucks-how-you-call-a-function-and-document-it/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>QuasselDroid: Quassel for Android  &#8211; cross-platform mobile IRC client</title>
		<link>http://blog.mfabrik.com/2011/03/28/quasseldroid-quassel-for-android-cross-platform-mobile-irc-client/</link>
		<comments>http://blog.mfabrik.com/2011/03/28/quasseldroid-quassel-for-android-cross-platform-mobile-irc-client/#comments</comments>
		<pubDate>Mon, 28 Mar 2011 18:42:28 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[android]]></category>
		<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[irc]]></category>
		<category><![CDATA[irssi]]></category>
		<category><![CDATA[logcat]]></category>
		<category><![CDATA[quassel]]></category>
		<category><![CDATA[quasseldroid]]></category>
		<category><![CDATA[sdk]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1112</guid>
		<description><![CDATA[IRC (Internet Relay Chat, the description of IRC) is a chat protocol used by many open source and hacktivism projects for real-time discussion and support chat. I myself participate to Python and Plone discussion and now recently to Android chat on Freenode and IRCNet networks. Quassel is a distributed IRC client. Distributed in the sense [...]]]></description>
			<content:encoded><![CDATA[<p>IRC (Internet Relay Chat, <a href="http://www.youtube.com/watch?v=O2rGTXHvPCQ">the description of IRC</a>) is a chat protocol used by many open source and hacktivism projects for real-time discussion and support chat. I myself participate to Python and Plone discussion and now recently to Android chat on Freenode and IRCNet networks.</p>
<p>Quassel is a distributed IRC client. Distributed in the sense that it keeps your chat sessions on the server side: even if you get disconnected you won&#8217;t lose any chat messages. This is a nice feature for people who need to be constantly in touch with the communities.  For IRC veterans, Quassel is like the good ol&#8217; screen + irssi combo, but with an user interface which does not require a degree in Perl scripting. This is a short tutorial for getting or building  the mobile version of Quassel,  Quasseldroid for Android.</p>
<p><a href="http://blog.mfabrik.com/wp-content/uploads/2011/03/SC20110328-2053501.png"><img class="alignnone size-medium wp-image-1167" title="SC20110328-205350" src="http://blog.mfabrik.com/wp-content/uploads/2011/03/SC20110328-2053501-180x300.png" alt="" width="180" height="300" /></a></p>
<p>Everyone how has tried it knows that irssi or any terminal software suits very badly for mobile screens. QuasselDroid fixes this: it provides an user interface which is suitable even for touch screens. Also, with Quassel core on the server side, you do not need to worry about disconnections which often happen with mobile networks, With desktop Quassel and mobile QuasselDroid you should be able to  seamlessly leave your desktop, go traveling whilst continuing the  on-going dispute of the next most important internet thing with your  on-line friends and foes.</p>
<p>This tutorial show how to get binary or source from  Github and compile the project for your phone. Note that <em>QuasselDroid is still in very early developing phase</em> and the main purpose of this is to drive more development into QuasselDroid. Do not expect it to be ready for your specific use cases yet! Also, these instructions are tested only on Samsung Galaxy S with Android 2.2.</p>
<p><a href="http://blog.mfabrik.com/wp-content/uploads/2011/03/SC20110328-205252.png"><img class="alignnone size-medium wp-image-1169" title="SC20110328-205252" src="http://blog.mfabrik.com/wp-content/uploads/2011/03/SC20110328-205252-180x300.png" alt="" width="180" height="300" /></a></p>
<p>Quassel is originally based on Qt C++ libraries and uses Qt based serialization protocol to communicate between the server (your IRC session) and client (your phone). QuasselDroid implements Qt protocol from scratch in Java and does not use any Qt libraries on Android. There also existed a prior version which required a proxy server, but this has been fixed for now.</p>
<h2>Getting and building QuasselDroid</h2>
<p>Before proceeding you need</p>
<ul>
<li>A server which allows you to run a background process with more than hundred megabytes of memory usage</li>
<li><a href="http://quassel-irc.org/downloads">Quassel core</a> installed on the server side (this maintains your IRC session). Core  itself comes with decent command-line help. If you get stuck ask help on  #quassel channel @ freenode IRC network.</li>
<li>Preferable <a href="http://quassel-irc.org/downloads">Quassal desktop client</a> (Windows, OSX, Linux) for ircing from the desktop</li>
</ul>
<h3>Downloading pre-built binary</h3>
<p>Note: there exists a pre-built Android binaries for non-Android hackers. <a href="https://github.com/sandsmark/QuasselDroid/wiki/QuasselDroid-Wiki ">Download QuasselDroid Android binary from here</a>. You still need to set-up the server side core yourself.</p>
<h3>Prerequisites for building and running QuasselDroid</h3>
<p>This is the recommend method of installing QuasselDroid if you are looking for helping in QuasselDroid development. It is not that difficult, as Android tools are quite friendly for newcomers.</p>
<ul>
<li>OSX or Linux (your mileage on Windows may vary)</li>
<li>Android Phone (Android 2.1 or newer)</li>
<li><a href="http://developer.android.com/sdk/index.html">Android SDK</a></li>
<li><a href="http://www.eclipse.org/downloads/">Eclipse IDE for Java Developers</a></li>
<li>Android Eclipse plug-in (<a href="http://developer.android.com/sdk/installing.html">you need to install it through Find and Install updates inside Eclipse</a>)</li>
<li>Git (for OSX use <a href="http://www.macports.org/">Macports</a> to install it)</li>
<li>Minimal understanding of terminal and UNIX style command line</li>
</ul>
<h3>Compiling and running</h3>
<p>Install Android SDK, Eclipse  Android plug-ins for Eclipse. Note this is several hundreds of megabytes worth of software, so be patient and entertain yourself with some cool music whilst downloading.</p>
<p>Install Quassel client, Quassel core and get yourself familiar with the noveau IRC experience.</p>
<p>Get code from Github:</p>
<pre>git clone https://github.com/sandsmark/QuasselDroid</pre>
<p>Open project in Eclipse. Start Eclipse, choose or create any empty directory as workspace of just choose the default one. Then choose <em>File -&gt; Import -&gt; General -&gt; Existing projects into Workspace</em>. In Select Root Directory you need to choose a directory <strong>above</strong> Github checkout directory. Select QuasselDroid in Projects list (which is now refreshed after selecting root directory).</p>
<p>In this point I had to select the project, choose <em>Project -&gt; Clean</em> from Eclipse menu (there were some errors popping up in Eclipse internal console).</p>
<p>Right click <em>Project -&gt; choose Run as -&gt; Android application</em>.</p>
<ul>
<li>If your phone is connected via USB Eclipse will automatically build and install APK directly to your phone</li>
<li>If you do not have phone connected QuasselDroid will start in the emulator</li>
</ul>
<h2>Installing QuasselDroid</h2>
<h3><a href="http://blog.mfabrik.com/wp-content/uploads/2011/03/SC20110328-205210.png"><img class="alignnone size-medium wp-image-1168" title="SC20110328-205210" src="http://blog.mfabrik.com/wp-content/uploads/2011/03/SC20110328-205210-180x300.png" alt="" width="180" height="300" /></a></h3>
<h3>Creating a core entry</h3>
<p>When QuasselDroid is run for the first time. press Android <em>Menu</em> key on the start-up screen(this was little hard to discover) and choose Manage cores. Now you need to configure quassel core for the server &#8211; for this process you should already have experience with Quassel desktop client.</p>
<h3>SSL</h3>
<p>Also, you might need to disable SSL support if you are running a core without SSL compiled in. Again, press Android Menu key, choose <em>Preferences</em> and uncheck <em>SSL</em>.</p>
<h2>Debugging issues</h2>
<p>When you run an issue and you can repeat it reliably with necessary log traces available, file a bug report <a href="https://github.com/sandsmark/QuasselDroid/issues">on Github project page</a>.</p>
<p>Android has a logging tool called LogCat, showing log output from emulator or device. You will see Android log output in Eclipse in LogCat view when</p>
<ul>
<li>Emulator is running</li>
<li>A device is connected via USB, debug mode enabled (from system <em>Settings</em> menu)</li>
</ul>
<p>Use Eclipse <em>Window -&gt; Show -&gt; Debug perspective</em> to see LogCat window if it&#8217;s hidden.</p>
<p>If you launch the application in Eclipse using Debug run (the bug icon) Eclipse will stop on the line where an uncaught Java exception is thrown. This is very useful for debugging crashing bugs (Android pops up force close dialog).</p>
<p>On the server side, you can see quasselcore output in stdout and see how the core reacts to client connection attempts.
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/03/28/quasseldroid-quassel-for-android-cross-platform-mobile-irc-client/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Run your Python application using PyPy &#8211; it&#8217;s fast!</title>
		<link>http://blog.mfabrik.com/2011/03/26/run-your-python-application-using-pypy-its-fast/</link>
		<comments>http://blog.mfabrik.com/2011/03/26/run-your-python-application-using-pypy-its-fast/#comments</comments>
		<pubDate>Sat, 26 Mar 2011 18:14:18 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[compiler]]></category>
		<category><![CDATA[distribute]]></category>
		<category><![CDATA[easy_install]]></category>
		<category><![CDATA[jit]]></category>
		<category><![CDATA[multiprocessing]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[plac]]></category>
		<category><![CDATA[pypy]]></category>
		<category><![CDATA[setuptools]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1153</guid>
		<description><![CDATA[Try your Python application with PyPy, the new hot Python JIT compiler Your program will run faster&#8230; &#8230; faster&#8230; and ..faster! Here are quick instructions for using PyPy on OSX. You should be able to apply these instructions to other UNIX systems as well. Install PyPy by getting binary tarball. wget http://pypy.org/download/pypy-1.4.1-osx64.tar.bz2 tar -xjf pypy-1.4.1-osx64.tar.bz [...]]]></description>
			<content:encoded><![CDATA[<p>Try your Python application with <a href="http://pypy.org/">PyPy</a>, the new hot Python JIT compiler</p>
<ul>
<li>Your program will run faster&#8230;</li>
<li>&#8230; faster&#8230;</li>
<li>and ..faster!</li>
</ul>
<p>Here are quick instructions for using PyPy on OSX. You should be able to apply these instructions to other UNIX systems as well.</p>
<p><a href="http://pypy.org/download.html">Install PyPy by getting binary tarball</a>.</p>
<pre>wget http://pypy.org/download/pypy-1.4.1-osx64.tar.bz2
tar -xjf pypy-1.4.1-osx64.tar.bz</pre>
<p>Install Distribute / easy_install command (setuptools fork) in order to install third party libraries.</p>
<pre>cd pypy-1.4.1-osx64
wget http://python-distribute.org/distribute_setup.py
bin/pypy distribute_setup.py</pre>
<p>Install libraries &#8211; <em>easy_install</em> seems to run just fine on PyPy as long as you don&#8217;t try to install Python native extensions</p>
<pre>bin/easy_install plac # command line parser
bin/easy_install iso8601 # date format parser</pre>
<p>Then run your application</p>
<pre>~/code/pypy-1.4.1-osx64/bin/pypy exceptionanalysis.py     -s=2010-01-01T00:00:00 /Users/moo/xxx/log/client1.log</pre>
<p>In my case the application was a simple log analyzer based on Python generators (code will be posted later). It reads a text file and tries to interpret it. The script utilizes only one CPU core and thus is very CPU bound. The speed comparison results are</p>
<ul>
<li>With Python 2.4: Completed in 111.08 seconds</li>
<li>With PyPy: Completed in 30.39 seconds</li>
</ul>
<p><strong>That&#8217;s almost 4x speed-up!</strong></p>
<p>Things did not work with PyPy</p>
<ul>
<li>import multiprocessing &#8211; was not hard dependency, needed to comment out in plac_ext</li>
</ul>
<p>Here is the traceback if anyone can help:</p>
<pre>Traceback (most recent call last):
 File "app_main.py", line 53, in run_toplevel
 File "exceptionanalysis.py", line 20, in &lt;module&gt;
 import plac
 File "/Users/moo/code/pypy-1.4.1-osx64/site-packages/plac-0.8.0-py2.5.egg/plac.py", line 35, in &lt;module&gt;
 from plac_ext import Interpreter, import_main, ReadlineInput, stdout, runp, Monitor
 File "/Users/moo/code/pypy-1.4.1-osx64/site-packages/plac-0.8.0-py2.5.egg/plac_ext.py", line 7, in &lt;module&gt;
 import itertools, traceback, multiprocessing, signal, threading
 File "/Users/moo/code/pypy-1.4.1-osx64/site-packages/multiprocessing-2.6.2.1-py2.5-macosx-10.6-i386.egg/multiprocessing/__init__.py", line 87, in &lt;module&gt;
 import _multiprocessing
 File "/Users/moo/code/pypy-1.4.1-osx64/site-packages/multiprocessing-2.6.2.1-py2.5-macosx-10.6-i386.egg/multiprocessing/_multiprocessing.py", line 7, in &lt;module&gt;
 __bootstrap__()
 File "/Users/moo/code/pypy-1.4.1-osx64/site-packages/multiprocessing-2.6.2.1-py2.5-macosx-10.6-i386.egg/multiprocessing/_multiprocessing.py", line 6, in __bootstrap__
 imp.load_dynamic(__name__,__file__)
AttributeError: 'module' object has no attribute 'load_dynamic'</pre>
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/03/26/run-your-python-application-using-pypy-its-fast/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Fixing a misbehaving terminal after after software interruption (pdb) or messed up output</title>
		<link>http://blog.mfabrik.com/2011/03/23/fixing-a-misbehaving-terminal-after-after-software-interruption-pdb-or-messed-up-output/</link>
		<comments>http://blog.mfabrik.com/2011/03/23/fixing-a-misbehaving-terminal-after-after-software-interruption-pdb-or-messed-up-output/#comments</comments>
		<pubDate>Wed, 23 Mar 2011 13:07:25 +0000</pubDate>
		<dc:creator>Mikko Ohtamaa</dc:creator>
				<category><![CDATA[plone]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[technology]]></category>
		<category><![CDATA[enter key]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[new line]]></category>
		<category><![CDATA[osx]]></category>
		<category><![CDATA[sane]]></category>
		<category><![CDATA[ssty]]></category>
		<category><![CDATA[stops working]]></category>
		<category><![CDATA[terminal]]></category>
		<category><![CDATA[tty]]></category>

		<guid isPermaLink="false">http://blog.mfabrik.com/?p=1147</guid>
		<description><![CDATA[Preface Your terminal on Linux or OSX may end up to a bad state. You cat a binary file to terminal You interrupt pdb or some other application reading lines in a bad way Symptoms New lines don&#8217;t work You cannot see your own typing to terminal Backspace stops working Fix Type command stty sane [...]]]></description>
			<content:encoded><![CDATA[<h2>Preface</h2>
<p>Your terminal on Linux or OSX may end up to a bad state.</p>
<ul>
<li>You cat a binary file to terminal</li>
<li>You interrupt pdb or some other application reading lines in a bad way</li>
</ul>
<h2>Symptoms</h2>
<ul>
<li>New lines don&#8217;t work</li>
<li>You cannot see your own typing to terminal</li>
<li>Backspace stops working</li>
</ul>
<h2>Fix</h2>
<p>Type command</p>
<pre>stty sane</pre>
<p>This may fix some problems without needing to restart the terminal. <a href="http://www.peachpit.com/articles/article.aspx?p=659655&amp;seqNum=13">More info</a>.
<p class="signature">
<a href="http://mfabrik.com/@@zoho-contact-form"><img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/mfabrik-24.png"></a> <a href="http://mfabrik.com/@@zoho-contact-form">Get developers</a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml"><img valign="middle" src="http://www.feedburner.com/fb/images/pub/feed-icon16x16.png" alt="" style="vertical-align:middle;border:0"/></a> <a href="http://feeds.feedburner.com/mFabrikWebAndMobileDevelopment" rel="alternate" type="application/rss+xml">Subscribe mFabrik blog in a reader</a> <a href="http://twitter.com/mfabrik"> <img valign="middle"  src="http://blog.mfabrik.com/wp-content/uploads/twitter-24.png"></a> <a href="http://twitter.com/moo9000">Follow me on Twitter</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.mfabrik.com/2011/03/23/fixing-a-misbehaving-terminal-after-after-software-interruption-pdb-or-messed-up-output/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

