Python Programming, news on the Voidspace Python Projects and all things techie.

Python & Lisp

emoticon:python Lisp is a language with an esoteric and mysterious aura. It promises the ultimate flexibility in programming power for those who can truly grasp the enlightenment it hides.

But now it seems you can have the best of both worlds, the clarity of Python and the power of Lisp. Behold, arise :

CLPython - Python Written in Common Lisp

One thing that isn't clear from the Trac page is why. Laughing

Actually, it does suggest that CLPython will provide the same integration between Python & Lisp that Jython enjoys with Java, but this merely defers the question...

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-06 22:31:09 | |

Categories: ,


Movable Python, Tkinter & Tooltips

emoticon:python Did I mention that I am working on Movable Python ? Wink

One of the new features that I thinks greatly improves usability was also one of the easiest to implement, tooltips.

There is a very easy to use module included in the Python standard library, as part of IDLE, called CallTipWindow.py. With a bit of modification it made adding tooltips to buttons (and other widgets) a snap.

As the code isn't very long I've included it here in full.

from Tkinter import *

class ToolTip(object):

    def __init__(self, widget):
        self.widget = widget
        self.tipwindow = None
        self.id = None
        self.x = self.y = 0

    def showtip(self, text):
        "Display text in tooltip window"
        self.text = text
        if self.tipwindow or not self.text:
            return
        x, y, cx, cy = self.widget.bbox("insert")
        x = x + self.widget.winfo_rootx() + 27
        y = y + cy + self.widget.winfo_rooty() +27
        self.tipwindow = tw = Toplevel(self.widget)
        tw.wm_overrideredirect(1)
        tw.wm_geometry("+%d+%d" % (x, y))
        try:
            # For Mac OS
            tw.tk.call("::tk::unsupported::MacWindowStyle",
                       "style", tw._w,
                       "help", "noActivates")
        except TclError:
            pass
        label = Label(tw, text=self.text, justify=LEFT,
                      background="#ffffe0", relief=SOLID, borderwidth=1,
                      font=("tahoma", "8", "normal"))
        label.pack(ipadx=1)

    def hidetip(self):
        tw = self.tipwindow
        self.tipwindow = None
        if tw:
            tw.destroy()

def createToolTip(widget, text):
    toolTip = ToolTip(widget)
    def enter(event):
        toolTip.showtip(text)
    def leave(event):
        toolTip.hidetip()
    widget.bind('<Enter>', enter)
    widget.bind('<Leave>', leave)

This is how it looks, shown with one of the new Movable Python dialogs :

Tooltips in Action

To use it, simply create a button (or label or whatever) and call :

createToolTip(widget, "This is a tooltip")

Another useful thing to do is bind Return to the action of the button. That way when it is focussed the user can activate it with the return or enter key :

widget.bind('<Return>', command)

I won't give away quite all my secrets, but I thought this was nice. The tooltips are shown when the mouse is over the widget, and it is remarkably smooth in action. Smile

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-06 21:29:24 | |

Categories: ,


IronPython & Modal Dialogs

emoticon:halt My IronPython Tutorials have slowed down whilst I'm working full steam on Movable Python. Good progress, honestly. Rolling Eyes

In the meantime, this nifty example of making a modal dialog was posted to the IronPython Mailing List by Martin Maly.

import clr
clr.AddReference ('System.Windows.Forms')

from System.Windows import Forms


class MyDialog(Forms.Form):
   def __init__(self):
       self.Text ='Dialog'
       egg_button = Forms.Button(Text='Eggs', Visible=True)
       egg_button.Click += self.OnEgg
       spam_button = Forms.Button(Text='Spam', Visible=True, Left=50)
       spam_button.Click += self.OnSpam
       print self.Controls.Add(egg_button)
       print self.Controls.Add(spam_button)

   def OnEgg(self, *args):
       self.result = "Eggs"
       self.DialogResult = Forms.DialogResult.OK
       self.Close()

   def OnSpam(self, *args):
       self.result = "Spam"
       self.DialogResult = Forms.DialogResult.OK
       self.Close()

class MyMainForm(Forms.Form):

   def __init__(self):
       self.Text = 'Main Form'
       my_button = Forms.Button(Text='Choose one!')
       my_button.Click += self.OnClick
       self.Controls.Add(my_button)

   def OnClick(self, *args):
       md = MyDialog()
       if md.ShowDialog() == Forms.DialogResult.OK:
           print md.result


app = MyMainForm()
Forms.Application.Run(app)

It's not the most attractive example, but the code is very readable.

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-06 20:59:30 | |

Categories: , ,


Do You WTF ?

emoticon:speaker It wasn't very long ago that someone introduced me to The Daily WTF, where horrible and evil code examples are posted for the rest of us to laugh at.

Today's is (was ?) brief and mildly amusing, a short function written in VB :

Private Function Add(ByRef Which As Integer, ByVal HowMany As Integer)
  Which = Which + HowMany
End Function

The amusement factor is that the whole function could have been replaced with the += operator (which may or may not have existed in the version of VB in use when the function was written), or simply Which = Which + HowMany.

Now I don't often indulge in smug MLIBTYL debates [1], but even more amusing than the original is the Perl equivalent that someone posted as a comment :

sub Add
{
@_[0] = @_[0] + @_[1];
}

WTF ? Laughing

[1]Well possibly I do, but less than I used to since I started working with a Ruby admirer and an intern with impressive C# skills who isn't yet convinced by Python.

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-06 20:49:02 | |

Categories: ,


Firedrop2 News

emoticon:firedrop2 Firedrop2 is a Python blog client that I use, and maintain along with a bunch of a few other kindred souls.

Adalbert Prokop has created a web-page on his site about Firedrop2 :

Firedrop Page

Particularly of interest are the following items available from that page :

  • He has created a Firedrop RPM
  • He has also created a Wax RPM
  • A patch which addresses a couple of minor issues in the latest release of Firedrop

Many thanks to Adalbert.

I'm currently bogged down with Movable Python, but will return to Firedrop development soon. More news about Movable Python shortly...

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-04 10:45:02 | |

Categories: ,


IronPython & Modules

emoticon:noise IronPython seems to be settling in well at its new home.

Someone recently asked on the Mailing List about including Python code in DLLs, rather than distributing Python source files with their application.

The following trick will also work for CPython. It is less needed there because you can distribute bytecode (.pyc) files instead. (You can however pickle bytecode objects, into a database for example, and use this to 're-inflate' modules later.)

import imp
import sys

newModule = imp.new_module(moduleName)
exec(moduleSource, newModule.__dict__)
sys.modules[moduleName] = newModule

After this you can import the module as usual. If you have any circular imports, you may be able to solve the dependency order by inserting the empty modules into sys.modules before you exec the source file.

This means you can include your Python source code as a string (encrypted if you want) in your DLL and make it available to IronPython. This of course is a hack, but it is a workaround until compiling Python source to assemblies is stable. Razz

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-04 10:15:26 | |

Categories: , ,


Has Sourceforge Lost its Mojo ?

emoticon:cyberpunk Sourceforge has long been a mainstay of the Open Source community, providing hosting and development services for thousands of projects including several major ones.

Up until recently it has hosted the code repository for Python, and still hosts the bug tracker.

Several of my Python projects, including ConfigObj, Firedrop2 and rest2web have homes there. As well as providing a useful mirror for the (rare) occasions when the Voidspace site is down, they provide mailing lists (with online archive) for developer discussion.

Unfortunately their are signs that either Sourceforge can't cope with its success, or perhaps is losing its Mojo Question

Because of developer complaints about the bug tracker (outages, failing to send emails, general interface awkwardness), the call has gone out to find a replacement bug tracker for Python.

Although Sourceforge now provides Subversion repositories, when Python moved from CVS they moved away from Sourceforge because of the delays in synchronising the back end repositories with the public facing ones.

The sourceforge web interface, particularly for project management is fairly gruesome (and don't even think about turning on their forums). A little AJAX (updating trove categories for example) would go some way to resolving this. Luckily a great little project (written in Python of course) called Releaseforge takes all the pain out of updating and administering sf projects, so I stopped worrying about that a while ago.

Unfortunately, the SF website has intermittently and infuriatingly failed to allow me to login over the past few weeks. Sometimes I could login, but as soon as I navigated to a new page it would 'forget' me. sigh

I've finally succeeded in registering a new project, because I still think it is useful for projects to have a presence their, but my enthusiasm is further dimmed. Hopefully the sourceforge team, who I'm sure have the best of intentions, can deal with these problems and will retain their position in the community. If they don't, Microsoft are hard on their heels. Wink

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-04 09:30:41 | |

Categories:


How Dynamic is too Dynamic ?

emoticon:scanner One of my colleagues is a young and distinguished Polish gentleman who has altogether too many consonants in his name (and in quite the wrong order), Andrzej Krzywda.

As well as being a decent sort of chap, he is a very good programmer. Smile

He has a good instinct for "code smell", when code gets overly complex or over engineered. This is particularly import for us at Resolver as we tend not to comment code. If you can't tell what it's doing by looking at it, it needs refactoring [1]. Razz

Sometimes of course, code has to be complex. If you're expressing a complicated algorithm, or doing something inherently difficult, then some complexity is unavoidable. Andrzej introduced me to a new concept when he said that this sometimes point to "requirement smell". If the requirements are forcing the code to be ugly and complex, the requirements may be in need of a refactor. Nice.

Anyway, on to the real point of this entry. Andrzej now programs for Resolver in Python. Before that he wrote web applications in Ruby, and is very fond of the language. For his personal projects he uses Ruby on Rails [2].

All of his Ruby experience is via Rails, so he feels more like a "Rails Programmer" than an experienced "Ruby Programmer". He likes both languages and can see the benefits (and disadvantages) of both languages.

For example the lack of unicode support in Ruby is a problem, but the "more than one way to do it" philosophy often allows elegant solutions to problems.

He is writing a language comparison, which at some point I will post here, or link to if he gets it together and creates his own blog. It will be nice to read a balanced comparison by someone who uses both languages in practical situations and has no axe to grind... Smile

He made an interesting (and valid) comment recently. He says that in discussion with Java programmer a Python programmer would crow about how dynamic their language is, and how much of an advantage this is. Yet in a discussion with a Ruby programmer, who can append methods to built-in classes, the same guy would say "that's just too dynamic". In Python we call this 'monkey patching', but Andrzej uses it to great effect.

When I asked him if it caused problems with third party libraries, who will use your modified data-types or may modify data-types themselves, he replied that if you have full unit test coverage you will catch this before it is a problem.

[1]We do have some comments.
[2]Another interesting aside, he has a friend who is a Python fanatic and thinks that Django is fantastic. However when it came to choosing a framework for a web application at his company, he chose Rails because of the lack of Ajax support in Django. (His words not mine.)

Like this post? Digg it or Del.icio.us it.

Posted by Fuzzyman on 2006-07-04 09:09:27 | |

Categories: ,


Hosted by Webfaction

Counter...