Archive for December 2011

pyjaco and jQuery

After giving up on CoffeeScript, I decided to play around with Pyjaco the Python to Javascript Compiler.

While the code is readable, there is very little in the way of end-user documentation. I hope to address this with this blog post. The Pyjaco examples all embed generated javascript in an html page. I needed a way to generate an external Javascript file as I would include in an HTML file. I also wanted to find out if I could use Pyjaco with jQuery.

The first step was to install a development version of Pyjaco:

git clone https://github.com/chrivers/pyjaco.git

Pyjaco normally requires a generated Javascript file mapping Python builtins to Javascript to be included with the created Javascripts. This must be generated:

cd pyjaco
python2 generate_library.py
cp py-builtins.js ~/pyjaco_test # directory for my new page

The next step was to create an HTML file that included jquery, the py-builtins.js script above, and a yet-to be defined javascript file named clicker.js that will be generated from a yet-to-be-defined python file. I also add a couple of DOM elements (a heading and paragraph) that are to be manipulated via jQuery:

<!DOCTYPE html>
<html>
<head>
<script type=”text/javascript” src=”jquery-1.6.4.min.js”></script>
<script type=”text/javascript” src=”py-builtins.js”></script>
<script type=”text/javascript” src=”clicker.js”></script>
</head>
<body>
<h1>Click me</h1>
<p id=”when_clicked”></p>
</body>
</html>

That’s the easy part. Writing python code that compiles to correct Javascript is the hard part. Pyjaco doesn’t currently provide very useful compile-time errors, and it also does not yet map javascript errors back to the input python.

There are (at least) two ways to compile python code in Pyjaco. The first, which is used in the Pyjaco examples, and appears to be the preferred method at this time is to create a custom main() method that uses various pyjaco.Compiler methods to combine the functions into a string of text. See https://github.com/chrivers/pyjaco/tree/devel/examples for three examples.

However, I was looking to have a complete python file that compiles to a complete javascript file. Pyjaco supports this as well, using the provided pyjs.py script. It took some investigating to understand how to reference javascript variables inside python functions. Decorator syntax is used to expose the variables for jQuery, Math.random, and Math.floor in the following example. The mystifying bit is that because we will be compiling this file to javascript as a string, it is not necessary (or possible) to import the JSVar decorator, as was done in the Pyjaco examples linked above.

# clicker.py
@JSVar("jQuery")
def ready():
    jQuery('h1').click(on_click)
 
@JSVar("jQuery", "Math.random", "Math.floor")
def on_click():
    if jQuery('#when_clicked').html():
        r = Math.floor(Math.random() * 255)
        g = Math.floor(Math.random() * 255)
        b = Math.floor(Math.random() * 255)
        color = "rgb(%d, %d, %d)" %(r,g,b)
        jQuery('#when_clicked').attr('style', 'background-color: ' + color)
    else:
        jQuery('#when_clicked').html("you clicked it!")
 
jQuery(ready)

Notice that I’m using the jQuery function instead of the $ alias, since $ is not a valid variable name in Python. This is a rather odd looking mix of Python and Javascript functions, but it works.

I had to repeat the compile and test step a few times before coming up with the above file. The script can be compiled using the pyjs.py that comes with the pyjaco source distribution (and, thanks to a simple patch I submitted, will come with the binary distribution in the next release.) Here’s how the script is run:

python2 ~/code/pyjaco/pyjs.py -N --output clicker.js clicker.py

The -N option tells pyjs not to generate the builtin library that we created manually in the first step.

This translation step creates a clicker.js file that looks like this:

var ready = function() {
    var __kwargs = __kwargs_get(arguments);
    var __varargs = __varargs_get(arguments);
    var $v1 = Array.prototype.slice.call(arguments).concat(js(__varargs));
    jQuery("h1").click(on_click);
return None;
}
var on_click = function() {
    var __kwargs = __kwargs_get(arguments);
    var __varargs = __varargs_get(arguments);
    var $v2 = Array.prototype.slice.call(arguments).concat(js(__varargs));
    if (bool(jQuery("#when_clicked").html()) === True) {
        var r = Math.floor((Math.random()) * (255));
        var g = Math.floor((Math.random()) * (255));
        var b = Math.floor((Math.random()) * (255));
        var color = str('rgb(%d, %d, %d)').PY$__mod__(tuple([r, g, b]));
        jQuery("#when_clicked").attr("style", ("background-color: ") + (color));
    } else {
        jQuery("#when_clicked").html("you clicked it!");
    }
return None;
}
jQuery(ready);

I find this rather unfortunately difficult to read. There is code for argument parsing that would not have been needed if I had hand-written javascript. Further the use of “mock” python builtins makes the javascript look less javascripty. However, the original python file looks much more readable than an equivalent javascript one would. I am hopeful that improvements to pyjaco will cause it to generate more readable javascript with less extraneous code.

The entire example can be found on my github fork

Christian Iversen is actively working on Pyjaco right now. I am excited about this project and hope that further community involvement will help it evolve into a practical and useful tool. I intend my next patch to be an autocompile tool that monitors files in one directory for change and outputs .js files in another directory, one of CoffeeScript’s killer features. I am also considering a port to Python 3.

I can’t use CoffeeScript

I had some space between wrapping up my last contract on December 20, and starting my new job on January 16. I decided it was finally time to build a simple task management system, something I’ve attempted to do and never finished several times before. I currently use RememberTheMilk, which is a lovely service, but I don’t like paying them for mobile access. Further, even though I trust this small company, I see no reason to share intimate information about the tasks I accomplish every day with them. My long term goal is to pull as much of my personal data out of the cloud as I possibly can. This project is a step towards that goal.

There are numerous open source task manager apps out there that I’m sure would suit my not-too-exotic tastes. However, I also wanted to take this opportunity to learn a bunch of new technologies for an offline-enabled and mobile-enabled web application.

Therefore, I’ve spent most of my vacation time so far researching some technologies I haven’t had a chance to explore in the past year. JQuery Mobile was at the top of the list. I think it’s a lovely framework and I expect to continue using it.

I also wanted to try out CoffeeScript, as I’ve always hated writing Javascript, and I wanted to use some sort of client-side ORM for localstorage. I looked at backbone.js, but was more attracted to Spine.js. I have spent three days studying and playing with these two technologies. I am still undecided about Spine.js, but I have come to the conclusion that CoffeeScript is not for me.

I understand all the hype around the project. JavaScript really does suck. And CoffeeScript does suck less, it has pretty language features and it is much more succinct than JavaScript. I can imagine a lot of people being really excited about CofeeScript, especially Ruby and PERL programmers, and possibly even php programmers.

But not Python programmers. I tried to learn Ruby several times, and each time I was left with a foul taste in my mouth. It’s not a bad language, it just doesn’t fit in well with my personal philosophy. My personal philosophy happens to coincide almost exactly with the Zen Of Python. I chose Python because it matched my philosophy… not the other way around.

Like Ruby and PERL, CoffeeScript violently violates what I consider the most important rule of Python: “There should be one — and preferably only one — obvious way to do it.” I’m not going to argue why this is a good idea, I understand that some programmers prefer the “even if I don’t understand it, I can write code that will probably work” paradigm that Ruby promotes.

The simple truth is, writing CoffeeScript leaves me feeling like I’ve done something dirty, no less dirty than writing JavaScript. There is no incentive for me to add a layer of complexity (the CoffeeScript to JavaScript compile step) to my code when I know my code is going to be “ugly” either way.

CoffeeScript is a wonderful idea. It’s far better than JavaScript. It’s just not good enough. Luckily, the Python community is already working on pythonic answers, including the evilly poorly documented pyjaco and the less-than-well maintained pyvascript and pyjamas projects. I hope one of these or a new upstart will soon gain community momentum so frontend development is no longer painful.

Internet Privacy for Dummies

I know my recent blog entries have tended towards rants on Internet privacy. It blows my mind that more people aren’t worried about it.

I’m not one to repost links on my blog, my readers know I prefer to have new content as much as possible. But this link is a wonderful summary of why normal people should be worried about privacy, and it’s outlined in a way that your mother can understand:

http://donttrack.us/

It doesn’t go as far as I would like (Facebook tracking is an even more serious offence), but it’s a good start for people who need to understand why privacy should be taken seriously.

This link is an advertisement for the duckduckgo search engine. I personally have switched from Scroogle to Starting Page. It is billed as the worlds most private search engine and has apparently been independently verified by a third party. However, Duck Duck Go may be a viable alternative as well.

My friend Matthew did not like the RequestPolicy plugin that I recommended because it required too much interaction to make sites work. He found the Ghostery plugin which works for most web browsers and does an exceptional job of removing most data trackers without any user interaction. I love this plugin! I’ve been using it for a month or so now and have experienced no broken websites. I trust it enough to put it on my family’s web browsers without them experiencing any breakage. Protecting their privacy will indirectly protect mine.

I am still being tracked on my mobile phone browser. If anyone can recommend a similar plugin for Blackberry or Android browsers, I would appreciate it.

I’ve started using bookmarks and search bookmarks a lot more often again. I had gotten in the habit of using the omni-bar for everything. Now instead of Googling the weather in some city, I search Weather Underground directly. Instead of searching google for a word definition, I search m.dictionary.com directly (the mobile site has a cleaner interface than their main one). Instead of searching for a site I had stumbled across in the past, I bookmark the site the first time I see it so I can request it without letting any search engines know I was looking for it.

“You should be on Facebook”

As I’m preparing to leave Switzerland, a lot of my friends have tried to pressure me to join Facebook so they can keep in touch. This isn’t going to happen due to privacy concerns I’ve mentioned many times before. I’d additionally like to counter a couple arguments people keep making in Facebook’s favour.

The most commonly voiced conviction is that “Facebook is so convenient,” or in the case of certain overly excitable individuals, “Facebook is soooooooooo convenient.”

I really shouldn’t have to point this out, but if Facebook were truly convenient, they would provide tools to send me a message or invite me to your events even though I don’t have an account with them. One obvious way to do this would be to integrate the Facebook messaging system with e-mail. Then you’d be able to communicate with me and anybody in the world who has an e-mail address. Facebook may connect over 800 million users (depending how many of those accounts are actually bots trying to harvest your data), but e-mail is able to connect around 2 billion people, and I am one of the 1.2 billion that are not on Facebook.

Of course, Facebook could be even more convenient if they allowed you to keep in touch with your Grandma who doesn’t know how to use a computer. Perhaps they should also support an option for mailing a letter via conventional post.

There is also no reason Facebook shouldn’t allow you to invite me to events by sending e-mails to people who do not use their service. It’s not hard to implement a non-member RSVP service; I’ve done so myself for two different client projects. The fact is, Facebook is deliberately restricting these conveniences for their own benefit.

The second argument I often here is that if I join Facebook I’ll “get to” keep up with all my friend’s lives. It is always worded as though I am missing out on some sort of privilege or basic right.

This is a bit more personal than the convenience argument. The truth is, since the adoption of the Internet, it has become trivial for absolutely anybody to author absolutely anything. Written information is a basic commodity. This puts the power in the reader’s hands, instead of the author’s.

In short, the reader has the privilege of choosing what they will read, and whose written information they will consume. The author is not granting privileges to the reader (despite the “all rights reserved” designation we still see on formally published articles).

Most people are not very good authors, and I’m sorry to say, most of the information disseminated via Facebook (that is not also available elsewhere) is simply not of interest to me.

I’m not saying my friends aren’t interesting, nothing could be further from the truth! But I prefer personalized messages in which we discuss things that are of mutual interest. I acknowledge that most of the stuff in my life is not of interest to any one of my friends. However, for those topics, facts, or events that I know you are interested in, I am happy to spend the time crafting a message meant for your eyes only in which I discuss those things I know you will care about. I won’t discuss Canadian politics if you live in Europe. I won’t discuss complex technical topics unless you’re as fascinated by them as I am. I won’t send you links to my sketches unless you’re interested in art. I would appreciate the same care from you; please don’t send me stupid cat photos, I’m not interested. I don’t care about celebrity or even local gossip. I’m not interested in the latest viral Internet meme.

Google has made an effort to address both these concerns with Google Plus. They have integrated Plus with Gmail, Google Talk, and SMS services so you can still keep in touch with me even though I have deleted my Google Plus profile. The whole Circles architecture is designed to address the second issue, although in my opinion it has failed to do so.

In summary, as I covered in my last post, Facebook does not provide such “convenient” services that they are worth the extremely high value of the data they wish to take from me in payment. If you choose to restrict your personal interactions only to the portion of the population who is active on Facebook, that is your prerogative. In turn, I will choose to keep in touch with those people who are willing to use services that I find more convenient.