From bit to a heart beat

insane innovations from a sane insanity

Sun Jan 17

Activerecord in Python: Do it like Rails!

I’ve searched around the net for a nice, clean implementation of activerecord in Python but I found none. There are many better libraries for database abstraction out there in Python but I think that Rails’ “activerecord” way is a breeze and a fun way to access a database.

So, my weekend project was to see whether I could hack together a small activerecord for Python.

The first thing I reeeeaally wanted to do, is to create dynamic queries. What dynamic queries are you ask.

Let’s say you have a database and a table with some fruits fields.

Table: People

Fields: id, name, sex

Using ActiveRecord you can do this:

user = People.find_by_name(“Robert”)

and you’ll get all the People with the name Robert. The magic thing is that you haven’t defined anywhere the function find_by_name. Activerecord has only the function find_by and depending on your search it creates automatically a new function called find_by_name (if the ‘name’ field exists on your table). This is all thanks to Ruby’s method_missing function.

Ruby’s method_missing is called automatically from ruby’s VM everytime a function you tried to call was not found. So, when you called find_by_name, ruby couldn’t find the function and after all the search it went to method_missing. From there, activerecord took control and done it’s magic.

That are many different ways to do it in Python but only one comes close to Rails’ implementation.

Behold: __getattr__

Everytime you call a class attribute, this function is called. So, in Python:

user = User.find_by_name(“Robert”)

calls __getatr__ and if the attribute does not exist, it throws an ‘AttributeError’ exception. That’s the place we are going to put our code and create the dynamic queries.

The most difficult part was this: The function __getattr__ gets one parameter (the attribute) so in this example it was the find_by_name. I had to find a way to pass to __getattr__ the query’s argument.

Behold: Lambda

I know a hobby project of mine is awesome when I have to use lambda (old habits from C and Lisp). Using

lambda value: do_smth(value),

you open up the way for another parameter to join the game (hint: value). So, we have this:

dynamic_query = {

“find_by_”: lambda value: self._find(field, value)

}[query]

This is a dictionary emulating a switch/case in Python with lambdas. If you want to add more functions (insert,update) or more logic (find_by_name_and_sex), this is the place to hack.

Check it online at my bitbucket account and push your changes.

Comments (View)
Wed Jan 6

Nimbuzz, Android and Skype: Put your headphones on!

I love Nimbuzz (loving it since I first learn about it when I was at the Erlang Factory in London and spoke with a guy from Nimbuzz) ‘cause it was running smoothly on my Symbian and allowing me to connect with Skype. So when I got my HTC Hero, it was the first app I was going to install. But Skype(to Skype) didn’t seem to work (couldn’t speak, couldn’t hear).

I tried Fring where everything seemed to be working smoothly and I noticed that a headphones icon was appering on my notification bar eventhough I had no headphones connected. So, I connected my slick HTC Hero headphones, fired up Nimbuzz and tadaaaa!

Maybe this solves the muted mic for the Droid on Nimbuzz. I hope for an update and video call!

Comments (View)

Facebook Connect for web2py

Even though web2py has support for building facebook applications, we didn’t have a way to use Facebook Connect.

I’ve studied many ways (like Facebook’s Javascript API) and checked other frameworks (Rails and Django) and after 4 hours I made a patch to facebook.py that enables web2py (and I’m sure that other python frameworks can use - like webpy) to use Facebook Connect by doing this:

def index():
   connected = facebook_connect(request, facebook_settings)
   if connected:
       user = get_facebook_user(request.facebook)
       response.flash = "Hello ", user       
   return dict(api_key=facebook_settings.FACEBOOK_API_KEY)

Just one line of code and you are done!

You can check a live example here and grub the code from github

Comments (View)
Sat Dec 26

Implementing a Rails-like scaffolding in web2py (but better!)

Sometimes I want to create a better administration panel for our clients. With this hack you can create an add/edit/delete panel for every table you like and extend it easily. in order to use it you just go inside the controllers and add:

@scaffold(None)
def authors():
pass

this will create an admin page (authors) that has all the properties from the table “authors”. if you have to “admin” a different table just put it’s name:

@scaffold("other_table")
def authors():
pass

Read the comments for more hacks. PS: I have also a new version that you can pass custom queries (I’ll keep you updated). PS2: Also a version with DataTables (http://datatables.net/)

You can also chain decorators in order to prevent unauthorized access:

@auth.requires_login()
@scaffold("other_table")
def authors():
pass

Now, the installation:

First, put this code inside a module (or in a separate file in models).

def scaffold(tblname=None, fieldid=None): “”” Decorator that exposes show/add/edit/delete for admin purposes

    You can specify a table name else it will use the
name of the function as table name
You can specify a field id that will be displayed for the record
else it will use the first field value
"""

def decorator_outside(func):

def decorator_inside(*args):

db_name = db # we could get the database name from globals
table_name = func.__name__ if tbl_name == None else tbl_name
if table_name not in db_name.tables:
raise Exception("No table with name '%s' found" % table_name)

form = None
if len(request.args) > 1:
action = request.args[0]
record_id = request.args[1]

if action == 'create':
form = crud.create(db_name[table_name])

elif action == 'show':
form = crud.read(db_name[table_name], record_id)

elif action == 'edit':
form = crud.update(db_name[table_name], record_id)

elif request.args[0] == 'delete':
form = crud.delete(db_name[table_name], record_id)

result = db_name(db_name[table_name].id > 0).select()
func()

return dict(rows=result, cntr_name=table_name, form=form, field_id=field_id)
return decorator_inside

return decorator_outside

The do the action in the controller @scaffold(“other_table”) def authors(): pass

Finally create a view file:

{{extend 'layout.html'}}
{{ include 'scaffold.html' }}

and paste this into your views folder:

{{= form if form != None else "" }}
<br />
<table>
{{ i = 0 }}
{{ for row in rows: }}
{{ i += 1 }}
<tr class="{{='even' if i%2 else 'odd'}}">
<td class='main'><a href="{{= URL(r=request, f=cntr_name+'/show',
args=row.id) }}">{{= row.values()[field_id] }}</a></td>
<td><a href="{{= URL(r=request, f=cntr_name+'/edit',
args=row.id) }}">Edit</a></td>
<td><a href="{{= URL(r=request, f=cntr_name+'/delete',
args=row.id) }}">Delete</a></td>
</tr>
{{ pass }}
</table>

{{ if not len(rows): }}
No records found
{{ pass }}

<br />
<a href="{{= URL(r=request, f=cntr_name+'/create/new') }}">Add new</a>
Comments (View)
Fri Dec 18

Uploading files using CKEditor in web2py

This is the second part of integrating CKEditor in web2py. I should warn you that quotes are messed up in the blog so you can check at web2pyslices for the updated (and ready for copy-paste) version.

What it needs to be done in order to have ckeditor uploading works. First, it needs a “file browser” url. That’s just a form with an upload field where we can use to find and upload files. The think is that we must return the path of the uploaded file BACK to the parent form. The most difficult part is activating the Upload button. That is done by specifying the “filebrowserBrowseUrl”. So, here it goes!

Let’s add a new table that will hold our files:

import datetime;
timestamp = datetime.datetime.today()
db.define_table('files',
Field('title', 'string'),
Field('uploaded_data', 'upload'),
Field('created_on','datetime',default=timestamp))

db.files.title.requires = IS_NOT_EMPTY()
db.files.uploaded_data.requires = IS_NOT_EMPTY()

Now, lets add an action the our controller

def upload_file():
url = ""

form = SQLFORM(db.files, showid=False)
if form.accepts(request.vars, session):
response.flash = T('File uploaded successfully!')
url = URL(r=request, f="download",
args = db(db.files.title == request.vars.title).select(orderby=~db.files.created_on)[0].uploaded_data)
return dict(form=form, cknum=request.vars.CKEditorFuncNum, url=url)

and a view upload_file.html:

{{extend 'layout.html'}}

<h2>Upload file</h2>
{{=form}}


{{ if url != "": }}
<script type="text/javascript">
window.opener.CKEDITOR.tools.callFunction({{=cknum}}, '{{=url}}');
</script>
{{ pass }}

Then, lets add the javascript files to our layout AFTER web2py_ajax.html:

 <script type="text/javascript" src="{{=URL(request.application,'static','js/ckeditor/ckeditor.js')}}"></script>

Finally, lets create a test page:

{{extend 'layout.html'}}

{{=form}}

<script type="text/javascript">
var ckeditor = CKEDITOR.replace('page_body', {
filebrowserBrowseUrl : "{{=URL(request.application, c='default', f='upload_file')}}",
//filebrowserUploadUrl : "{{=URL(request.application, c='default', f='upload_file')}}",
});
</script>

We are ready!

Comments (View)
Wed Nov 18

Creating unicode permalinks in Python (even from Greek!)

Optimizing this blog post, which shows you how to create a greek to greeklish “translator”, I’ve created a permalink function that creates urls from greek titles (but you can use your language).

Enjoy!

def create_permalink(s):
“”“
Create greeklish permalinks.
Also works for english.
“”“
import string
import re

input_string = s.lower().decode(‘utf-8’).encode(‘iso-8859-7’, ‘replace’)
from_chars = ‘αβγδεζηθικλμνξοπρσςτυφχψωάήέίόύώϊ’.decode(‘utf-8’).encode(‘iso-8859-7’, ‘replace’)
to_chars = ‘abgdezh8iklmn3oprsstufxywaheiouwi’

translation_table = string.maketrans(from_chars, to_chars)
input_string = string.translate(input_string, translation_table)

return re.compile(“\W+”, re.UNICODE).sub(“_”, input_string)


Comments (View)
Fri Oct 30

Using widgets in web2py (integrating CKEditor)

Although web2py comes with an integrated editor, I really like ckeditor and using it for a text field is trivial using widgets!

First, install ckeditor (put the ckeditor inside a js/ckeditor file in your static folder and include it) :

<script type=”text/javascript” src=”{{=URL(request.application,’static’,’js/ckeditor/ckeditor.js’)}}”></script>

After that, we define a ‘body’ text field (or whatever name you like):

db.define_table(‘page’,
# more Fields …
Field(‘body’, ‘text’))

Then, inside your db.py (or to another file in your models directory) put the widget:

def advanced_editor(field, value):
return TEXTAREA(_id = str(field).replace(‘.’,’_’), _name=field.name, _class=’text ckeditor’, value=value, _cols=80, _rows=10)

and use the widget

db.page.body.widget = advanced_editor

From now, SQLFORM will use ckeditor to show/edit/save data!

CkEditor in web2py

Comments (View)
Wed Oct 7

Creating a dropdown with country names in web2py

There are many ways to create a dropdown that includes all countries in web2py but the most pythonic way goes like this:

Create a module (let’s name it countries.py) and put a list of countries :

COUNTRIES=(‘United States’, ‘Afghanistan’, ‘Albania’, ‘Algeria’, ‘Andorra’, ‘Angola’, ‘Antigua and Barbuda’, ‘Argentina’, ‘Armenia’, ‘Australia’, ‘Austria’, ‘Azerbaijan’, ‘Bahamas’, ‘Bahrain’, ‘Bangladesh’, ‘Barbados’, ‘Belarus’, ‘Belgium’, ‘Belize’, ‘Benin’, ‘Bhutan’, ‘Bolivia’, ‘Bosnia and Herzegovina’, ‘Botswana’, ‘Brazil’, ‘Brunei’, ‘Bulgaria’, ‘Burkina Faso’, ‘Burundi’, ‘Cambodia’, ‘Cameroon’, ‘Canada’, ‘Cape Verde’, ‘Central African Republic’, ‘Chad’, ‘Chile’, ‘China’, ‘Colombia’, ‘Comoros’, ‘Congo’, ‘Costa Rica’, “C&ocirc;te d’Ivoire”, ‘Croatia’, ‘Cuba’, ‘Cyprus’, ‘Czech Republic’, ‘Denmark’, ‘Djibouti’, ‘Dominica’, ‘Dominican Republic’, ‘East Timor’, ‘Ecuador’, ‘Egypt’, ‘El Salvador’, ‘Equatorial Guinea’, ‘Eritrea’, ‘Estonia’, ‘Ethiopia’, ‘Fiji’, ‘Finland’, ‘France’, ‘Gabon’, ‘Gambia’, ‘Georgia’, ‘Germany’, ‘Ghana’, ‘Greece’, ‘Grenada’, ‘Guatemala’, ‘Guinea’, ‘Guinea-Bissau’, ‘Guyana’, ‘Haiti’, ‘Honduras’, ‘Hong Kong’, ‘Hungary’, ‘Iceland’, ‘India’, ‘Indonesia’, ‘Iran’, ‘Iraq’, ‘Ireland’, ‘Israel’, ‘Italy’, ‘Jamaica’, ‘Japan’, ‘Jordan’, ‘Kazakhstan’, ‘Kenya’, ‘Kiribati’, ‘North Korea’,’South Korea’, ‘Kuwait’, ‘Kyrgyzstan’, ‘Laos’, ‘Latvia’, ‘Lebanon’, ‘Lesotho’, ‘Liberia’, ‘Libya’, ‘Liechtenstein’, ‘Lithuania’, ‘Luxembourg’, ‘FYROM’, ‘Madagascar’, ‘Malawi’, ‘Malaysia’, ‘Maldives’, ‘Mali’, ‘Malta’, ‘Marshall Islands’, ‘Mauritania’, ‘Mauritius’, ‘Mexico’, ‘Micronesia’, ‘Moldova’, ‘Monaco’, ‘Mongolia’, ‘Montenegro’, ‘Morocco’, ‘Mozambique’, ‘Myanmar’, ‘Namibia’, ‘Nauru’, ‘Nepal’, ‘Netherlands’, ‘New Zealand’, ‘Nicaragua’, ‘Niger’, ‘Nigeria’, ‘Norway’, ‘Oman’, ‘Pakistan’, ‘Palau’, ‘Palestine’, ‘Panama’, ‘Papua New Guinea’, ‘Paraguay’, ‘Peru’, ‘Philippines’, ‘Poland’, ‘Portugal’, ‘Puerto Rico’, ‘Qatar’, ‘Romania’, ‘Russia’, ‘Rwanda’, ‘Saint Kitts and Nevis’, ‘Saint Lucia’, ‘Saint Vincent and the Grenadines’, ‘Samoa’, ‘San Marino’, ‘Sao Tome and Principe’, ‘Saudi Arabia’, ‘Senegal’, ‘Serbia and Montenegro’, ‘Seychelles’, ‘Sierra Leone’, ‘Singapore’, ‘Slovakia’, ‘Slovenia’, ‘Solomon Islands’, ‘Somalia’, ‘South Africa’, ‘Spain’, ‘Sri Lanka’, ‘Sudan’, ‘Suriname’, ‘Swaziland’, ‘Sweden’, ‘Switzerland’, ‘Syria’, ‘Taiwan’, ‘Tajikistan’, ‘Tanzania’, ‘Thailand’, ‘Togo’, ‘Tonga’, ‘Trinidad and Tobago’, ‘Tunisia’, ‘Turkey’, ‘Turkmenistan’, ‘Tuvalu’, ‘Uganda’, ‘Ukraine’, ‘United Arab Emirates’, ‘United Kingdom’, ‘Uruguay’, ‘Uzbekistan’, ‘Vanuatu’, ‘Vatican City’, ‘Venezuela’, ‘Vietnam’, ‘Yemen’, ‘Zambia’, ‘Zimbabwe’)

then import it to db.py

from applications.yourapplicationname.modules.countries import *

and just “map” the whole list to a database field

db.shipping_info.countries.requires = IS_IN_SET(COUNTRIES)

Now, when you render the field using SQLFORM in your view, a dropdown (select) will be created automatically including all the countries.

Yeap, SQLFORM rocks.

Enjoy!

Comments (View)
Mon Sep 28

Adding your .emacs to Mercurial / Git

Having my favorite .emacs settings available, in the tip of my “hg clone” command is precious. No more backups and no more “oh no, I have an older version in my usb stick”. And it’s easy!

First of all, you need a mercurial server. Or an account at http://bitbucket.org/. Of course the same procedure stands for git.

Then you create a new repository (let’s call it my-emacs).

After that, you must move/rename your .emacs.d/ directory to .emacs.d-old/ and clone your repository.

cd ~

mv .emacs.d/ .emacs.d-old

rm -R .emacs.d/

hg clone https://yourname@bitbucket.org/yourname/my-emacs .emacs.d

the last line is available for copy-past on bitbucket.

Then you copy all your files to the .emacs.d which is now under version control

cp .emacs.d-old/ .emacs.d -R

Now the only thing is missing is adding your .emacs file. There are two ways. One is creating a init.el and the other one is having a .emacs file that loads another one dot-emacs.el which is in your version-controlled .emacs.d/

So,

cp .emacs .emacs.d/dot-emacs.el

The .emacs which is outside of .emacs.d (thus not under version control, should have this line:

(load “~/.emacs.d/dot-emacs.el”)

And you are ready! If you need to ignore a directory (which is inside .emacs.d/) just create a .hgignore file inside .emacs.d/ and add the name of the directory or any other files (google “hg ignore”):

ignore-dir/

Finally commit everything and push them to server.

cd .emacs.d

hg add *

hg commit -m “First commit”

hg push

Enjoy!

Comments (View)
Sat Sep 19

First review - Karmic Ubuntu Moblin Remix

No one has posted a review of the upcoming Ubuntu remix, so here we go!

First of all, I installed it via usb-creator on a 64gb USB (you need more than 1gb usb for installation via usb - even a 2gb will do) with no problem at all.

The boot stage is identical to the Ubuntu 9.10 and way slower than Moblin’s boot stage (+10secs). After that, the environment seems the same, but now we have the Ubuntu wallpaper and many Ubuntu programs (OpenOffice, Empathy, Synaptic package manager, etc).

The network still has the same bugs as the Moblin has (can’t save password and I couldn’t connect to wifi) and the main problem is that every time you run a program, it doesn’t seem very integrated into the Moblin UI, so when you close the application, a white screen welcomes you. After that you have to click the menu bar and return to whatever you were doing.

Another thing is that whenever you are starting a program you have to decide whether you want a new space or you want to squeeze it to an old one (the dialog stays for about 3 secs).

Definitely not a production-ready image (it’s called “development iso” for a reason) but I think that in order to utilize the Moblin v2 UI, many application must be rewritten or replaced.

You can check the images in better quality and some more here

Comments (View)