Search Results: "js"

20 December 2009

Daniel Stone: don't be evil

'I give permission for IBM, its customers, partners, and minions, to use JSLint for evil.'

Romain Francoise: Defining evil

How exactly are these packages DFSG-free? (via, via)

17 December 2009

C.J. Adams-Collier: IRC logs for #ubuntu-us-wa

Hello, google. I would like to introduce you to our chat logs. Chat logs, google. Google, chat logs. We will discuss things here such as Mono, GNOME and Debian. We may even use it to talk about work on the DLR project stuff.
<script>//<script language="javascript" src="http://reddit.com/button.js?t=1"></script>

10 December 2009

Kartik Mistry: foss.in/2009: Report from lazy man


* Yes. I m kicking myself for being lazy and not doing stuffs that I supposed to do before, during and after foss.in/2009. I had expected too much that never happened but something too good happened that I wasn t able to imagine. foss.in/2007 was my last foss.in visit where we had lots of fun. Really. But, along with that certain elements (ie Real Life) made it hard to let me enjoy that. Same happened during 2008. Pity. I missed KDE Song and what not.. But, this year I determined and kicked myself several times. Real Life was kind of in happy mood. foss.in team helped me to figure out travel issues. So, I was all set. All days were filled with fun, much better involvement (& RTFM) with Debian and then my small talk at KDE PoTD was surprise to me (and also to that Projector that never worked with my Macbook). I ve made some cool friends Ramkumar, Siddhesh, Shreyank, Rahul Sundaram and many more from Pai hotel discussion group! For those who missed my stupid brown humor and PJs next time. C ya at foss.in/2010! And yes, I took only two pictures during entire conference. But, fossdotin flickr or picasa tag will say you what kind of fun we had.

4 December 2009

Russell Coker: Testing Noise Canceling Headphones

This evening I tested some Noise Canceling Headphones (as described in my previous post [1]). I first tried the ones on sale at Brookstone [2], they were the on the ear type so there was never a chance that I would buy them but they seemed like good ones to test. I wore them for about 10 minutes while I walked around the store looking at all the electronic stuff that s on sale. I noticed that they were much more effective at filtering low frequencies and regular sounds. So for the Christmas music that was playing the music was mostly filtered just leaving the sound of the singing. Also I was able to talk to the guy who worked there and hear him clearly when the noise canceling was turned on this can be considered a bug or a feature depending on your planned use. When I listened to electric fans the sound of the buffeting air was filtered just leaving the high pitched bearing noise. It is well documented that there is a hissing sound from noise canceling headphones and sometimes a feeling of pressure. I didn t hear any hissing but it did feel a little different when I turned on the noise canceling. After 10 minutes I didn t feel in any way uncomfortable, so I could probably survive an entire flight while wearing such headphones. I can highly recommend the customer service at the Brookstone store in Menlo Park. The guy who was working there was totally helpful, even by US standards his customer service was really good. Sometimes when you make an unusual request (such was wanting to try the merchandise for an extended period of time) the staff aren t particularly enthusiastic, but I had no problems at Brookstone! After Brookstone I went to a Bose store and tried the Quiet Comfort 15 noise canceling headphones [3]. The Bose store conveniently had a device configured to emulate the sound of a jet engine to demonstrate how the QC15 stopped that. I was quite impressed with that. I did feel that the QC15 was a little light for my taste, I would rather have something bigger and heavier with thicker padding to improve the passive resistance to sound. But I expect that many people would like it to be small and light as it s designed for travel. I visited a Sony store a couple of times, but no-one seemed able to serve me. I ll go there again some time when they are less busy. Finally I have to note that I have received a significant number of comments suggesting ear-bud type devices. I suggest that anyone who doesn t mind wearing such things should consider ear-bud type devices. But as I can t stand such things I will continue my search for over-ear headphones. I may end up just buying the Bose QC15, they seem to be good enough and not really expensive.

2 December 2009

Russell Coker: Noise Canceling Headphones

My patience with the noise of airlines has run out, on my trip from AU to US I didn t get any sleep due to the cramped seat and the noise of the plane. While I can t do anything about the cramped seat without spending a lot of money it seems that I can do something about the noise with moderate expense. I ve been researching Noise Canceling Headphones [1]. The principle of such devices is that they have a microphone on the outside and a speaker on the inside to generate sound that is 180 degrees out of phase which will then almost cancel out the ambient noise. Apparently such devices are very effective for low frequencies but less effective for high frequencies. High frequencies are more easily blocked by sound insulation, so the ideal seems to be around the ear headphones with lots of padding to passively stop noise with active noise canceling to deal with the lower frequencies. So I m now planning on buying a set of headphones before I leave the US. Choice Magazine (an Australian independent product review organisation) published a review of noise canceling headphones in 2007, it has some interesting information but is not suitable for buying advice today [2]. Choice gave the best results to the Jabra C820s which had just gone out of production when they published the review and by now could only be bought on eBay. The Jabra had an active cancellation of 14.3dB and a passive cancellation of 8.3dB. The best active cancellation of all the reviewed products was 19.5dB for the Bose QuietComfort 3 which incidentally only had a passive cancellation of 4.8dB. Both the Bose and Jabra products got good reviews in a mailing list discussion. It s a pity that Jabra is now only manufacturing products for call centers. I am not considering the headphones that go on top of the ears, they will inherently give less passive protection due to the design and they will annoy me. I am also not considering the ear-buds because I don t like putting things in my ears. I will note that there are some very positive reviews of some of the ear-bud devices. The Etymotic Research devices get very good reviews and are apparently on sale at reasonable prices in Apple stores (among other places) [3]. Anyone who wants noise-canceling headphones and disagrees with me about the desirability of ear-bud type devices should probably consider them. The Bose QuietComfort 15 is selling for $300 (NB for this post all prices will be in US dollars) [4]. It has microphones both inside and outside the ear cup to allow better detection of ambient sound. A single AAA battery is supposed to last 35 hours, it has a detachable audio cable (for use in just blocking noise), and comes with an airline adapter (for the two-port airline sockets). It does require being turned on to listen to audio, some headphones allow you to turn off the noise canceling feature to listen to music without a battery this doesn t matter for my planned use. They have a volume switch (low and high settings) to cope with airlines that set the volume too high. They are specifically designed for passengers in commercial jet aircraft. Surprisingly the Bose web site doesn t mention the number of dB of audio protection and none of the reviews I have read have mentioned it either. The store Brookstone was recommended, they have some unbranded noise canceling headphones, but as they are on the ear and more expensive than comparable Sony products ($130 vs $100) I eliminated them quickly. Sony has a good range of noise-canceling headphones [5]. They have ear-buds starting at $90 and on-ear headphones for as little as $50. They have two models of over the ear headphones that are advertised at $200 and $400. The MDR-NC60 costs $200 and reduces noise by 12dB at 200Hz while the MDR-NC500D costs $400 and reduces noise by 20dB at 160Hz. I don t know why they didn t measure both headphones at the same frequency or give any information on passive sound insulation. They state that the MDR-NC500D was voted as being better than the Bose QC2 and QC3 but made no such claim about the MDR-NC60 presumably the older Bose devices were rated as better than the MDR-NC60, and I have to wonder about how the Bose QC15 would compare to the MDR-NC500D. The MDR-NC500D has an internal Lithium-Ion battery that lasts 16 hours and can take a pair of AA batteries as well for a total of 28 hours. The Sennheiser PXC 350 claims up to 32dB of passive attenuation and up to 18dB of active noise compensation [6]. Their claims about NoiseGuard (TM) cause me to lack confidence in their products. The PXC 350 is advertised at $330 and the reviews that I have read suggest that the Bose might be a better product. Sennheiser also has PXC 450 which offers 23dB of active noise compensation and costs $450. I am not going to pay $450 for headphones. It seems that the choice for over the ear noise canceling headphones comes down to the Sony MDR-NC60 at $200 and the Bose QuietComfort 15 at $300. I have the impression that the Bose product is better, but whether it is $100 better is the question. Also while I haven t forgiven Sony for Rootkitting their customers [7], this is not going to prevent me from buying the headphones that best suit my needs. Does anyone have any suggestions? Did I miss a good brand that I should be considering? Does Sennheiser have some redeeming features that I missed?

27 November 2009

Steve Kemp: I work alone like you. We always work alone.

A couple of days ago I was lamenting the state of webstats, although I was a little vague as to my purpose. Specifically I was wanting to find out about the screen resolutions and user-agents viewing a couple of sites. To get screen resolutions you really need to inject javascript into your pages, which is icky. Still its a small price to pay, and chances are most people won't notice. Of course there are drawbacks:
Javascript dependency.
If the visitors don't use/enable javascript you see nothing.
You cannot capture everything.
e.g. HTTP status code isn't available.
To solve this problem completely you therefore need to have access to both your apache logs and your javascript-captured information. Probably. As a proof of concept I've injected the following javascript into most pages of three sites. This code: The script that receives the data writes out the data to a small per-domain SQLite database, which I can then use to generate prettyness. However I suck at being pretty, in most ways, so I've only got functional: All of this is dynamic and most of the data is anchored to "today", as thats proof of concept enough. Were piwik not written in vile PHP I'd use that - I don't see anything similar out there which is Perl.. The big decision is now "Keep it dynamic" vs. "Output static pages". (vs. call off the experiment now I know that I'm safe to assume "big resolutions"). (Naming software is hard. Recent stuff I've done has had an skx prefix primarily for google-juice. e.g. Randomly I notice that if you search for my personal site on Google's UK engine I come top. Cool.) ObSubject: The Bourne Identity

21 November 2009

Biella Coleman: How Far Can it Go?

During the month of October I spent quite a bit of time thinking about the past, present, and future of F/OSS. This was due in part to participation in a Berkman Center event on Free Culture, where we discussed the historical arc of Free Software to Free Culture, the relationships between them (and their differences), and also the content and meaning each. Over the years, what I have found so interesting about Free Software is how it left its enclave to inspire countless groups into rethinking the politics and ethics of production and access and yet, as I raised in this pod-cast interview (due to the prompting of my interviewer, Elizabeth Stark), Free Software and/or Free Culture is still pretty bounded and contained phenomenon especially when compared to something like the existing consciousness over the environmental movement, which many folks know about and understand even when and if they are not involved in doing anything for the movement. I always ask my first year students whether they know what Free Software or Free Culture is and 9 out 10 stare at me with those blank eyes that basically speak in silence: no. Now, there are a group of activists, many located in Europe, a number of them with deep roots in the social justice movement who are taking Free Culture down a different path, trying to expand its meaning and conjoin it to social justice issues, build a broad set of coalitions across the political spectrum so as to override the fragmentation that is so characteristic to contemporary political moment, and use FC as an opportunity to critique the market fundamentalism of the last few decades. If you are interested in these issues, take a look at their charter: they are looking for comments (critical and constructive) as well as endorsements (here is the long version). I myself have a few comments, for example, I think it is worth noting something like the limits of what FC can do, that even if in many ways it can be activated to do good in the world, it is also best to highlight in the same swoop that FC is not some political panacea and has limits. For example some groups in the world, notably some indigenous communities abide by a different logic of access and culture, whereby full access is not culturally or ethically desirable, as the work of Kim Christen has illuminated. I also wonder in what ways issues of labor might be addressed more forcefully, and though they briefly raise the question of environmental sustainability, it is worth expanding these more directly and deeplyas this article by Toby Miller and Richard Maxwell make clear. There is more to say but I will leave it here for now and just say it is really great to see Free Culture taken down another political path that is rooted in coalition building.

Biella Coleman: How Far Can it Go?

During the month of October I spent quite a bit of time thinking about the past, present, and future of F/OSS. This was due in part to participation in a Berkman Center event on Free Culture, where we discussed the historical arc of Free Software to Free Culture, the relationships between them (and their differences), and also the content and meaning each. Over the years, what I have found so interesting about Free Software is how it left its enclave to inspire countless groups into rethinking the politics and ethics of production and access and yet, as I raised in this pod-cast interview (due to the prompting of my interviewer, Elizabeth Stark), Free Software and/or Free Culture is still pretty bounded and contained phenomenon especially when compared to something like the existing consciousness over the environmental movement, which many folks know about and understand even when and if they are not involved in doing anything for the movement. I always ask my first year students whether they know what Free Software or Free Culture is and 9 out 10 stare at me with those blank eyes that basically speak in silence: no. Now, there are a group of activists, many located in Europe, a number of them with deep roots in the social justice movement who are taking Free Culture down a different path, trying to expand its meaning and conjoin it to social justice issues, build a broad set of coalitions across the political spectrum so as to override the fragmentation that is so characteristic to contemporary political moment, and use FC as an opportunity to critique the market fundamentalism of the last few decades. If you are interested in these issues, take a look at their charter: they are looking for comments (critical and constructive) as well as endorsements (here is the long version). I myself have a few comments, for example, I think it is worth noting something like the limits of what FC can do, that even if in many ways it can be activated to do good in the world, it is also best to highlight in the same swoop that FC is not some political panacea and has limits. For example some groups in the world, notably some indigenous communities abide by a different logic of access and culture, whereby full access is not culturally or ethically desirable, as the work of Kim Christen has illuminated. I also wonder in what ways issues of labor might be addressed more forcefully, and though they briefly raise the question of environmental sustainability, it is worth expanding these more directly and deeplyas this article by Toby Miller and Richard Maxwell make clear. There is more to say but I will leave it here for now and just say it is really great to see Free Culture taken down another political path that is rooted in coalition building.

20 November 2009

C.J. Adams-Collier: building unmodified_drivers

This is the gist of it: $ cd /usr/src/
# $ sudo chmod a+rwx .
$ wget ftp://ftp.suse.com/pub/projects/kernel/kotd/SLE11_BRANCH/src/kernel-source-2.6.27.39-0.0.0.25.15a4c6f.src.rpm
$ alien -tg kernel-source-2.6.27.39-0.0.0.25.15a4c6f.src.rpm
$ cd kernel-source-2.6.27.39
$ tar xfj linux-2.6.27.tar.bz2
$ for f in patches.*.tar.bz2; do
tar xfj $f break;
done
$ for p in $(./guards x86_64 < series.conf); do
patch -d linux-2.6.27 -p1 < $p break
done
$ cd linux-2.6.27
$ fakeroot make-kpkg debian
$ fakeroot make-kpkg build
$ sudo make install modules_install
$ cd /usr/src
$ hg clone http://xenbits.xen.org/xen-unstable.hg
$ cd xen-unstable.hg/unmodified_drivers/linux-2.6
$ XEN=/usr/src/xen-unstable.hg/xen XL=/usr/src/kernel-source-2.6.27.39/linux-2.6.27 ./mkbuildtree x86_64
$ make -C /usr/src/kernel-source-2.6.27.39/linux-2.6.27 M=$PWD modules
$ sudo make -C /usr/src/kernel-source-2.6.27.39/linux-2.6.27 M=$PWD modules_install
<script>//<script language="javascript" src="http://reddit.com/button.js?t=1"></script>

13 November 2009

C.J. Adams-Collier: Xen PV network driver

I haven t used Xen HVM until recently. When I was at Amazon and
hanging with the Xen provisioning folks, I recall complaints about the
performance of network drivers on HVM instances. I ve recently
discovered that this was due to the use of the ioemu virtual interface
(vif) system. In paravirtualized environments, Xen vif devices are
more efficient because the guest kernel can talk to the hypervisor to
schedule I/O. In hardware virtualized environments, the hypervisor
emulates the back end of a common network driver and the guest uses it
as if it is the real thing. The Xen team (or was it RedHat?) patched the 2.6.18 kernel such that
HVM guests got the best of both worlds. The guest ran in a HVM
environment, but also had a way of talking with the hypervisor by way
of the xen-vnif kernel driver
(kernel/drivers/xenpv_hvm/netfront/xen-vnif.ko). I may not be looking in the right places, but I can t seem to find
such a paravirtualized network driver for any kernels more recent than
2.6.18. This has recently become a bit of an issue, since karmic (and probably sid)
depends on udev 145, which depends on signalfd, and thus won t run on
kernels before (something like) 2.6.25. Unless I miss my guess (which is quite possible =]), this means one of
the following needs to happen: Has this already happened? Am I missing something?
<script>//<script language="javascript" src="http://reddit.com/button.js?t=1"></script>

11 November 2009

Yves-Alexis Perez: Key transition (this is _not_ a meme)

Ok, so following the trend, I created some time ago a new GPG key, which I'm now transitioning too. I've set up a transition document, available at http://molly.corsac.net/~corsac/key-transition.txt. It's signed by both the old and the new keys and is reproduced below:
-----BEGIN PGP SIGNED MESSAGE-----
Hash: RIPEMD160,SHA512
Wed, 11 Nov 2009 13:44:05 +0100
I've recently set up a new RSA-based GPG key, and will be transitioning away
from my old DSA-based one.  The old key will be revoked soon, so I prefer all
future correspondence to use the new one.  I would also like to ensure that
this new key is well-integrated into the web of trust.  This message is signed
by both keys to certify the transition.
The old DSA key was:
pub   1024D/C5C05BAE 2004-11-11
      Key fingerprint = DE26 2FC4 7097 FFC6 DE2C  D8C0 4D44 C020 C5C0 5BAE
The new RSA key is:
pub   4096R/71EF0BA8 2009-05-06
      Key fingerprint = 4510 DCB5 7ED4 7040 60C6  6476 3055 0F78 71EF 0BA8
If you already know my old key, you can verify that the new key is
signed by the old one:
  gpg --check-sigs 71EF0BA8
If you don't already know my old key, or if you're extra-paranoid, you
can check the fingerprint against the one given above:
  gpg --fingerprint 71EF0BA8
If you have previously signed my old DSA key, and if you're satisfied
that you've got the correct new RSA key, then I'd appreciate it if you
would sign my new key as well:
  caff 71EF0BA8
The caff program is in the signing-party package in Debian.  Please be careful
to generate signatures that don't rely on the weakening SHA-1 hash algorithm,
which requires some careful configuration even if you've already configured
gpg correctly.  See http://www.gag.com/bdale/blog/posts/Strong_Keys.html for
the gory details.
Thanks,
- --
Yves-Alexis Perez
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
iEYEAREDAAYFAkr6sqQACgkQTUTAIMXAW64HiACeIyabQueDHAeiAX8EkIeApiDj
++UAn2z7YkjHx0lQh0+s5WdhikG0YztiiQIcBAEBCgAGBQJK+rKkAAoJEDBVD3hx
7wuodUcQAKMbG9Rehxz+uZ6fST99cHt5Fjnv9TorY4hQaQK+85ZgiwPaHMHfYM1G
5hcrXI+JFUpz8j40deZuaWuspOdHBHwnHNQril8MqT0CJgtB6HFTo+w/7Lmmui5M
DDMMed39UJl7bF73hV9ywGecxPpeh+dtoVnh0VT16uK2xTvW6ICEZgaPw1xfPUHS
+jxQ7I05X1OWQkPpmhxXJqGclDyO+qx4CJZsOxUAvt2LphHxhZxB3QE5OUdudGKQ
AH6KhC4rpNQdJVMX20SG8PybL/AipN3Y8N/63VkoqVC2heRlaQ69HjsuqIAkIyan
hHnqmJH8Q+TDTbdKZvOQv6jcd4o3VSibz0T9MwnOfqQ0uRYyTpaXC0vLUH6lXaC4
eK+VVWbY8vCAFHR3h80Q61i2me2HU5ly7a/W22dz19zzDNNC5q9MO78uIYkUK78N
Z0wzJrmOxRyhvs5DOSOpNVlXZhffNQM1f42xxG8cUDaIf7pR5jK+xqHV7tIBQE1D
CrD0mt+YQCnngK0i4wQTO7VT/vjypf4A9W+VSsoJJpRhBbngU4pHu9JWqO84/7AA
j5FN8ug15MWysaS+FQ/EqzHmT7BGBWaTPv3yGlHKUjx0w4bPEpbH7y3fwHAcmOFf
xFRzvZFQ03zeer06yAqTVNuwr77HZgrCzgyQVgIkegAg6iUPiZcs
=CBT+
-----END PGP SIGNATURE-----

9 November 2009

Joey Hess: king kong vs godzilla from a mouse's perspective

In Ubuntu Server Edition 9.10: No hardware required, Matt Zimmerman announces that from now on, "every release of Ubuntu Server Edition is simultaneously available on EC2". Amazon's EC2 documentation says: "the ability to create and publish kernels and ramdisks is restricted to Amazon EC2 and selected vendors". Canonical appears to be one of those vendors. Their newest EC2 AMI's contain modules from an Ubuntu build of linux-xen (2.6.27-23). Eric Hammond, who has been for a while making both Ubuntu and Debian images for EC2 says
Historically on EC2, neither Debian nor Ubuntu have had completely Debian and Ubuntu stacks from the kernel up. Instead, we've had to make do with patching the runtime on top of older kernels (2.6.16, 2.6.18, 2.6.21) built for other distros (Fedora Core). Amazingly, we've managed to hold this together and keep it running well for a couple years on EC2.
He goes on to describe current problems with eg, Debian's new udev version and the available EC2 kernels. Furthermore, anticipating today's news:
When the point comes where I am not publishing the base Ubuntu server AMIs, it will not make sense for me to publish new Debian AMIs either.
Those wanting to run Debian on EC2 will be stuck with duct-taping together Debian with the available kernels. Maybe I'm wrong. Maybe Ubuntu is actually working with Debian's kernel team, and will be letting them use Canonical's access to publish AKI's of official Debian kernels. Or maybe Ubuntu is working with Debian's kernel team to include identical linux-xen kernel in Debian, so the Ubuntu AKI's could be used. But appearances are that this is another case where Ubuntu has managed to take a situation that was less than ideal for all concerned, and turn it into an advantage for Ubuntu, while at the same time being a unfixable loss for Debian. My mouse's perspective is that a) we maybe only have so many losses left in us (altho we did get thru that whole dinosaur thing ok!) and b) King Kong is still oddly dependent on his mammilian heritage to be up there with his head in the cloud, tearing at Godzilla and stamping on us.

4 November 2009

Enrico Zini: Custom function decorators with TurboGears 2

Custom function decorators with TurboGears 2 I am exposing some library functions using a TurboGears2 controller (see web-api-with-turbogears2). It turns out that some functions return a dict, some a list, some a string, and TurboGears 2 only allows JSON serialisation for dicts. A simple work-around for this is to wrap the function result into a dict, something like this:
@expose("json")
@validate(validator_dispatcher, error_handler=api_validation_error)
def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
    # Call API
    res = self.engine.list_colours(filter, productID, maxResults)
    # Return result
    return dict(r=res)
It would be nice, however, to have an @webapi() decorator that automatically wraps the function result with the dict:
def webapi(func):
    def dict_wrap(*args, **kw):
        return dict(r=func(*args, **kw))
    return dict_wrap
# ...in the controller...
    @expose("json")
    @validate(validator_dispatcher, error_handler=api_validation_error)
    @webapi
    def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
        # Call API
        res = self.engine.list_colours(filter, productID, maxResults)
        # Return result
        return res
This works, as long as @webapi appears last in the list of decorators. This is because if it appears last it will be the first to wrap the function, and so it will not interfere with the tg.decorators machinery. Would it be possible to create a decorator that can be put anywhere among the decorator list? Yes, it is possible but tricky, and it gives me the feeling that it may break in any future version of TurboGears:
class webapi(object):
    def __call__(self, func):
        def dict_wrap(*args, **kw):
            return dict(r=func(*args, **kw))
        # Migrate the decoration attribute to our new function
        if hasattr(func, 'decoration'):
            dict_wrap.decoration = func.decoration
            dict_wrap.decoration.controller = dict_wrap
            delattr(func, 'decoration')
        return dict_wrap
# ...in the controller...
    @expose("json")
    @validate(validator_dispatcher, error_handler=api_validation_error)
    @webapi
    def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
        # Call API
        res = self.engine.list_colours(filter, productID, maxResults)
        # Return result
        return res
As a convenience, TurboGears 2 offers, in the decorators module, a way to build decorator "hooks":
class before_validate(_hook_decorator):
    '''A list of callables to be run before validation is performed'''
    hook_name = 'before_validate'
class before_call(_hook_decorator):
    '''A list of callables to be run before the controller method is called'''
    hook_name = 'before_call'
class before_render(_hook_decorator):
    '''A list of callables to be run before the template is rendered'''
    hook_name = 'before_render'
class after_render(_hook_decorator):
    '''A list of callables to be run after the template is rendered.

    Will be run before it is returned returned up the WSGI stack'''
    hook_name = 'after_render'
The way these are invoked can be found in the _perform_call function in tg/controllers.py. To show an example use of those hooks, let's add a some polygen wisdom to every data structure we return:
class wisdom(decorators.before_render):
    def __init__(self, grammar):
        super(wisdom, self).__init__(self.add_wisdom)
        self.grammar = grammar
    def add_wisdom(self, remainder, params, output):
        from subprocess import Popen, PIPE
        output["wisdom"] = Popen(["polyrun", self.grammar], stdout=PIPE).communicate()[0]
# ...in the controller...
    @wisdom("genius")
    @expose("json")
    @validate(validator_dispatcher, error_handler=api_validation_error)
    def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
        # Call API
        res = self.engine.list_colours(filter, productID, maxResults)
        # Return result
        return res
These hooks cannot however be used for what I need, that is, to wrap the result inside a dict. The reason is because they are called in this way:
        controller.decoration.run_hooks(
                'before_render', remainder, params, output)
and not in this way:
        output = controller.decoration.run_hooks(
                'before_render', remainder, params, output)
So it is possible to modify the output (if it is a mutable structure) but not to exchange it with something else. Can we do even better? Sure we can. We can assimilate @expose and @validate inside @webapi to avoid repeating those same many decorator lines over and over again:
class webapi(object):
    def __init__(self, error_handler = None):
        self.error_handler = error_handler
    def __call__(self, func):
        def dict_wrap(*args, **kw):
            return dict(r=func(*args, **kw))
        res = expose("json")(dict_wrap)
        res = validate(validator_dispatcher, error_handler=self.error_handler)(res)
        return res
# ...in the controller...
    @expose("json")
    def api_validation_error(self, **kw):
        pylons.response.status = "400 Error"
        return dict(e="validation error on input fields", form_errors=pylons.c.form_errors)
    @webapi(error_handler=api_validation_error)
    def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
        # Call API
        res = self.engine.list_colours(filter, productID, maxResults)
        # Return result
        return res
This got rid of @expose and @validate, and provides almost all the default values that I need. Unfortunately I could not find out how to access api_validation_error from the decorator so that I can pass it to the validator, therefore I remain with the inconvenience of having to explicitly pass it every time.

24 October 2009

Gustavo Noronha Silva: GNOME Shell for Debian

Over the last few days I have worked for some hours on packaging the last dependency of GNOME Shell that was missing in Debian: gjs. That work has been sponsored by Collabora, along with the work required to package GNOME Shell itself. I was very impressed by the time it took for FTP Masters and Assistants to deal with the new packages - it only took a couple days for each; kudos! What this all means is that you can now easily test GNOME Shell, and even make it your default environment on a Debian unstable system, by just installing the gnome-shell package. As I expected, some people have been having trouble with the new package, but the general feedback has been fairly positive. If the README.Debian package doesn t help you with your specific issue, do take the time to file a bug report! By the way, thanks go to Joss, for his work on dh_girepository, and for him, and Sebastian Dr ge for their work on creating the new GObject Introspection policy.

15 October 2009

Enrico Zini: Building a web-based API with Turbogears2

Building a web-based API with Turbogears2 I am using TurboGears2 to export a python API over the web. Every API method is wrapper by a controller method that validates the parameters and returns the results encoded in JSON. The basic idea is this:
@expose("json")
def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
    # Call API
    res = self.engine.list_colours(filter, productID, maxResults)
    # Return result
    return res
To validate the parameters we can use forms, it's their job after all:
class ListColoursForm(TableForm):
    fields = [
            # One field per parameter
            twf.TextField("filter", help_text="Please enter the string to use as a filter"),
            twf.TextField("productID", help_text="Please enter the product ID"),
            twf.TextField("maxResults", validator=twfv.Int(min=0), default=200, size=5, help_text="Please enter the maximum number of results"),
    ]
list_colours_form=ListColoursForm()
#...
    @expose("json")
    @validate(list_colours_form, error_handler=list_colours_validation_error)
    def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
        # Parameter validation is done by the form
        # Call API
        res = self.engine.list_colours(filter, productID, maxResults)
        # Return result
        return res
All straightforward so far. However, this means that we need two exposed methods for every API call: one for the API call and one error handler. For every API call, we have to type the name several times, which is error prone and risks to get things mixed up. We can however have a single error handler for all methonds:
def get_method():
    '''
    The method name is the first url component after the controller name that
    does not start with 'test'
    '''
    found_controller = False
    for name in pylons.c.url.split("/"):
        if not found_controller and name == "controllername":
            found_controller = True
            continue
        if name.startswith("test"):
            continue
        if found_controller:
            return name
    return None
class ValidatorDispatcher:
    '''
    Validate using the right form according to the value of the "method" field
    '''
    def validate(self, args, state):
        method = args.get("method", None)
    # Extract the method from the URL if it is missing
        if method is None:
            method = get_method()
            args["method"] = method
        return forms[method].validate(args, state)
validator_dispatcher = ValidatorDispatcher()
This validator will try to find the method name, either as a form field or by parsing the URL. It will then use the method name to find the form to use for validation, and pass control to the validate method of that form. We then need to add an extra "method" field to our forms, and arrange the forms inside a dictionary:
class ListColoursForm(TableForm):
    fields = [
            # One hidden field to have a place for the method name
            twf.HiddenField("method")
            # One field per parameter
            twf.TextField("filter", help_text="Please enter the string to use as a filter"),
    #...
forms["list_colours"] = ListColoursForm()
And now our methods become much nicer to write:
    @expose("json")
    def api_validation_error(self, **kw):
        pylons.response.status = "400 Error"
        return dict(form_errors=pylons.c.form_errors)
    @expose("json")
    @validate(validator_dispatcher, error_handler=api_validation_error)
    def list_colours(self, filter=None, productID=None, maxResults=100, **kw):
        # Parameter validation is done by the form
        # Call API
        res = self.engine.list_colours(filter, productID, maxResults)
        # Return result
        return res
api_validation_error is interesting: it returns a proper HTTP error status, and a JSON body with the details of the error, taken straight from the form validators. It took me a while to find out that the form errors are in pylons.c.form_errors (and for reference, the form values are in pylons.c.form_values). pylons.response is a WebOb Response that we can play with. So now our client side is able to call the API methods, and get a proper error if it calls them wrong. But now that we have the forms ready, it doesn't take much to display them in web pages as well:
def _describe(self, method):
    "Return a dict describing an API method"
    ldesc = getattr(self.engine, method).__doc__.strip()
    sdesc = ldesc.split("\n")[0]
    return dict(name=method, sdesc = sdesc, ldesc = ldesc)
@expose("myappserver.templates.myappapi")
def index(self):
    '''
    Show an index of exported API methods
    '''
    methods = dict()
    for m in forms.keys():
        methods[m] = self._describe(m)
    return dict(methods=methods)
@expose('myappserver.templates.testform')
def testform(self, method, **kw):
    '''
    Show a form with the parameters of an API method
    '''
    kw["method"] = method
    return dict(method=method, action="/myapp/test/"+method, value=kw, info=self._describe(method), form=forms[method])
@expose(content_type="text/plain")
@validate(validator_dispatcher, error_handler=testform)
def test(self, method, **kw):
    '''
    Run an API method and show its prettyprinted result
    '''
    res = getattr(self, str(method))(**kw)
    return pprint.pformat(res)
In a few lines, we have all we need: an index of the API methods (including their documentation taken from the docstrings!), and for each method a form to invoke it and a page to see the results. Make the forms children of AjaxForm, and you can even see the results together with the form.

11 October 2009

C.J. Adams-Collier: A quick update I m a grad student!

Hey all! I m sorry I haven t been very active with my packages recently. I all-of-a-sudden started grad school and have been swamped with studying. I also started a contract and have been busy trying to learn a new codebase while contributing something other than snark. I promise I ll get back to packaging IronRuby and IronPython on Mono for Debian as soon as things start settling down. Getting an A in the class is higher priority, though, sorry Don t worry. I haven t forgotten about you ;) Cheers, C.J. PS, I am implementing a Perl library to exercise my understanding of the class. You can follow along at the search.cpan.org page for Lingua::HPSG or by cloning the git repo: $ git clone git://karma.colliertech.org/colliertech/langparser
<script>//<script language="javascript" src="http://reddit.com/button.js?t=1"></script>

27 September 2009

Francois Marier: OpenStreetMap/OpenLayers and Privoxy

I have been meaning to switch to OpenStreetMap for a while now, but the fact that it didn't work with Privoxy was holding me back. I don't enjoy surfing the web without protection and Privoxy is one of the most convenient ways of enhancing one's browsing experience on Debian and Ubuntu.

So I decided to spend some time trying to figure out what was wrong. If you want to skip the details and just get the fix, scroll down to the bottom of this post for the solution.

Finding all affected URLsIn order to get a list of all of the URLs that Privoxy filters when one visits the front page of OpenStreetMap, I did the following:

Comparing the filesArmed with the list of all affected URLs, I downloaded them through Privoxy using wget into a privoxy/ directory:
$ http_proxy=localhost:8118 wget URL
Then I downloaded the same URLs without Privoxy into a noproxy/ directory:
$ http_proxy= wget URL
To find identical files, I ran md5sums in each directory:
md5sum *
After deleting all identical files, I was left with:
index.html
OpenLayers.js?1251388304
Which I diff'ed together:
colordiff -u noproxy/FILE privoxy/FILE
The first file, index.html did not have any relevant changes, but I noticed in the second one that a few of these
this.moveTo(this.position)
were replaced with
''.concat(this.position)
Searching for "concat" in /etc/privoxy/, I found that the "jumping-windows" filter was the culprit. After disabling it, all of the problems went away.

I have filed a bug upstream.

The SolutionHere's what you need to put in your /etc/privoxy/user.action:
 -filter jumping-windows 
.openstreetmap.org

16 September 2009

Benjamin Mako Hill: Order Without Law

Order Without Law is a fantastic book by Robert Ellickson published in 1991. In a way, the book is an in-depth case study of the irrelevance of law. Subtitled, "how neighbors settle disputes," Ellickson shows how people solve complicated problems in an archetypal area of liability law without knowledge of the law. Ellickson shows that even when people know exactly what the law says, they often ignore it in favor of community norms and, in his examples, models of "neighborliness." Specifically, the book is about how neighbors in northern California settle disputes related to damage caused by roaming cattle, how neighbors construct and share costs of fences, and how, although the law is frequently debated in relation to classifying land as either open or closed to free grazing, the law tends to take a back seat to unwritten norms in the way that problems are actually solved. There is order and a shared understanding of rules in Ellickson's account; it just has very little to do with the law. As part of his description, Ellickson goes into some detail about the types of damage that cattle cause. For example, Ellickson describes how bulls, will often break down barbed wire fences and go on rampages impregnating heifers, eating vast amounts of food, and destroying crops and equipment. When I was on a long bike trip through northern California a few weeks ago, I was sitting under a tree waiting for my cyling partner to catch up. A giant black bull nearby noticed me. Shorting, mooing, and shaking ribbons of slobber from its mouth, it lumbered toward me. Only a rather weak-looking barbed wire fence separated us. All I could think about was Order Without Law.

Isaac Jones: The Monad Reader, Issue 3

The Monad Reader is a monthly newsletter by Haskellers. From the announcement email: This month's issue has a definite introductory theme. It includes republished book reviews, notes on learning, a look at the differences between functional and object oriented programming, and distributed computation. As always, The Monad.Reader invites submissions on Haskell and related topics. Send a summary or abstract for your article to shae@ScannedInAvian.com -- Shae Matijs Erisson

Next.

Previous.