Unkillable zombie blog

This blog just won't die

Feb 21, 2008

Resolver is a great idea.

I was reading about Resolver quite often, mostly on planet python. I had made a mental memo to try it out for my self sometime but always seemed to be delaying it. I tried it out yesterday i was really impressed by the concept. 

With Resolver you have a spreadsheet with tightly integrated python programmability. The window has 3 panes. The ‘spreadsheet’ pane, the Python editor, and the ‘output’ pane. You can define any python function you like and make it available for use in your spreadsheet. This means you can do database connectivity using python, or advanced data manipulation that is either no possible with Excel, or very difficult.  I can’t tell you how many times i wished i could do that easily with Excel. In fact, i very often needed to pull data from the database of a Django project and do some manipulation using Excel , and present it to some users. But i wanted to use the Django ORM instead of raw SQL. With Resolver it should be very easy.

At least for me, it was often the case that i needed to solve a problem that was too complex for Excel, and too simple for writing a full-blown application. I needed something that would combine the best of both worlds.

Resolver is written in IronPython and uses Python for programming.  It might be possible to run it using mono but i haven’t tried anything of the sort. Ironpython supposedly runs on linux , but mono has an incomplete Forms implmementation.

Best of all, it free for non-commercial use, so you need to try it out.

Click to read and post comments

Feb 06, 2008

IBAN validating code

Recently i needed to validate some IBAN numbers (International Bank Account Number). I quick search revealed the wikipedia article on the subject.

Though i had initially hacked up a Greek-only IBAN validator i though it might be of use to other people as well and modified it to validate  every possible IBAN (as long as the wikipedia article is complete).

 

So here it is:

 

#!/usr/bin/python
# -*- coding: utf-8

# iban.py
# http://kill9.eu/
#
# Copyright (C) 2008 Konstantinos Metaxas 
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published
# by the Free Software Foundation; version 2 only.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

import string

class IBAN(object):

    def __init__(self,iban):
        """Represents an IBAN number.
        iban must be supplied as a string"""
        self.iban = iban.strip().upper()
        #List retrieved from http://en.wikipedia.org/wiki/IBAN
        self.error_list = []
        self.country_length_table = {
                'AD':('Andora',24),
                'AT':('Austria',20),
                'BE':('Belgium',16),
                'BA':('Bosnia and Hetzegovina',20),
                'BG':('Bulgaria',22),
                'HR':('Croatia',21),
                'CY':('Cyprus',28),
                'CZ':('Czech Republic',24),
                'DK':('Denmark',18),
                'EE':('Estonia',20),
                'FO':('Faroe Islands',18),
                'FI':('Finland',18),
                'FR':('France',27),
                'DE':('Germany',22),
                'GI':('Gibraltar',23),
                'GR':('Greece',27),
                'GL':('Greenland',18),
                'HU':('Hungary',28),
                'IS':('Iceland',26),
                'IE':('Republic of Ireland',22),
                'IL':('Israel',23),
                'IT':('Italy',27),
                'LV':('Latvia',21),
                'LI':('Liechtenstein',21),
                'LT':('Lithuania',20),
                'LU':('Luxembourg',20),
                'MK':('FYROM',19),
                'MT':('Malta',31),
                'MC':('Monaco',27),
                'ME':('Montenegro',22),
                'MA':('Morocco',24),
                'NL':('Netherlands',18),
                'NO':('Norway',15),
                'PL':('Poland',28),
                'PT':('Portugal',25),
                'RO':('Romania',24),
                'SM':('San Marino',27),
                'RS':('Serbia',22),
                'SK':('Slovakia',24),
                'SI':('Slovenia',19),
                'ES':('Spain',24),
                'SE':('Sweden',24),
                'CH':('Switzerland',21),
                'TR':('Turkey',26),
                'TN':('Tunisia',24),
                'GB':('United Kingdom',22),

                }

    def is_valid(self):
        """checks if it is a valid IBAN"""

        if not self._is_valid_for_countrycode():
            return False
        if not self._swift_check():
            return False
        return True

    def _is_valid_for_countrycode(self):
        code = self.iban[:2]
        try:
            max_length = self.country_length_table[code][1]
        except KeyError:
            return False
        if len(self.iban) != max_length:
            return False
        else:
            return True

    def _swift_check(self):
        """
        http://en.wikipedia.org/wiki/IBAN
        """
        head_to_tail_iban = self.iban[4:] + self.iban[:4]
        numerical_ascii_map = dict( zip(string.ascii_uppercase,range(10,36)) )

        translated_iban = ""
        for c in head_to_tail_iban:
            if c in numerical_ascii_map:
                translated_iban += str(numerical_ascii_map[c])
            else:
                translated_iban += c

        try:
            integer_iban = int(translated_iban)
        except ValueError:
            return False

        modulo = integer_iban % 97

        if modulo == 1:
            return True
        else:
            return False

Using it as as simple as:

 

Python 2.5.1 (r251:54863, Oct 14 2007, 19:24:49)
[GCC 4.2.2 (Gentoo 4.2.2 p1.0)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import iban
>>> myIBAN = iban.IBAN('GRXXXXXXXXXXXXXXXXXX') # Actual IBAN omitted for privacy reasons
>>> myIBAN.is_valid()
True

 

It should be easy to make it into a custom Django Form Field , and i might post the relevant code later.

posted at 17:53  ·   ·  python
Click to read and post comments

Feb 06, 2008

XML feed με το πρόγραμμα των ελληνικών καναλιών

Γιατί τα ελληνικά κανάλια στα site τους δεν παρέχουν XML feeds με το πρόγραμμά τους?

Δεν είναι κρυφή πληροφορία, και θα ήταν πολύ χρήσιμο σε projects όπως το mythtv, αλλα και σε όσους θα ήθελαν να αυτοματοποιήσουν κάποιο σύστημα βασισμένοι στην πληροφορία αυτή.

Είναι μια απλή παράλειψη ή υπάρχει κάποιος άλλη εξήγηση?

posted at 00:21  ·   ·  greek
Click to read and post comments

Oct 07, 2007

Displaying a message after a POST/Redirect/GET

I use the POST/Redirect/GET (RPG) pattern to avoid multiple submission problems. Sometimes however i want the GET part to display a message related to the POST part. Eg, “Your change has been done. Thank you” without creating special view just for this.
I found the solution to this problem in the www.djangosnippets.org site. It’s snippet no 319 titled “Flash Message Template Tag”.
What it does is use sessions and a special template tag to display a message in the template and immediately delete it from the session. After you set it up, all you have to do is something like this:

request.session['flash_msg'] = 'Your FOO has been BARed'
request.session['flash_params'] = {'type': 'success'}

Thanks Robert Conner!

posted at 23:37  ·   ·  django
Click to read and post comments

Sep 29, 2007

Even my sister can hack Altec telecoms

A few days ago, my sister’s boyfriend, who is currently in the army in some far away island, wanted to change the DNS settings on his domain, because his hosting provider changed DNS servers. Not being very knowledgable in these things he had given the registrar a contact email on his domain, which meant he couldn’t get the verification-code he needed to login and do the changes.

He called my sister and told her to fax them , telling them to change the contact email address on his domain. My sister popped-up MS Word and wrote a letter without contact details, just the company name, and asked them to do the changes. Sure enough they sent an email with the verification-code …. for a different company. Apparently anyone can send any piece of paper, no matter how awful, asking them for the verification code of any domain, and the automatons over at Altec Telecoms will happily oblige.

Besides the obvious security issue, i must comment on their service level. My sister would keep contacting them for two days, being given from representative to representative to technical staff, to sales staff, to the janitor and ‘whoever-would-be-walking-besides-a-ringing-telephone’. At some point she got mad and asked the lady she was speaking with about her name. The lady, which identified heslef as ‘Papadopoulou’ told my sister to ‘fuck off’ while hunging up. Probably though my sister had not head me. Upon hearing this i tried to call them and complain to some supervisor, but i was put on hold for more than five minutes (their way of telling me…. ‘fuck off, too’ i guess) and i hang up.

I wish i could say that Altec Telecoms is alone in being such a horrible pain to deal with, but my own ISP, Forthnet, has been just a evil…

Click to read and post comments

Aug 17, 2007

Captcha widgets in Django

This blog was getting stormed by comment spam so i decided to use some captcha protection. I chose pycaptcha for this and had to integrate it nicely with Django. I wanted to make it an easy widget that does it’s own validation and does not require view code for validating the captcha. So here is what i came up with:

EDIT: Updated for SVN trunk version of Django ( value_from_datadict has an extra parameter)

First, the custom form field:


class CaptchaField(CharField):
widget = CaptchaWidget
def __init__(self, *args, **kwargs):
super(CaptchaField, self).__init__(*args, **kwargs)


def clean(self,values):
value,captchaid = values
#Check if the value matches that in the session
factory = PersistentFactory('/tmp/captcha_persistence')
test = factory.get(str(captchaid))
factory.storedInstances.close()
if (not test) or (not test.valid):
raise ValidationError(u"""Captcha does not exist or is
invalid. Please refresh to get new captcha""")
if not test.testSolutions([value.strip()]):
raise ValidationError(u"""You did not type the correct
captcha text""")
return ""

The Widget used by this form field:


class CaptchaWidget(Input):
input_type = "text"
def render(self,name,value,attrs=None):
#Always generate a new captcha on rendering
factory = PersistentFactory('/tmp/captcha_persistence')
test = factory.new(Tests.PseudoGimpy)
factory.storedInstances.close()
captchaid = test.id
superclass_output = super(CaptchaWidget,self).render(name,"",attrs)
output = """<img src="/captcha/%s" border="0"/><br/>
<input type="hidden" name="captchaid" value="%s" />
%s
""" %(captchaid,captchaid,superclass_output)
return output

def value_from_datadict(self,data,files,name):
return [ data[name],data['captchaid'] ]


We also need a view to deliver the image for the captcha so here it is:

def captcha_image(request,id):

factory = PersistentFactory('/tmp/captcha_persistence')
test = factory.get(str(id))
factory.storedInstances.close()
if not test:
return HttpResponseNotFound()

response = HttpResponse(mimetype='image/jpeg')
test.render().save(response,'JPEG')
return response


Dont forget to add a urls.py entry for our view. something like:

(r'^captcha/(?P<id>\w+)','blogon.blog.views.captcha_image'),

should be enough (change the view to your view. If you change the url then be sure to change it in the html generated by the widget.

. Notice that in our code we use a file in /tmp for writing the persistence of pycaptcha. This may be a security problem depending on our environment. So be careful, or us a trusted location.
I should use a template for the HTML generated by the widget so as to make it more easily customizable but i just got bored after i got it working.

Click to read and post comments

Jul 14, 2007

Making my Sony Handycam HDR-UX3 work with linux (almost)

I was recently given a Sony Handycam HDR-UX3 video camera as a present (yea!). This camera can record at in HD format ( 1080i ) and records straight to DVD. It’s a very new camera and not much info about making it work under linux, so here what i can up with.
First, reading the MemoryStick Duo that contains any images is straightforward. Just plug the USB cable, select the memory stick from the LCD and you get a new device that you can mount as usual.
I have not tested HD video. Just SD video using a DVD-VR disk. Again, plug in the USB cable, choose the dvd icon on your camera’s LCD and you get a new /dev/sr* device. (eg. i got /dev/sr1 sicne i already had a /dev/sr0). This can be mounted as a normal file system (i believe it’s UDF 2.0 so your kernel must support it, which it should).
Now, the tricky part is extracting the video. The only program i could find that does this is here . Just download, untar and compile (typing ‘make’ should be enough.)
Assuming you have mounted the camera at /mnt/mycamera you simply type:
/dvd-vr VR_MANGR.IFO VR_MOVIE.VRO
to extract the .vob files. Eg in my case:
./dvd-vr /mnt/mycamera/DVD_RTAV/VR_MANGR.IFO /mnt/mycamera/DVD_RTAV/VR_MOVIE.VRO
And that’s it!
It seems that if you are using 16:9 recording the ratio is not right, but i chose ‘anamorphic’ format under xine which fixed it.
It’s rather simple, and easy to use. You can even eject the disc by typing:
eject /dev/sr1
 Enjoy.
Click to read and post comments

Jul 11, 2007

doesn’t pownce.com support unicode properly?

I was invited to pownce.com today. It’s a hot new Web 2.0 messaging applications that is also developed by a really hot developer in a hot language using a hot framework.
It’s still in BETA and the new accounts are invite only. I suspect that most people have accounts and the whole ‘invite’ thing is a way to make it sound cool. After all, upon registration you get 6 invites automatically. It’s not like they are controlling how fast they grow like google did by giving invites using their own criteria to control growth.
Being in BETA it means there are bugs, and features missing. It seems that one particular bug is rather significant. My Greek friends tried to send messages in Greek (in unicode encoding) and all they got was question marks. Not being able to communicate in my native language is a major bug. I am also a little curious as to why this is happening. Django and Python have excellent unicode support, Mysql (horrible as it may be) has unicode support, so what gives?
Click to read and post comments

Jun 26, 2007

Lambda Lives!

It seems that Guido Van Rossum has decided to keep lamda for Python 3000 (or as it will be called when release.. Python 3.0.
I can’t say i like all of the proposed changes. It starts to feel more and more like Java, though that may not be necessarily a bad thing.
It’s backwards incompatibly in a significant way, so don’t expect major applications to be ported right away (or at all!)
posted at 00:19  ·   ·  python
Click to read and post comments

Jun 17, 2007

Validating Greek VAT code (έλεγχος Α.Φ.Μ)

I recently had to validate the VAT code entered in an internetl Django application. Searching around lead me to this site. The implementation there is Visual Basic though, which wouldn’t suit me. So i translated it to Python as best as i could (given i don’t actually know any VB :p )
Here it is:
def isValidAFM(afm):
    if len(afm) != 9:
        return False

    try:
        int(afm)
    except ValueError:
        return False

    AFMpart = afm[:-1]
    afmsum = 0
    multiplier = 2
    for c in AFMpart[::-1]:

        afmsum += ( int(c) * multiplier )
        multiplier *= 2

    if not afmsum:
        return False

    afmmod = afmsum % 11

    lastdigit = int(afm[-1])
    if lastdigit == afmmod:
        return True
    elif (lastdigit == 0) and (afmmod ==10 ):
        return True
    else:
        return False

Caveats:
  • I don’t know if the actual algorithm is valid since my search for official documentation turned up nothing. It seems to be accepted by a large on-line community of accountants though, and that’s good enough for me.
  • I have not tested it much. You at your own risk, as always
posted at 13:54  ·   ·  python
Click to read and post comments
← Previous Next → Page 5 of 6