Friday, December 14, 2012

Prototyping a class in Python

I'm not sure what's the name for this technique (for me it resembles what is called prototyping in javascript -- I know it's not the same, but the fact is that you're building your class outside of it, although in Python it's still in its declaration step).

Anyways, the idea is the following: you want to change the class attributes before it becomes final -- there are things you just can't do in Python after a class is already declared (Python uses this technique for creating properties -- in my specific use-case I'm using it to overcome some limitations that Django has in its model inheritance with fields, but I've already used this many times).

The idea is the following: you get the frame which is being used inside the class declaration and change the locals in it so that the final created class will have the things you declared.

I.e.: This code:

import sys

def prototype_class(frame=None):
    if frame is None:
        frame = sys._getframe().f_back

    frame.f_locals['new_attribute'] = 'New attribute'

class MyNewClass(object):
    prototype_class()

print MyNewClass().new_attribute
 

Is the same as:

class MyNewClass(object):
    new_attribute = 'New attribute'
 

-- Just more complicated and more flexible -- in my case, it'll properly help me to choose how to create and customize the fields of a Django model class without having to copy and paste a bunch of code.

On a separate note, blogspot just sucks for code... why can't they simply create an option to add a piece of code? I'm now manually putting my code in html as described in http://stackoverflow.com/a/8697421/110451 -- it'd certainly be trivial for the blogspot devs to put a button which would do that for me right? (colors would be nicer, but this is the easiest things that just works for me and I'd already settle for it if blogger added it -- I know blogger has the quotes, but I want the code at least on a box with a monospaced font).

Friday, December 07, 2012

Python tricks: making sure a function is only called once

Sometimes I want a function to be called only a single time (there are many use-cases, but specifically this time I wanted to change the way the Python garbage collection worked when dealing with Qt and threads).

Anyways, usually I did that setting some flag so that the second time a function is called, it'd check that flag and would skip the function in the second time.


After tinkering a bit about it, I came with a shorter version changing the function code which I thought is pretty nice:

 def func():  
   print 'Calling func only this time'  
   func.func_code = (lambda:None).func_code  


Now, calling it a second time will actually execute the lamda:None code.

Yes, I know you'll say it's cryptic, so, I'm including a decorator version below which does the same checking with a variable:

 @call_only_once  
 def func():  
   print 'Calling func only this time'  
 def call_only_once(func):  
   def new_func(*args, **kwargs):  
     if not new_func._called:  
       try:  
         return func(*args, **kwargs)  
       finally:  
         new_func._called = True  
   new_func._called = False  
   return new_func  

Thursday, December 06, 2012

Plugins in Eclipse to accompany PyDev

Below are some plugins which I believe may be very helpful for people installing Eclipse/PyDev (those are the plugins I usually install on any new Eclipse install).


1. StartExplorer: 

Details at https://github.com/basti1302/startexplorer

Mostly, I use it to open the current file in explorer or copy the current file path to the clipboard (but it has other niceties too).


2. Extended VS Presentation plugin for Eclipse

Details at: http://andrei.gmxhome.de/skins/index.html

I use it for skinning Eclipse (i.e.: providing a better look and feel), but note it's only for Eclipse 3.x (Eclipse 4.x has a skinning engine builtin).


3. Eclipse Color Themes

Details at: http://eclipsecolorthemes.org

Note that if you're using the Aptana Studio editors, you don't really need this plugin as Aptana Studio itself has a theming feature which supersedes this, but if you're only on Eclipse/PyDev and other editors, this may be a nice addition so that you can apply the same colors for several editor plugins at once.


4. Practically Macro

Details at: https://sourceforge.net/projects/practicalmacro

Yes, I know, Eclipse does not have macro record/playback by default and it's a major shortcoming. Well, this plugin does cover most of the use-cases I have for doing macro record/playback (although it does have some weirdness sometimes -- in which case I usually just start notepad++ editor just for this feature).


5. EGit

Details at: http://wiki.eclipse.org/EGit/User_Guide

Note that Aptana Studio has its own Git integration (so, when I'm in Aptana Studio I don't usually install EGit). Although it can do many things with Eclipse, I use the Eclipse integration (either from EGit or Aptana Studio) mostly to have a quick way to know which files I've changed and sometimes seeing the history for a given file. For most of my work I like to work on the shell, usually using a tool I wrote in Python: https://github.com/fabioz/mu-repo which helps managing many git repositories at once from a shell (and showing differences I can edit via WinMerge) -- and sometimes I even fire http://code.google.com/p/gitextensions for exploring some git repository.

I was thinking a bit about this one since in cvs and svn I did everything inside Eclipse, but when it comes to git this trend didn't continue. I think it's mostly because the major thing for me is that the synchronize view wasn't available to me on cvs/svn and the EGit synchronize view is not as streamlined/fast as the other integration -- as I have the habit of reviewing all the code I'm about to update, and as EGit made that process a bit slower (and git is pretty easy to extend with scripting on top of it), I just went a different way this time (but who knows, if EGit provides a more streamlined/faster synchronize view in the future for my modus-operandi I may switch back to only Eclipse here -- but it'd have to beat the time in which I do things in mu-repo which fetches/diffs lots of repositories in parallel in a pretty fast way, so, I'm not sure how feasible that is).