<?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>Ben Jao Ming &#187; Python</title>
	<atom:link href="http://overtag.dk/wordpress/category/computers/python-computers/feed/" rel="self" type="application/rss+xml" />
	<link>http://overtag.dk/wordpress</link>
	<description>101% objective... always</description>
	<lastBuildDate>Thu, 02 Feb 2012 12:29:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Automating stopforumspam.com ASAP (updated!)</title>
		<link>http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com-updated/</link>
		<comments>http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com-updated/#comments</comments>
		<pubDate>Sat, 17 Sep 2011 19:06:41 +0000</pubDate>
		<dc:creator>benjamin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Web]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[spam]]></category>
		<category><![CDATA[stopforumspam.com]]></category>

		<guid isPermaLink="false">http://overtag.dk/wordpress/?p=254</guid>
		<description><![CDATA[In case you need a quick way of getting rid of spammers on your apache server, use this method as a temporary solution until you find a better one. Please take not that it will evaluate EVERY SINGLE REQUEST through &#8230; <a href="http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com-updated/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>In case you need a quick way of getting rid of spammers on your apache server, use this method as a temporary solution until you find a better one.</p>
<p>Please take not that it will evaluate EVERY SINGLE REQUEST through a Deny policy in Apache&#8217;s mod_access &#8211; it does not halt your performance much if you&#8217;re just running a site with few requests. But I only suggest this solution as a temporary one until you have a better integration. I am currently working on a Django middleware that will only check the client&#8217;s IP address in case it is a POST request directed at a certain URL.</p>
<p>Since I&#8217;ve been told that Apache doesn&#8217;t use /etc/hosts.deny, you should probably use this method instead, unless you have a webserver that actually uses hosts.deny. Another method would be to add the IP addresses to iptables, if you&#8217;re running that &#8212; this is probably more efficient than using Apache configuration policies.</p>
<p>This method creates a file that you can include in httpd.conf (to cover ALL your virtual hosts). The overall goal is to avoid .htaccess files since they are evaluated at runtime. Thus, you won&#8217;t have to configure each site, and you save a but of CPU time.</p>
<ol>
<li>Copy the script below to a file on your server, eg. <strong>/usr/sbin/stopforumspam.py</strong>. You might want to read it quickly as it will pretty much explain itself&#8230;</li>
<li>Make the file executable, eg. <strong>chmod +x /usr/sbin/stopforumspam.py</strong></li>
<li>Add it to your crontab for automatic execution each night, eg. <strong>crontab -e</strong> and then insert the line <strong>0 0 * * * /usr/sbin/stopforumspam.py &amp;&amp; /etc/init.d/apache2 reload </strong></li>
<li>By default, we will ban an entire class C subnet if more than 5 IP addresses are in this space. You can configure this behavior by giving stopforumspam.py a single argument, ie. <strong>/usr/sbin/stopforumspam.py 10</strong> would mean that at least 10 IPs have to be within the class C subnet to qualify it for a ban.</li>
<li>By default stopforumspam.py creates <strong>/etc/apache2/stopforumspam.conf</strong> &#8211; you can change this by editing the script.</li>
<li>Add <strong>Include /etc/apache2/stopforumspam.conf</strong> to <strong>/etc/apache2/httpd.conf</strong> (Debian/Ubuntu).</li>
<li><strong style="color: #C00">Caution!</strong> Make sure that you DO NOT change the <strong>Order Deny,Allow</strong> option in VirtualHost directives or .htaccess files as this unblock the deny policies.</li>
</ol>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">zipfile</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> <span style="color: #ff4500;">1</span>:
    SUBNET_THRESHOLD = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">else</span>:
    SUBNET_THRESHOLD = <span style="color: #ff4500;">5</span>
&nbsp;
DOWNLOAD_ZIP = <span style="color: #483d8b;">&quot;http://www.stopforumspam.com/downloads/listed_ip_7.zip&quot;</span>
ZIP_FILENAME = <span style="color: #483d8b;">&quot;listed_ip_7.txt&quot;</span>
&nbsp;
HTTPD_CONFIG_INCLUDE = <span style="color: #483d8b;">&quot;/etc/apache2/stopforumspam.conf&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># For security purposes we test that each line is actually an IP address</span>
IP_MATCH = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;^(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)<span style="color: #000099; font-weight: bold;">\.</span>(<span style="color: #000099; font-weight: bold;">\d</span>+)$&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
filename, headers = <span style="color: #dc143c;">urllib</span>.<span style="color: black;">urlretrieve</span><span style="color: black;">&#40;</span>DOWNLOAD_ZIP<span style="color: black;">&#41;</span>
&nbsp;
z = <span style="color: #dc143c;">zipfile</span>.<span style="color: black;">ZipFile</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>
ips = z.<span style="color: black;">read</span><span style="color: black;">&#40;</span>ZIP_FILENAME<span style="color: black;">&#41;</span>
&nbsp;
ips = ips.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># Remove non-ip members</span>
ips = <span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: #ff7700;font-weight:bold;">lambda</span> ip: IP_MATCH.<span style="color: black;">match</span><span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>, ips<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> get_ip_segments<span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>:
    segments_match = IP_MATCH.<span style="color: black;">search</span><span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: black;">&#91;</span><span style="color: #008000;">int</span><span style="color: black;">&#40;</span>segments_match.<span style="color: black;">group</span><span style="color: black;">&#40;</span>i<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span>,<span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> convert_ip_to_number<span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>:
    numeric_value = <span style="color: #ff4500;">0</span>
    ip_segs = get_ip_segments<span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">for</span> i <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: #008000;">range</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span><span style="color: black;">&#41;</span>:
      numeric_value += ip_segs<span style="color: black;">&#91;</span>i<span style="color: black;">&#93;</span><span style="color: #66cc66;">*</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">255</span><span style="color: #66cc66;">**</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">4</span>-i<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> numeric_value
&nbsp;
<span style="color: #808080; font-style: italic;"># Sort everything first</span>
ips.<span style="color: black;">sort</span><span style="color: black;">&#40;</span>key=convert_ip_to_number<span style="color: black;">&#41;</span>
&nbsp;
subnets = <span style="color: black;">&#123;</span><span style="color: black;">&#125;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> ip <span style="color: #ff7700;font-weight:bold;">in</span> ips:
    ip_segs = get_ip_segments<span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>
    key = <span style="color: black;">&#40;</span>ip_segs<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span>, ip_segs<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, ip_segs<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> key <span style="color: #ff7700;font-weight:bold;">in</span> subnets.<span style="color: black;">keys</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
        subnets<span style="color: black;">&#91;</span>key<span style="color: black;">&#93;</span> = <span style="color: black;">&#91;</span>ip<span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        subnets<span style="color: black;">&#91;</span>key<span style="color: black;">&#93;</span>.<span style="color: black;">append</span><span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>
&nbsp;
final_list = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> subnet, subnet_ips <span style="color: #ff7700;font-weight:bold;">in</span> subnets.<span style="color: black;">items</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>subnet_ips<span style="color: black;">&#41;</span> <span style="color: #66cc66;">&amp;</span>gt<span style="color: #66cc66;">;</span> SUBNET_THRESHOLD:
        <span style="color: #808080; font-style: italic;"># Ban the whole subnet</span>
        final_list.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;.&quot;</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span><span style="color: #008000;">map</span><span style="color: black;">&#40;</span><span style="color: #008000;">str</span>, subnet<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span> + <span style="color: #483d8b;">&quot;.0/24&quot;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        final_list = final_list + subnet_ips
&nbsp;
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;&quot;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Lengh of original list: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>ips<span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Lengh of final list: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span>final_list<span style="color: black;">&#41;</span>
&nbsp;
apache_conf_file = <span style="color: #008000;">file</span><span style="color: black;">&#40;</span>HTTPD_CONFIG_INCLUDE, <span style="color: #483d8b;">&quot;w&quot;</span><span style="color: black;">&#41;</span>
apache_conf_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
apache_conf_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;    Order Deny,Allow<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> entry <span style="color: #ff7700;font-weight:bold;">in</span> final_list:
    apache_conf_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;    Deny from %s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #66cc66;">%</span> entry<span style="color: black;">&#41;</span>
&nbsp;
apache_conf_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
apache_conf_file.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com-updated/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Automating stopforumspam.com</title>
		<link>http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com/</link>
		<comments>http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com/#comments</comments>
		<pubDate>Fri, 16 Sep 2011 22:33:40 +0000</pubDate>
		<dc:creator>benjamin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[Web]]></category>

		<guid isPermaLink="false">http://overtag.dk/wordpress/?p=251</guid>
		<description><![CDATA[THIS DOES NOT WORK WITH APACHE SINCE IT DOES NOT USE /etc/hosts.deny &#8211; See this post instead Use the following Python script to maintain a file in the hosts.deny syntax so that your Debian/Ubuntu box (or other Linux server) is &#8230; <a href="http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong><span style="color: #ff0000;">THIS DOES NOT WORK WITH APACHE SINCE IT DOES NOT USE /etc/hosts.deny<span style="color: #000000;"> &#8211; <a href="http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com-updated/">See this post instead</a></span></span></strong></p>
<p>Use the following Python script to maintain a file in the hosts.deny syntax so that your Debian/Ubuntu box (or other Linux server) is kept undisturbed by forum spammers &#8212; COMPLETELY undisturbed, as the spammer is disallowed all access to the system.</p>
<p>1. Copy the script to a file on your server, eg. <strong>/usr/sbin/stopforumspam.py</strong><br />
2. Make the file executable, eg. <strong>chmod +x /usr/sbin/stopforumspam.py</strong><br />
3. Add it to your crontab for automatic execution each night, eg. <strong>crontab -e</strong> and then insert the line <strong>0 0 * * * /usr/sbin/stopforumspam.py</strong><br />
4. Add the path to the file containing the ip list to /etc/hosts.deny by inserting this line: <strong>ALL: /etc/hosts.deny.stopforumspam</strong></p>
<p>The script itself is here, modify it as you need.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/python</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">re</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urllib</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">zipfile</span>
&nbsp;
DOWNLOAD_ZIP = <span style="color: #483d8b;">&quot;http://www.stopforumspam.com/downloads/listed_ip_7.zip&quot;</span>
ZIP_FILENAME = <span style="color: #483d8b;">&quot;listed_ip_7.txt&quot;</span>
&nbsp;
HOSTS_DENY = <span style="color: #483d8b;">&quot;hosts.deny.stopforumspam&quot;</span>
&nbsp;
<span style="color: #808080; font-style: italic;"># For security purposes we test that each line is actually an IP address</span>
IP_MATCH = <span style="color: #dc143c;">re</span>.<span style="color: #008000;">compile</span><span style="color: black;">&#40;</span>r<span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\d</span>+<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>+<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>+<span style="color: #000099; font-weight: bold;">\.</span><span style="color: #000099; font-weight: bold;">\d</span>+&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
filename, headers = <span style="color: #dc143c;">urllib</span>.<span style="color: black;">urlretrieve</span><span style="color: black;">&#40;</span>DOWNLOAD_ZIP<span style="color: black;">&#41;</span>
&nbsp;
z = <span style="color: #dc143c;">zipfile</span>.<span style="color: black;">ZipFile</span><span style="color: black;">&#40;</span>filename<span style="color: black;">&#41;</span>
ips = z.<span style="color: black;">read</span><span style="color: black;">&#40;</span>ZIP_FILENAME<span style="color: black;">&#41;</span>
&nbsp;
deny_file = <span style="color: #008000;">file</span><span style="color: black;">&#40;</span>HOSTS_DENY, <span style="color: #483d8b;">&quot;w&quot;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">for</span> ip <span style="color: #ff7700;font-weight:bold;">in</span> ips.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> IP_MATCH.<span style="color: black;">match</span><span style="color: black;">&#40;</span>ip<span style="color: black;">&#41;</span>:
        deny_file.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;%s<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span> <span style="color: #66cc66;">%</span> ip<span style="color: black;">&#41;</span>
&nbsp;
deny_file.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

]]></content:encoded>
			<wfw:commentRss>http://overtag.dk/wordpress/2011/09/automating-stopforumspam-com/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Using GtkBuilder and connect_signals</title>
		<link>http://overtag.dk/wordpress/2011/02/using-gtkbuilder-and-connect_signals/</link>
		<comments>http://overtag.dk/wordpress/2011/02/using-gtkbuilder-and-connect_signals/#comments</comments>
		<pubDate>Wed, 23 Feb 2011 00:14:41 +0000</pubDate>
		<dc:creator>benjamin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[connect_signals]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[gtkbuilder]]></category>
		<category><![CDATA[pygtk]]></category>

		<guid isPermaLink="false">http://overtag.dk/wordpress/?p=235</guid>
		<description><![CDATA[I have been hunting spontaneous crashes with errors from the C GTK libs. The errors looked somewhat like these: Warning: g_object_ref: assertion `G_IS_OBJECT (object)' failed gtk.main() Warning: instance of invalid non-instantiatable type `AtkSelection' gtk.main() Warning: g_signal_emit_valist: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed &#8230; <a href="http://overtag.dk/wordpress/2011/02/using-gtkbuilder-and-connect_signals/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>I have been hunting spontaneous crashes with errors from the C GTK libs. The errors looked somewhat like these:</p>

<div class="wp_syntax"><div class="code"><pre class="text" style="font-family:monospace;">Warning: g_object_ref: assertion `G_IS_OBJECT (object)' failed
  gtk.main()
Warning: instance of invalid non-instantiatable type `AtkSelection'
  gtk.main()
Warning: g_signal_emit_valist: assertion `G_TYPE_CHECK_INSTANCE (instance)' failed
  gtk.main()
(...)
Warning: instance of invalid non-instantiatable type `'
  gtk.main()</pre></div></div>

<p>In most versions of GTK window decorators, this caused a crash &#8211; in a few lucky cases, it didn&#8217;t! My (wrong) assumption was that calling <strong>connect_signals</strong> was only of interest, if I actually had signal handlers to connect. This is also the case when looking at the docs. <a title="Go to PyGtk docs" href="http://www.pygtk.org/docs/pygtk/class-gtkbuilder.html#method-gtkbuilder--connect-signals" target="_blank">For instance</a>:</p>
<blockquote><p>The function connect_signals and variants thereof <del datetime="2011-02-22T23:44:27+00:00">can</del> MUST be used to connect handlers to the named signals in the description.</p>
<p>(&#8230;)</p>
<p>For each of handlers that cannot be found, a <code>RuntimeWarning</code> is issued.</p></blockquote>
<p>However, when the warning was issued, GTK would crash anyways. This behavior was most like caused by dereferencing and deleting GTK widgets, which caused GTK to look for an <strong>on_delete_event</strong> handler as some sort of default behavior. Since I have a program that adds and removes GTK widgets during runtime, my program needed to handle these signals, even if the event handler would simply be empty. To make a long story short, you should ALWAYS make sure to call <strong>connect_signals</strong> no matter what, as it will connect core event handlers that you may not be aware of. This is how it should look:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">class</span> YourObject<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">def</span> <span style="color: #0000cd;">__init__</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>:
        glade = add_from_file<span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;x.glade&quot;</span><span style="color: black;">&#41;</span>
        win = glade.<span style="color: black;">get_object</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">&quot;window&quot;</span><span style="color: black;">&#41;</span>
        win.<span style="color: black;">show_all</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># ALWAYS DO THIS:</span>
        glade.<span style="color: black;">connect_signals</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">def</span> on_delete_event<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, <span style="color: #66cc66;">*</span>args<span style="color: black;">&#41;</span>:
        <span style="color: #ff7700;font-weight:bold;">pass</span></pre></div></div>

<p>And even if the above may not fail, here is something that <em>will potentially</em> fail if you don&#8217;t connect the signals. Please beware, that using the same <strong>on_delete_event</strong> handler for two different objects is a bad strategy.</p>
<p>Always take care that widgets are removed and deleted, and that delete events may be invoked at very separate places in your application. You should also be aware that the python garbage collector could be the one initiating these events, causing those strange c library reference errors.</p>
]]></content:encoded>
			<wfw:commentRss>http://overtag.dk/wordpress/2011/02/using-gtkbuilder-and-connect_signals/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Django localized date template filter</title>
		<link>http://overtag.dk/wordpress/2009/07/django-localized-date-template-filter/</link>
		<comments>http://overtag.dk/wordpress/2009/07/django-localized-date-template-filter/#comments</comments>
		<pubDate>Fri, 10 Jul 2009 22:24:13 +0000</pubDate>
		<dc:creator>benjamin</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[template filter]]></category>

		<guid isPermaLink="false">http://overtag.dk/wordpress/?p=155</guid>
		<description><![CDATA[UPDATE! This is going to be redundant in Django 1.2, in which you can add DATE_FORMAT to your django.po files. I&#8217;ve often been frustrated that using settings.DATE_FORMAT does not give a localized date. Granted that the name of a month &#8230; <a href="http://overtag.dk/wordpress/2009/07/django-localized-date-template-filter/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p><strong>UPDATE!</strong> This is going to be redundant in Django 1.2, in which you can add DATE_FORMAT to your django.po files.</p>
<p>I&#8217;ve often been frustrated that using <strong>settings.DATE_FORMAT</strong> does not give a localized date. Granted that the name of a month may be localized, but the format string does not change. So let&#8217;s start out by modifying <strong>settings.py</strong>. We wrap our default date format in a <b>ugettext</b> so the makemessages command will detect it, and we need to make it a dummy function, because the i18n library cannot be imported in settings.py due to circularity (it depends on settings.py).</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;">ugettext = <span style="color: #ff7700;font-weight:bold;">lambda</span> s: s
DATE_FORMAT = ugettext<span style="color: black;">&#40;</span><span style="color: #483d8b;">'N j, Y'</span><span style="color: black;">&#41;</span></pre></div></div>

<p>Run compilemessages and type in your localized date formats. Now we need a template filter that uses a localized format for calling the Django date format function. This is really simple:</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">template</span>.<span style="color: black;">defaultfilters</span> <span style="color: #ff7700;font-weight:bold;">import</span> stringfilter
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span> <span style="color: #ff7700;font-weight:bold;">import</span> dateformat
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">utils</span>.<span style="color: black;">translation</span> <span style="color: #ff7700;font-weight:bold;">import</span> ugettext
<span style="color: #ff7700;font-weight:bold;">from</span> django.<span style="color: black;">conf</span> <span style="color: #ff7700;font-weight:bold;">import</span> settings
&nbsp;
@register.<span style="color: #008000;">filter</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">def</span> localdate<span style="color: black;">&#40;</span>value<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Format date with localized date format&quot;&quot;&quot;</span>
    format = ugettext<span style="color: black;">&#40;</span>settings.<span style="color: black;">DATE_FORMAT</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> dateformat.<span style="color: black;">format</span><span style="color: black;">&#40;</span>value, format<span style="color: black;">&#41;</span></pre></div></div>

<p>And done. Using the filter is straight forward:</p>
<p><code><br />
Date: {{ my_date|localdate }}<br />
</code></p>
]]></content:encoded>
			<wfw:commentRss>http://overtag.dk/wordpress/2009/07/django-localized-date-template-filter/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Presenting: django-simple-wiki</title>
		<link>http://overtag.dk/wordpress/2009/04/presenting-django-simple-wiki/</link>
		<comments>http://overtag.dk/wordpress/2009/04/presenting-django-simple-wiki/#comments</comments>
		<pubDate>Sun, 26 Apr 2009 23:52:57 +0000</pubDate>
		<dc:creator>benjamin</dc:creator>
				<category><![CDATA[Django]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[django application]]></category>
		<category><![CDATA[django-simple-wiki]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[wiki]]></category>

		<guid isPermaLink="false">http://overtag.dk/wordpress/?p=142</guid>
		<description><![CDATA[It was bothering me that all the wikis I tried, all had either errors, feature lacks, too many dependencies or were simply unmaintained. So I decided to create yet another one. Curiously, the third hit when googling &#8216;django wiki&#8217; is &#8230; <a href="http://overtag.dk/wordpress/2009/04/presenting-django-simple-wiki/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>It was bothering me that all the wikis I tried, all had either errors, feature lacks, too many dependencies or were simply unmaintained. So I decided to create yet another one. Curiously, the third hit when googling &#8216;django wiki&#8217; is <a href="http://showmedo.com/videotutorials/video?name=1100000">Create a wiki in 20 minutes</a>. Luckily that&#8217;s not really true, so all the PHP guys and MediaWiki can continue breathing. This took me several days.</p>
<blockquote style="font-size: 150%;"><p><strong><a href="http://code.google.com/p/django-simple-wiki/">Google Code project page</a></strong></p></blockquote>
<blockquote style="font-size: 150%;"><p><strong><a href="http://wikidemo.overtag.dk/">Demo website</a></strong></p></blockquote>
<p><strong>Hierarchy and relations</strong><br />
First of all, as in the Trac wiki system, I chose to create a system for hierarchy, meaning that it&#8217;s possible to create an article and then create sub-articles. The hierarchy does not support multiple inheritance, because it needs to be basis for the permission system. That&#8217;s where the relation system comes in place: All articles can contain symmetrical relations to any other articles in the hierarchy.</p>
<p><strong>Parsing</strong><br />
Python and Django supports Markdown pretty much out of the box, so it&#8217;s an obvious choice to use this for parsing. The HTML features of normal Markdown have been removed, so all HTML is escaped in django-simple-wiki. And parsing is static, so every time a revision is created, the contents are passed and stored. This means that the contents of the article itself are not supposed to be dynamic. On the other hand, it is desirable to avoid parsing contents for every page hit. The parsing area of the application is only a few lines of code, and can be expanded if further parsing needs to be done, or someone wants to replace Markdown completely. For instance, if no parsing is done and HTML escaping is disabled, the wiki becomes a very simple CMS.</p>
<p><strong>Curious issues</strong><br />
There are a few out standing problems:</p>
<ul>
<li>Permission system is related to User entries in the Django auth system. But maybe this is too much of an annoyance, if the project already has groups setup in the existing auth system. On the other hand, other users would be bothered to setup both wiki groups and user groups, if the permission system was linked to user groups. And directly linking articles to user groups would require wiki-related groups to be created directly in the auth system.</li>
<li>Since relations are symmetrical, what should happen if one article is locked, but a user modifies it&#8217;s relations by deleting them from related articles?</li>
<li>Title editing: The title can only be created once, since it is coupled to the &#8216;slug&#8217; of the article. A user can deliberately create a completely different title, which is fine, but should subsequent editing be allowed, which would add complexity to the revision system?</li>
<li>Article deletion: When an article is deleted from the backend it shouldn&#8217;t worry anyone. But if the feature is added to the frontend, we would want to handle maliciousness etc. But should we really store all these files and revisions? Should we alert admins, so they can do the final cleanup?</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://overtag.dk/wordpress/2009/04/presenting-django-simple-wiki/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>GTK and scrolling without scrollbars</title>
		<link>http://overtag.dk/wordpress/2009/01/gtk-and-scrolling-without-scrollbars/</link>
		<comments>http://overtag.dk/wordpress/2009/01/gtk-and-scrolling-without-scrollbars/#comments</comments>
		<pubDate>Tue, 27 Jan 2009 19:09:39 +0000</pubDate>
		<dc:creator>benjamin</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[full screen]]></category>
		<category><![CDATA[gtk]]></category>
		<category><![CDATA[gtk.Layout]]></category>
		<category><![CDATA[python]]></category>
		<category><![CDATA[rhythmbox]]></category>
		<category><![CDATA[scrolling]]></category>

		<guid isPermaLink="false">http://overtag.dk/wordpress/?p=114</guid>
		<description><![CDATA[There&#8217;s still some work to do on the full screen plugin for Rhythmbox, but the current version is very usable indeed. The latest addition is scrolling by hovering the track list. I changed the display from a normal fixed table &#8230; <a href="http://overtag.dk/wordpress/2009/01/gtk-and-scrolling-without-scrollbars/">Continue reading <span class="meta-nav">&#8594;</span></a>]]></description>
			<content:encoded><![CDATA[<p>There&#8217;s still some work to do on the full screen plugin for Rhythmbox, but the current version is very usable indeed. The latest addition is scrolling by hovering the track list.</p>
<p>I changed the display from a normal fixed table with 3 tracks to a <strong>gtk.Layout</strong> with a <strong>gtk.VBox</strong> containing <em>n</em> tracks. In a Layout widget it&#8217;s possible to freely place and move child widgets, so by detecting motion events on the edges of the Layout you can emulate scrolling by moving a child widget accordingly with <strong>Layout.move(widget, x, y)</strong>. Unfortunately I get a rather nasty blinking effect when scrolling too fast, and I don&#8217;t have an explanation for this, so I&#8217;d be glad to hear from anyone who can help.</p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #ff7700;font-weight:bold;">def</span> track_layout_scroll<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, widget, event<span style="color: black;">&#41;</span>:
    time_step = <span style="color: #ff4500;">10</span> <span style="color: #808080; font-style: italic;">#msecs</span>
    ycoord = event.<span style="color: black;">y</span>
    accel_factor = <span style="color: #ff4500;">10</span> <span style="color: #808080; font-style: italic;">#how many pixels to scroll at the edge</span>
    edge_distance = <span style="color: #ff4500;">100.0</span> <span style="color: #808080; font-style: italic;">#pixels</span>
    layout_size = widget.<span style="color: black;">get_size</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    top_dist = edge_distance - ycoord
    bot_dist = edge_distance - layout_size<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span> + ycoord
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> top_dist <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>:
        accel = -<span style="color: #ff4500;">1</span> - <span style="color: black;">&#40;</span>top_dist / edge_distance<span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> accel_factor
    <span style="color: #ff7700;font-weight:bold;">elif</span> bot_dist <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span>:
        accel =  <span style="color: #ff4500;">1</span> + <span style="color: black;">&#40;</span>bot_dist / edge_distance<span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> accel_factor
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        accel = <span style="color: #ff4500;">0.0</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">scroll_event_id</span>:
        gobject.<span style="color: black;">source_remove</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">scroll_event_id</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> accel == <span style="color: #ff4500;">0.0</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">scroll_event_id</span> = gobject.<span style="color: black;">timeout_add</span><span style="color: black;">&#40;</span>time_step, <span style="color: #008000;">self</span>.<span style="color: black;">do_scrolling</span>, accel, widget<span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> do_scrolling<span style="color: black;">&#40;</span><span style="color: #008000;">self</span>, accel, layout_widget<span style="color: black;">&#41;</span>:
    step = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">1</span><span style="color: #66cc66;">*</span>accel<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> step == <span style="color: #ff4500;">0</span>:
        <span style="color: #ff7700;font-weight:bold;">return</span>
    vbox_size = <span style="color: #008000;">self</span>.<span style="color: black;">vbox</span>.<span style="color: black;">size_request</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    layout_size = layout_widget.<span style="color: black;">get_size</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    scroll_height = vbox_size<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>-layout_size<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span> + step <span style="color: #66cc66;">&lt;</span> <span style="color: #ff4500;">0</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span> = <span style="color: #ff4500;">0</span>
    <span style="color: #ff7700;font-weight:bold;">elif</span> <span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span> + step <span style="color: #66cc66;">&gt;</span> scroll_height:
        <span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span> = scroll_height
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        <span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span> += step
&nbsp;
    <span style="color: #008000;">self</span>.<span style="color: black;">track_layout</span>.<span style="color: black;">move</span><span style="color: black;">&#40;</span><span style="color: #008000;">self</span>.<span style="color: black;">vbox</span>, <span style="color: #ff4500;">0</span>, -<span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> <span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">0</span> <span style="color: #ff7700;font-weight:bold;">and</span> <span style="color: #008000;">self</span>.<span style="color: black;">scroll_y</span> <span style="color: #66cc66;">&lt;</span> scroll_height</pre></div></div>

<p>The code is related to my Rhythmbox plugin, but I&#8217;m sure you get the idea. Also please note, that track_layout_scroll has to receive notify_motion_event from the Layout widget, and that you have to set a size for the Layout widget with set_size().</p>
<p><strong>Update:</strong> By playing around with time_step (lowering it to be more exact) and slowing down the acceleration, I managed to almost make the white flashes disappear.</p>
]]></content:encoded>
			<wfw:commentRss>http://overtag.dk/wordpress/2009/01/gtk-and-scrolling-without-scrollbars/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

