-
Notes
What's new with you?
-
Why My Mac Made My Sansa Clip+ Hang
Yeah well the other day I got me one of those shiny modern MP3 player thingies — namely a Sansa Clip+. Really nice gadget and all but whenever I copied some of my OGGs on it it would hang during the library update.
Long story short after two days of tinkering I found out Mac OS X creates ._somefile files if the file system copied to doesn't support all required attributes. The whole concept is called Apple Double Format and frankly not including an option to turn it off in some way seems totally ridiculous.
Though it seems Apple does indeed know how stupid the concept is since they provide the dot_clean command.
In case your Sansa MP3 player hangs up after putting music on it this hint might save you some pulled out hair.
-
Python: Decorate a Method That Gets Passed the Class Instance
The other day I needed to decorate a method with a decorator class that knows about the owner of the method meaning the instance. This works as expected with function decorators:
def some_decorator(func):
def decorator(self, *args, kwargs):
print 'instance %s of class %s is now decorated whee!' % (
self, self.class
)
return func(*args, kwargs)
return decorator
class SomeClass(object):
@some_decorator
def dostuff(self, foo, bar):
print 'do %s, %s' % (foo, bar)If you need/want to use a class based decorator you have to do this:
class SomeDecorator(object):
def init(self, func):
self.func = func
def call(self, *args, kwargs):
print 'instance %s of class %s this is now decorated whee!' % (
self.obj, self.cls
)
return self.func.call(*args, kwargs)
def get(self, instance, owner):
self.cls = owner
self.obj = instance
return self.call
class SomeClass(object):
@SomeDecorator
def dostuff(self, foo, bar):
print 'do %s, %s' % (foo, bar)Thanks to Ozgur who's post about the topic pointed me in the right direction.
-
Django Template Tag to Shorten URLs Like Google
Need to shorten your URLs like Google does? Something like http://example.com/some/really/long/path/ to http://example.com/.../path/? Here's my simplistic approach:
# -- encoding: utf-8 --
from django import template
from django.utils.html import conditional_escape
from django.utils.safestring import mark_safe
import re
register = template.Library()
@register.filter
def fancyurlize(value, arg):
length = int(arg)
text = value
for char in (u'%', u'?'):
arr = value.split(char)
if len(arr) > 1:
text = arr[0]
if len(text) > length:
arr = re.split(r'(?<!/)/(?!/)', text)
if len(arr) > 2:
text = u'/'.join((arr[0], u'...', arr[-1]))
if len(text) > 0 and text[-1] != u'/':
text = u''.join((text, u'/'))
return_value = u'<a href="%s" target="_blank">%s</a>' % (
conditional_escape(value),
conditional_escape(text),
)
return mark_safe(return_value)
fancyurlize.is_safe = True -
Studi-tools.de Is Online
Just a quick notice that I put studi-tools.de online today. Its a personal project to make the student life in Hof a little easier.
As most of my projects its pony powered and uses the usual apps like South and django-compress.
-
Nice to Know About virtualenvwrapper
Since I'm mostly working on various Django projects I am working with virtualenv/virtualenvwrapper a lot. It allows to encapsulate environments and keep them identical across all servers your app will run on.
The Problem
All this means setting up pretty much the same Python environment over and over again:
- create an environment
- enter environment
- install pip
- install IPython
- install Django
- install psycopg2
- install PIL
- install south
- install sorl-thumbnail
- install django-compress
- install all project specific packages and django apps
Quite tedious after your nth project really.
The Solution
After reading how virtualenv allows bootstrapping environments and as such reducing tedious work I wondered if that can be done with virtualenvwrapper, too. Turns its absolutely possible.
There actually are quite a few hooks in virtualenvwrapper that allow for stuff being run pre- and post- creating/deleting/activating environments. Now my postmkvirtualenv script looks like this:
#!/bin/bash
easy_install pip
pip install ipython
pip install yolk
pip install psycopg2
pip install django
pip install -e hg+http://bitbucket.org/andrewgodwin/south/@stableish#egg=south
pip install pil
pip install -e svn+http://sorl-thumbnail.googlecode.com/svn/trunk/#egg=solr
pip install -e svn+http://django-compress.googlecode.com/svn/trunk/#egg=compressNow whenever I create an environment with mkvirtualenv someproject all my standard Python packages and Django apps get installed automagically. And then I'm able to put something like this in my postactiveate script:
#!/bin/bash
cd /Users/me/Projects/someproject/So whenever I activate my environment with workon someproject I get beamed right into my project dir and can start hacking right away. Nice and easy.
-
Having Been at Tschitschereengreen
Okay so my (ex)boss asked me if I'd like to write a post about his company any my internship there. I said yes and after having moved back home and caught up on sleep a bit I finally feel ready to do so. Here we go.
Who are we talking about anyway?
First let's make it clear what company we are talking about. The official name is Tschitschereengreen - A Brand of the Yoosic Technology GmbH. Couldn't be any easier, right? Well, I had to write it quite a few time during my half-year internship there, so don't get me started.
It's a rather small company in the heart of Dresden with only just a hand-full of peeps working there. That was a big reason to go there in the first place by the way. They make up by using technologies that allow them to be agile and rapid and all that buzzwordy stuff. That includes frameworks like Django (dingdingding) and other open source stuff that Just Works(tm).
And You Did What There?
So what did I actually do during my internship there? Surprisingly I worked. Call me crazy but I'm of the opinion that a internship should be just what its name implies: pretend you're a regular employee and do/learn all the stuff a regular employee would do/learn. Work on a tryout basis pretty much - you get the idea.
Most of my time there I had the chance to endeepen (I know that is no word) my Python/Django skills. Another big reason why I chose Tschitschereengreen right there. Besides hardcore Django coding I also did some HTML/CSS/JavaScript projects and took care of some admin stuff like setting up servers and such. I even had a chance to do a small PHP/Wordpress project. PHP is fun in small doses actually.
Gimme a Resumé Already
Its been great fun. That's the shortest version. If you want a bit more detail: You probably won't get rich there but hey if money is your main concern you probably will have stopped reading after I mentioned the size of the company. But if you're like me then money isn't your main concern. You rather care about working with nice people and learning stuff by being given responsibility.
If you're in search of a nice internship in the IT area or searching for a full-blown job you should consider Tschitschereengreen. And hey you might even gain some bonus points if you mention you read about them on my blog. :)
-
A Howto on Django Syndication
Last week I had to implement a customized RSS feed in Django for the first time. Sounded like a fun project to me until I had a look at the documentation which is… well let's just say it's not as good as the core documentation.
So if anybody runs into the same problems as me here is a simple example on how to do a little customizing of the Django syndication stuff:
from django.contrib.syndication.feeds import Feed
from django.utils.feedgenerator import Rss201rev2Feed
from content.models import SomeModel
# this is our very own custom RSS feed generator class
class FooFeed(Rss201rev2Feed):
# add_root_elements adds xml elements to the root node of the RSS XML.
# In this case we add a 'foo' element to our feed root with a value of
# 'bar'.
def add_root_elements(self, handler):
super(FooFeed, self).add_root_elements(handler)
handler.addQuickElement(u'foo', 'bar')
# add_item_elements adds elements to the actual items in the RSS XML.
# In this case we add a 'foz' element with an attribute 'baz'. The values
# for those two keys are coming out of the passed in item dict.
def add_item_elements(self, handler, item):
super(FooFeed, self).add_item_elements(handler, item)
handler.addQuickElement(u'foz', item['foz'], attrs={'baz': item['baz']})
# this is our actual feed class that provides data for the RSS feed
class JobPostingFeed(Feed):
# this will use our custom RSS feed generator class from above
feed_type = FooFeed
title = 'FooFeed stuff'
link = '/'
description = 'Freaky FooFeed stuff.'
# this definies which objects are passed into the feed generator
def items(self):
return SomeModel.objects.order_by('-created_at')
# This took me the most time to figure out even though the idea is pretty
# simple. We used the item dictionary in add_item_elements above which is
# filled with the values we define here. Since we are accessing the keys
# 'foz' and 'baz' above we have to make sure those kyes/values actually
# exist in the 'item' dict.
def item_extra_kwargs(self, obj):
return {
'foz': obj.some_method(),
'baz': obj.some_attribute,
}Update: Fixed add_item_elements. Thanks for pointing it out John.
-
The Difference Between Work And Play
The other day I was wondering what the difference is between work and the screwing around I do at home for fun. After putting quite some thought into it and coming up with the typical explanations like not getting paid, being able to choose what you want to do and stuff it struck me: There are no deadlines for stuff.
Example: A colleague of mine was to configure a server to do some port forwarding to a virtual machine a few days ago. Since I usually don't get to do much administrating these days and am always keen to learn new things I kinda hijacked the project and tried to get it to work with him. We couldn't figure it out and after a few minutes he said: "Well this was the hour scheduled for it. Let's see if we can back to it Monday."
That's something I pretty much never do when I'm doing projects for myself: quit. Usually I just keep on poking and prodding the problem till it gives up and goes away. I would even go so far and call it one of my greatest strengths.
-
Nginx is Even Better Than I Thought
So for quite a few months I was pretty sure having HTTPS on multiple domains with the same IP was a no-go on nginx. I was wrong.
If you have a OpenSSL version >= 0.9.8f with SNI support compiled in and a half-way recent nginx version you are good to go. Just set up as many virtual domains as needed.
Quick example from memory (I'm quite positive it is correct though):
server {
server_name somedomain.example.com;
listen 443;
keepalive_timeout 70;
ssl on;
ssl_protocols SSLv3;
ssl_certificate /some/file.pem;
ssl_certificate_key /some/file.key;
}
server {
server_name someotherdomain.example.com;
listen 443;
keepalive_timeout 70;
ssl on;
ssl_protocols SSLv3;
ssl_certificate /some/other/file.pem;
ssl_certificate_key /some/other/file.key;
}
server {
server_name evenotherdomain.example.com;
}Keep in mind though, that enabling SSL in any way leads to a kind of catch-all situation. Meaning if you access https://evenotherdomain.exmaple.com you will most likely end up on one of your SSL-enabled domains (domedomain.example.com or someotherdomain.example.com).
Here is what I did to prevent that:
server {
listen 443;
server_name evenotherdomain.example.com;
rewrite ^(.*) http://example.com$1 permanent;
} -
Clear Up Gelato CMS' Gibberish
My search for a nice and easy tumble blog I can host myself lead me in a pretty straight line to Gelato CMS. But when I looked into the database after I had been playing around with it a bit I saw that all umlauts (äöü for you non-umlaut knowing ignoramus people) turned to garbage.
After I had tried to change the database collation a few times (gotta love MySQL for having like a bangzillion of encodings) I struck me that Gelato probably just didn't talk UTF8 to the database. A few minutes of code review later (heck who writes code in Spanish or Italian or whatever that is? and encodes it in latin?!) I came up with a minimal patch that makes Gelato speak proper UTF8.
In the file gelato/classes/mysql_conenction.class.php search for the function conectar and change the return lines (around line 64) to this:
<?php
mysql_query("SET NAMES utf8;", $this->mid_conexion);
return $this->mid_conexion;
?>