Archive for the 'Python' Category

04
Oct
09

PyML(Python Markup Language) template engine

I know it’s been a while since my last post. I’ve been busy with setting up and pulling down pepijndevos.nl(after I decided to go for another blog system), I’ve spend a good deal of time working on PyMouse and worked on some projects for myself and for clients.

I want to share one of those projects with you. I decided to make a CMS like Jekyll and Hyde(not the book!), since I liked neither of the previous systems. So like a lot of people who like reinventing wheels I started to look for a nice markup language for the user and a nice template language for the designer.

I choose for Markdown right away, end of story here…

Because of the little experience I have with Pylons I looked ad Genshi and Mako initially(can’t help the Chinese feeling these names give me). Personally the ugly tags in most template languages make me run away, so I threw Make out of the window, together with all the other ugly-tag-based languages.

I like the idea of working with valid XML attributes for templating, so I started of with Genshi initially, especially since speed isn’t a major point for a static blog!

Days later I came across this wiki page on the Python website: http://wiki.python.org/moin/Templating

Looking at Dirty I remembered my own attempts to write a template language implemented as Python objects(extending dict, for free functionality).

The problem with writing such a thing is described in the code below, I mailed the developer of Dirty about how he solved the problem — he didn’t.

>>> def div(*content, **attributes):
...     pass
...
>>> div("hello world!", id="test") # Doesn't html have the attributes first!? Ugly!
>>> def div(**attributes, *content): # Not allowed!
  File "", line 1
    def div(**attributes, *content):
                        ^
SyntaxError: invalid syntax
>>> def div(atributes, *content):
...     pass
...
>>> div({'id':'test'}, "hello world!") # Even uglier!

But then I came up with this slightly brilliant solution:

When you define __call__ on a class it allows you to call the class, no big deal, eh? Wrong! It allows you to write this:

html(xmlns="http://www.w3.org/1999/xhtml")(
    head( # No atributes
        title("Hello world")
    ),
    body(
        p(id="test")(
            "Hi", br(),
            "How are you?"
        ),
        img(src="test.img", alt="just a test") # No content
        ul(
            *[li(c) for c in xrange(10)] # Now that is cool!
        )
    )
)

In short PyML is a pure Python combination of a string and a dict looking like html when written and printed!

You can do all sorts of things with this that you normally do with dictionaries, strings and lists, like sorting and filtering them, change a p into a div or getting/setting attributes later with square brackets. You could define functions to return a snippet or you could include templates into others. If you’re finished with them, just print the object!

Oh, about the speed? Quite good for my hobby project! (Unreliable micro benchmark ahead!)

Render time Engine
0.03160 PyML
0.50618 Genshi
0.01813 Mako

You can get it here if you want! Or wait for my complete CMS of course…

23
Aug
09

About __main__

I think most Python programmers have written it a thousand times:

if __name__ == '__main__':
    #some code

I also assume you know what the result is of the following code:

class test(object):
    pass

print test.__name__
#test

So lets assume the __name__ variable contains the current class name, what would the __main__ class be? It’s the invisible main class of course! But there’s something strange going on:

print test
#<class '__main__.test'>

print __main__
#NameError: name '__main__' is not defined

So… the test function is a member of __main__, but main itself does not exist? Strange… When I was frustrated by this I experimented some, lets check the following piece of code:

import __main__

print __main__
#<module '__main__' (built-in)> 

print dir(__main__)
#['__builtins__', '__doc__', '__main__', '__name__', 'test']

__main__.test2 = 'Hello world!!!'
print test2
#Hello world!!!

Isn’t that amazing? We imported __main__, saw it had the test class assigned to it, we assigned a new variable and saw the module scope updated!

This might sound quite pointless, but you can do a lot of dirty tricks with it, for example assign variables by strings:

name = raw_input('Enter a variable name: ')
setattr(__main__, name, 'Dirty trick')
print dir(__main__)
#['__builtins__', '__doc__', '__main__', '__name__', 'test', 'test2', '<your input here>']

This method is used in my xhtml generator to assign partitial functions for xhtml tags to the module scope(to have a(href=”test”) instead of SomeClass.a(href=”test”) or even SomeClass.html(‘a’, href=”test”).

30
Jul
09

Get the overview on what is happening on Twitter visually!

example

Now available as a web service!

Have you lost who is saying what to who? Do you think one image(graph) says more than a thousand words(tweets)? Are you tired of clicking back and forth to see conversations?

I’ve made a new Twitter solutions that shows all your tweets and your friends tweets in one graph. It connects your tweets to the people you @refer to and to #tags!

To try this great application download it from my Box.net widget as usual. The usage is:

$ python tweetograph.py USERNAME:PASSWORD[ dot|neato|twopi|circo|fdp]

Requires Python-Twitter and PyDot to run. You can optionally specify the Graphviz tool you want to use for layout(default is dot), see Wikipedia.

Known bugs:

  • Dot is really picky on characters entered, so currently some characters get stripped

Update: Now it even draws dotted lines from ReTweets to their original, so you can actually see where that RT came from!

Update: here is a PDF of my network, so you can see how it works: bobdebvlinder(rendered using neato)

Update: Replies now get a dashed line between them so you can really follow conversations!

11
Jul
09

Ipod touch WiFi mouse with Python (web app)

You might know it is possible with several applications to turn your iPod Touch or iPhone into a wireless mouse. You download/buy the app in the app store, install the server and voila, finished!

This works perfect, so why did I make another one? I think the problem is that you need a client and a server. Maybe the best option would be making an app that implements the Bluetooth mouse protocol so you can use it as a normal Bluetooth mouse. The problem with that is that I don’t know anything about C or Bluetooth. So I reversed the plan and made a server without the need for a client.

I’ll explain how it works. I wrote a Python app that extends the Python built-in webserver to server an empty html document. Well… almost empty, it only contains some JS to send back the touch events. Back at the server I register the events and move the mouse.

Although ‘move the mouse’ sounds easy, that is the most complicated part of the application. It currently only works for Windows and Mac.

The advantage of using Safari is that it gives us JS access to all touch movement as wel as allowing for portrait and landscape mode and pinch-to-zoom for detailed movement. In the future I might add a text field to send text to the computer, but this would be another cross-platform horror…

You can download the app form my box widget in the sidebar. Just run it with Python and point you iPod touch/iPhone to <computer ip>:3333

10
Jul
09

Control the mouse on Mac with Python!

It’s 00:30 now here… After searching the internet for the whole day I finally found to move AND click the mouse with Mac OS X!!!

This link on StackOverflow got me on the right path. It explains how to use pyobjc to move the mouse around, but this does not include clicking it 😦 After a few more hours of Googling I found this extra piece of information for writing a command line click utility. But the pyobjc nor the Apple functions are documented very well, so I had absolutely no clue on how get the function into Python.

Then I finally found this xml document… I had nearly did away with it as it looked useless at first. Until I noticed that at the function described in the first document it showed {CGPoint=ff}, this piece of code was confusing me the most about this whole stuff. Well, the rest was guesswork at the interactive shell… ‘v{CGPoint=ff}III’ is the final string I came up with.

So here they are!

import objc

def clickMouse(x, y, button):
    bndl = objc.loadBundle('CoreGraphics', globals(), '/System/Library/Frameworks/ApplicationServices.framework')
    objc.loadBundleFunctions(bndl, globals(), [('CGPostMouseEvent', 'v{CGPoint=ff}III')])
    CGPostMouseEvent((x, y), 1, button, 1)
    CGPostMouseEvent((x, y), 1, button, 0)

def moveMouse(x, y):
    bndl = objc.loadBundle('CoreGraphics', globals(), '/System/Library/Frameworks/ApplicationServices.framework')
    objc.loadBundleFunctions(bndl, globals(), [('CGWarpMouseCursorPosition', 'v{CGPoint=ff}')])
    CGWarpMouseCursorPosition((x, y))

How I think it works:

  1. The first line works like an import statement to include CoreGraphics… nothing Python related happens here.
  2. The second line is the most important one. From the just imported bundle it imports the C function to Python… I think the second part is for mapping Python data types to C data types.
  3. Line 3 and 4 run the fresh C function with Python data types! (once for keyDown and once for keyUp, otherwise Finder gets stuck)

Enjoy!

25
Jun
09

Easy_install problems: No eggs found in (setup script problem?)

Just a note to myself and anyone who has problems using easy_install: This link helped me a lot.

$ easy_install -U setuptools

I wanted to install Pylons system wide, instead of the virtual Python it installs by default. easy_install provided an easy alternative, but it gave tons of errors for every dependency that there where egg files missing.

The above command updates setuptools, the package which contains easy_install, it’s like the selfupdate feature of Macports. After the update all files worked again for me!

When I succeed in getting Lighttpd to behave I’ll post a tutorial on how to set up system wide Pylons with multiple applications in Lighttpd on a mac. This article does not include the installation of Pyolons nor Lighttpd, and sets the webroot to the project file, but except for that it was very helpful to me.

So far I got Lighttpd to serve a html file with the scgi module disabled. I got Pylons to show the default project page when using the built in development server. But with scgi enabled I get(static content):

Too many redirects occurred trying to open “http://127.0.0.1/”. This might occur if you open a page that is redirected to open another page which then is redirected to open the original page.

or(project page)

2009-06-25 16:43:40 : Protocol error ‘invalid netstring length’
2009-06-25 16:43:40,553 ERROR [scgi-wsgi] Protocol error ‘invalid netstring length’

01
Apr
09

First library for my CMS started!

I finaly started coding for my CMS. I’m not sure if I’m already up to the job, but I’ll find out soon enough. The first library is part of the template engine. I don’t want people to write crap HTML, so I wrote a library that can generate strict XHTML with python code that is as similar to html as possible, see below for an example.

The big question remains, what to do with user content, even valid XHTML theme break if someone pastes his Word HTML in the editor. I plan on using BeautifulSoup to parse the user code, strip off the ‘invalid’ tags like <i>, <u>, <iframe>, etc… and feed it to my XHTMLLib. The even cooler part is that you could use your old HTML theme, feed it to my lib and fill/replace the content. With the latest version this became even easyer because I added some sort of xpath support(absolute paths only, but with attribute selection).

I present to you, my first lib!

Link: http://www.box.net/shared/6x01eol1x5 Also available in the sidebar widget. You need xhtmlattr.py as well!

Example:

page = XHTMLLib().template() # generate a basic XHTML template
    page.xpath('/html/head/title')['child'] = "Hello world" # set the title

    page.function_factory(['div', 'img', 'fieldset', 'input', 'ul', 'li'], '', '') # register functions

    lists = [li(class_='xtra', child="Home"), li(class_="test", child="Links"), li(child="Contact"), li(class_="test", child="About"), li(child="Sitemap")] # create a list
    lists.sort() # sort elements

    page.xpath('/html/body')['child'] = [ # add to the body
        div(id_='header', child='test & more'), # Entities get converted
        img(src='image.jpg'),
        fieldset(class_='test', child=[
            input(type_='text', name='name'),
           input(type_='submit')
        ]),
        ul(child=lists) # Comppose pages of different object sets.
   ]

    page.xpath('/html/body/img').__setitem__('onclick', 'alert("!@#$^, stop clicking!")', True) # Voodoo magic to get evil js in, alsays use external js!
    page.xpath('/html/body/ul/li[class=test][4]')['style'] = 'color:red' # Some more 'advanced xpath' to get a specific list item

    print page.render();

result:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
	<head>
		<meta content="application/xhtml+xml;charset=utf-8" http-equiv="Content-Type"></meta>
		<title>Hello world</title>
	</head>
	<body>
		<div id="header">test &amp; more</div>
		<img src="image.jpg" onclick="<![CDATA[alert("!@#$^, stop clicking!")]]>"></img>
		<fieldset class="test">
			<input type="text" name="name"></input>
			<input type="submit"></input>
		</fieldset>
		<ul>
			<li>Contact</li>
			<li>Sitemap</li>
			<li class="test">About</li>
			<li class="xtra">Home</li>
			<li style="color:red" class="test">Links</li>
		</ul>
	</body>
</html>



My blog has moved!

My blog has permanently moved to a self hosted Wordpress at http://pepijndevos.nl

This blog will stay around for accidental search engine visitors.

Me

This is me

Blog Stats

  • 22,233 hits

@PepijnDeVos