Today I’ve put the finishing touches on python-crontab 1.4. This release updates the tests and fixes a couple of bugs as well as two really interesting features.
The first is the ability to pull a log from a crontab or cronjob. When creating a crontab in the usual way you can specify a optional log file, if not specified the value ‘/var/log/syslog’ is substituted. The log attribute then provides you a filtered log view which limits the lines returned by the iterator to those attributed to the user your crontab controls. This is of course by default the ‘root’ user, but can be other users too.
Conversely each job in the crontab can return a log iterator which limits the retuned entries to those for this job only. This allows the programmer to tell when cron jobs were last run.
The second large feature is the scheduler. Using the croniter python module, this feature returns date/times when cron jobs would run from any given datetime offset. This allows the programmer to compile a list of datetimes when the job would run in the future and in the past. Use the schedule attribute from the cron job object.
I’ve written a script which I can use to get information about gobject introspection modules for use in python. It’s written in python and allows you to look at actual function names, actual object names and what really is going on.
This is mainly a problem because the documentation for Gtk with gi.repository is so poor and not clearly described that it makes it impossible to use without great force of will.
Hopefully this script can make the job easier for others, feel free to adapt it and post your remixes.
I’ve finished writing a new addon for xbmc (the tv media center for Ubuntu) called Librarian. She will take a look at your impressive video library and check for various inconsistencies and potential problems which you might want to look into. This 1.0 release includes the following features:
List Movie Files not Included in the Database
List Movies which have incorrect length, i.e. misidentified or corrupt (requires ffmpeg installed)
Lists TV Shop Episodes separately with both above features
Tells you which seasons and which episodes of each show you’re missing
Shows you which TV Show Paths are being ignored completely.
More checking can be added as good ideas come in, I’ve also written an addon module called xbmcdata which wraps sqlite3 the xbmc httpapi to give a consistant inside xbmc and outside testing/scripting interface. This makes addon development _much_ easier. For instance listing movies is now just a case of:
from xbmcdata import Movies
for movie in Movies():
print "%s (%s)" % (unicode(movie), movie['Year'])
One of the fun things to do with python is to use the language to bend the rules of programming. One neat way of using your resources wisely with objects is to create objects in the right places, but not generate or call costly data gathering operations until you absolutely need to.
So called ‘late data initialisation’ is useful in certain kinds of programs. I document here the best pattern I’ve found to turn a python list into a late data class:
print "Generating Now"
for x in range(42):
self.append( x )
self.populate = None
def __getitem__(self, key):
return super(newList, self.data).__getitem__(key)
return super(newList, self.data).__len__()
return super(newList, self.data).__iter__()
Basically populate can be any piece of code which calls what ever it needs in order to gather the data. It’ll only be called once and to prevent having to use an __init__ variable we just clobber the method attribute. Sneaky!
When the list is used for an iteration (for loop), or if you delve into it directly for a specific item, or need to know it’s length, then we can get the data behind our object and have it contained within the list object we’re inheriting. No need for secondary list object variables dangling off of self. Ugly! Although this pattern does require that every use you want to put the object to (i.e. string, representation, slicing, dicing, mincing or conditionalising) you’ll have to make a new super method to wrap around to make sure that the data is generated if that’s the first way the list will be used.
What are your thoughts about this pattern? Do you know how to fix the init issue with a better pattern?
The Genetic Wallpapers project is supposed to be able to help any artist create a wallpaper capable of shifting and moving over time to produce interesting and unique results over time.
The problem is that artists have all sorts of crazy ideas about what and how the wallpaper should progress and currently the logic for how the wallpaper will mutate is contained within the python code of the main project.
The alternative is to ask the community. But this is quite a highly specialised bit of functionality, very rarely do we need to run one bit of JIT code on another. But any ideas would be very welcome.
Comments and thoughts on the idea and the direction, please to post below.
"""Display a create user window"""
name = 'register'
primary = False
fields = [ 'postcode', 'age', 'gender', 'passphrase', 'computeruse' ]
def __init__(self, *args, **kwargs):
self.realname = kwargs.pop('real_name')
TranslatableFormWindow.__init__(self, *args, **kwargs)
intro = self.widget('label').get_label()
self.widget('label').set_label(intro % self.realname)
def cancel(self, widget, event=None):
if isinstance(widget, Gtk.Button) or (event and \
event.key.keyval == Gdk.KEY_Escape):
"""Return all the user entered data"""
result = self.field_data()
result['name'] = self.realname
While I’m not finished debugging it all, the idea is to be able to make Gtk apps which have a wizard style layout with minimum effort. Each page has validation checks (if you want) and standard signals which you can stick into glade and have next, back, cancel and destroy handled for you.
This code controls a 5 page registration window as so:
The scene is set, you have made a wonderfully useful dbus based service in python and you’re ready to serve interesting data in a desktop agnostic and thread safe fashion with fancy asyncronous calls and lovely event signalling. But woe! you have to write some tests1 and you find quite quickly that this would require you to have a running test service and even that won’t make your tests work.
Before I move into my blog entry showing the world how I solved this really tricky problem, I want to say that I did do due diligence and did extensive searches for existing solutions, modules, examples and so on. The little I found and the mass of questions and difficulties people have had testing their dbus services in python is a tribute to how different the python testing framework is to the dbus server/client requirements.2
In a shared base module that is used by both daemon and client modules: example code
This gives you session bus, root address and service address and all will be correct in context. The client module is very simple for me, just some helper functions: example code
The daemon module is as you would expect, a bunch of dbus.service.Object classes with an extra helper: example code
Then you’ll need a few bits for the test suite, a test base module that all test cases inherit example, a daemon service script which is run when tests are run example and finally a test suite with some tests example3.
As you can see you need a running service with a test address and a way to start and stop that service if it’s not already running. You also need to manage the gobject loops for testing signals from your dbus service and this is done using the much loved python threading module.
I hope these examples will prove useful to others.
1 Or had a requirement to write them prior to writing any code, depending on your method. 2 Do post a comment below if you know of other people’s examples and successes. 3 I’ve hacked this together from my project code to give example, it may not run.
I managed to port one of my libraries that I made way back from perl to python, the experience was quite interesting, although very tiring. I don’t think I can recommend perl again since the python just looks so much cleaner and there were whole sections I could remove because they were handled by python.
If your interested in data validation check out lp:~doctormo/doctormo-random/xsdvalidate and have a look at the tests, it’s basically a module similar to the existing xml.xsd but with a focus on python structures.
Because it’s a library few of you are going to know how to run the tests and have a dig around at what it can do. For those in the know, it’s got a structural error reporting mechanism which allows the code to know what failed to validate. In perl I was using this module hooked up to a django like framework which would be able to check if the form information was valid and which fields failed and how, this information was actually fed directly back to the template for human warnings so the entire process was automated to a frightening degree, you really didn’t need any code for most transactions.
I have a test suite but I could always do with more tests, if you find something it’s not covering let me know.