Older blog entries for ralsina (starting at number 698)

Doing Your Homework, With Style


The original poster claims this is not a school homework. Accepting that, it still doesn't mean how to answer to homework requests is not worthy of discussion.

As usual in all programming lists, every once in a while someone will post a question in the Python Argentina list which is obviously his homework. To handle that there are two schools of thought.

  1. Telling the student how to do it is helping them cheat.
  2. Telling the student how to do it is teaching him.

I tend more towards 1) but I think I have discovered a middle road:

1.5) Tell the student a solution that's more complicated than the problem.

That way, if he figures out the solution, he has done the work, and if he doesn't figure it out, it's going to be so obviously beyond his skill the teacher will never accept it as an answer.

As an example, here's the problem for which help was requested:

Given an unsorted list of two-letter elements (une lowercase, one uppercase), for example:

['eD', 'fC', 'hC', 'iC', 'jD', 'bD', 'fH', 'mS', 'aS', 'mD']

Sort it by these criteria:

  1. Create subsets according to the uppercase letter, and sort them by the number of members in ascending order, like this:

    ['fH', 'mS', 'aS', 'fC', 'hC', 'iC', 'jD', 'bD', 'eD', 'mD']
  2. Then sort each subset in ascending order of the lowercase letter, like this:

    ['fH', 'aS', 'mS', 'fC', 'hC', 'iC', 'bD', 'eD', 'jD', 'mD']

Ignoring that the problem is not correctly written (there are at least two ways to read it, probably more), I proposed this solution, which requires python 3:

from collections import defaultdict
d1 = defaultdict(list)
[d1[i[1]].append(i) for i in  ['eD', 'fC', 'hC', 'iC', 'jD', 'bD', 'fH', 'mS', 'aS', 'mD']]
{i: d1[i].sort() for i in d1}
d2 = {len(d1[i]): d1[i] for i in d1}
print([item for sublist in [d2[i] for i in sorted(d2.keys())] for item in sublist])

This produces the desired result: ['fH', 'aS', 'mS', 'fC', 'hC', 'iC', 'bD', 'eD', 'jD', 'mD'] but it's done in such a way that to understand it, the student will need to understand roughly three or four things he has probably not been taught yet.

Syndicated 2013-03-10 20:23:32 from Lateral Opinion

A Django Le Saltó La Cadena

Sorry, spanish only post!

Syndicated 2013-03-10 09:35:49 from Lateral Opinion

A Few Problems with A Song Of Ice and Fire

I read all of it, one book after the other, and ended a month ago. And since then, I have had a couple of things about it bothering me. Let's see if they make some sense. Mind you, I am going to read volumes six and seven, because these books are addictive as crack in ebook-form.

But, just like crack, they have some worrisome features.

There May Be No Plan

We are five books (and a couple of chapters) into it. It's supposed to be a seven book series. And nothing has happened. You may say a lot has, like "this character got killed" and "that other character got killed" (and a hundred other characters got killed), yeah.

But what has changed in the five kingdoms?

It's starting to feel, these many pages later, as if ... well, who cares what happens? The five kingdoms will have a king, or another. There will be dragons (which will support a king or another), there is war and everyone is having a crappy time, but hey, all that happened five times in the last hundred years or so already.

The hand of the king was killed? Well, so were five of the last seven hands.

A Targaryen may come, lay waste to all the armies of the realm and be crowned? Well, that already happened in the field of fire, and they had Targaryens for a while, until they ran out of dragons.

The Ironmen may conquer the north? Well, they already had conquered it a couple centuries ago, and then they lost it.

And so on: any of the payoffs of the book series has already happened, some of it more than once. So, what's special about this time around?

Does the author have a plan, something up his sleeve that's going to be a shock? I don't know, but the tricks are starting to get repetitive.

What would happen if, after seven books, it turns out that there's nothing special?

It's Too Earth-Like

The five kingdoms. Scotland, England, Wales, Ireland and which one? Isle of Man? Because, come on. There's these people who are almost exactly Mongols, except they have bells in their hair. There's the pseudo-viking, the pseudo-scots, the ersatz-irish, the fake-italians, the I-can't-believe-it's-not-chinese and so on.

There are knights, whose armour is exactly medieval armour. There's the seafaring raiders, on their longships. Etcetera, etcetera, et-freaking-cetera. It's like whenever the author needs to add an "exotic" character, he just throws a dart at the map, then another, creates a mix 80% one, 20% the other, makes up some silly ortography rule for names, and that's it.

The Magic is Lazy

So, dragons. And of course, dragons create magic (you can see how lots of magical gizmos start working since the dragons came).

So, let's make magic everything. Want to have legendary swords? Then they are made of Valyrian steel. That's magical steel, which is why it seems to never need sharpening. That's why you can have family heirloom swords. Because they are magical.

And there's a magical door, made of magical wood. The magical wood comes, of course, from magical trees.

And there's fake magical swords, made by real eastern magic. And there's magical assassins. And magical coins, magical candles. And so on, and so forth. You can't paint yourself into corners when you can count on there being a magical paintbrush that lays down paint that doesn't stain the magical shoes of the painters of the magical land of Paintheria, whose names always have a double laryngeal consonant in the middle.

More is More is More is Less

The first book manages to tell roughly a (earth) year of story. The fourth and fifth, together because they happen simultaneously, cover perhaps three months. And there are characters we have not seen since book three, when they were just about to say something. We are currently entering the third book waiting to know what the maiden of Tarth said at that moment.

There are books that are about one character, there are those that are about a dozen, there are those that are about one hundred. None of the latter is any good. The story keeps expanding and slowing down. At this step, all of book seven is going to be about a single day in the lifes of 50 first-person characters, and each one will describe their breakfast, before we unexpectedly get promised (very soon now) an eight book which will cover their post-breakfast craps and clear every question we may have had about the subject.

Fan Service

You, who know what was in the pies served in the feast at Winterfell in volume 5, you are being spoonfed that kind of thing to make you feel smart and knowledgeable. If you don't know what was in that pie... well, YOU MISSED IT.

And how is it a good idea to write three pages that (if you have a good memory) shout what was in that pie, when it's a story about a third-line and fourth-line characters whose names noone will remember?

Well, it's a good idea because it's fan service, and fans love being served. But it's a cynical, calculating move. You are being served bad pie there, fans.

So, Are the Books Good?

They are awesome. I can't wait for the sixth volume. George RR Martin, here's my money. Tell me a story.

Syndicated 2013-03-09 21:43:11 from Lateral Opinion

Twitter Off

A week ago, I took a decision I had not seen coming. I shut down comments on this blog unless the post was technical. Because I could not stand some of the comments anymore. I said "comments down for a month, and then I'll see if I miss them".

Well, so far I don't, as you can see by this post having comments disabled.

Today, I am removing the comment track of my life. I an shutting down my twitter account. Some automatic posts will go out, but I am not reading it and am not notified of anything. Again, it's "twitter down for a month, and then I'll see if I miss it΅.

Hopefully I will not.

Syndicated 2013-03-09 12:39:38 from Lateral Opinion

Python Trick: the Fundict (or the Diction)

Suppose you have made the choice in the past of exposing a dictionary as part of an object's interface. So, people are doing things like:


And now you want people to not have to specify foo because it can be obtained from somewhere else. In fact, what you want now is to expose something like this:

object.data(bar, foo='foo')

Here's an idea on how to do that without breaking the old code:

class fundict(dict):
    def __call__(self, bar, foo='foo'):
        return self[foo][bar]

That's a dictionary that's also a callable, and thus indistinguishable from a function. A function-dictionary. A fundict. And of couse, you could also do it the other way around, and implement a function that works as a dictionary. A dictionary-function, a diction. But since that's more work, I used this one.

Syndicated 2013-03-08 18:13:41 from Lateral Opinion

Twitter Card Support in Nikola

This feature for Nikola was implemented by @amokleben, and now, if you ask twitter your site can have it too.

What are Twitter Cards? Did you notice that for some sites, when you click on tweets that have links, you get a small preview of the content? Well, that's a twitter card.

This still needs a little improvement to support the richer "media" cards, but it does work:


You don't have to do anything in your site, but setting the "description" metadata to your posts helps make this more accurate (and it also works for google+)

Syndicated 2013-03-05 06:31:57 from Lateral Opinion

Nikola 5.4 is out!

I am thrilled to announce the release of version 5.4 of Nikola, a static site/blog generator

Here's the (incomplete!) changelog for this release [1]:


  • Twitter Card / Open Graph support.
  • Smart math support
  • New soundcould directive
  • Custom "read more" links
  • Better time display, timezone support
  • Better doit integration (Issue #151)
  • Make the whole listings folder browsable (Issue #128)
  • New GZIP_FILES/GZIP_EXTENSIONS options to create gzipped copies of some files (Issue #348)
  • New optional path parameter to new_post command.
  • Wordpress importer: option to not download files
  • Wordpress importer: option to squash newlines
  • Separated BLOG_URL into SITE_URL and BASE_URL
  • Added DISABLED_PLUGINS option (Issue #354)


  • Added missing </div> in default theme templates.
  • Wordpress import: Description is left empty if no description is found.
  • When running the build command it is now possible to get help.
  • Load jQuery before bootstrap in JS bundle (Issue #327)
  • Generate valid HTML5 for redirects (Issue #276)
  • Fixed "nikola check"
  • Fixed internationalized RSS links
  • Make commands that need to be run in a site fail gracefully (Issue #342)
  • Use localized links on lxml fixer
  • Redirections created during the import from wordpress are now written to conf.py
  • Stop parsing metadata in post file on first blank line
  • Metadata handling cleanups by Tordek
  • Fixed blockquote font size inconsistency
  • Wordpress Import: Do not break indentation (issue #189)
  • Make things work even if SITE_URL has a path (Fix #307)
[1]There are also some extra bits of documentation, and a awesome beta theme called "site-reveal" based on bootstrap and reveal.js!

Syndicated 2013-03-04 18:40:24 from Lateral Opinion

Creating a Site (Not a Blog) with Nikola

One of the most frequent questions I get about Nikola is "but how do I create a site that's not a blog?". And of course, that's because the documentation is heavily blog-oriented. This document will change that ;-)

Since it started, Nikola has had the capabilities to create generic sites. For example, Nikola's own site is a fairly generic one. Let's go step by step on how you can do something like that.

Using 5.3?

This tutorial is based on Nikola from github master. Some details are not correct for the 5.3 release. Master works quite well most of the time, but you may want to wait until the 5.4 release in a few days (which will include an updated version of this document).

As usual when starting a nikola site, you start with nikola init which creates a empty semi-configured site:

$ nikola init mysite
Created empty site at mysite.

Then we go into the new mysite folder, and make the needed changes in the conf.py configuration file:

# Configuration, please edit

# Data about this site
BLOG_AUTHOR = "Roberto Alsina"
BLOG_TITLE = "Not a Blog"
# This is the main URL for your site. It will be used
# in a prominent link
SITE_URL = "http://notablog.ralsina.com.ar"
BLOG_EMAIL = "ralsina@kde.org"
BLOG_DESCRIPTION = "This is a demo site (not a blog) for Nikola."

# Some things in the middle you don't really need to change...

post_pages = (
    ("pages/*.txt", "", "story.tmpl", False),

And now we are ready to create our first page:

$ nikola new_post -p
Creating New Post

Enter title: index
Your post's text is at:  pages/index.txt


The -p option in the nikola new_post command means we are creating a page and not a blog post.

We can now build and preview our site:

$ nikola build
Scanning posts.done!
.  render_site:output/categories/index.html
.  render_sources:output/index.txt
.  render_rss:output/rss.xml
: [Much more of the same]

$ nikola serve
Serving HTTP on port 8000 ...

And you can see your (very empty) site in http://localhost:8000

So, what's in that pages/index.txt file?

.. title: index
.. slug: index
.. date: 2013/03/01 10:26:17
.. tags:
.. link:
.. description:

Write your post here.

Title is the page title, slug is the name of the generated HTML file (in this case it would be index.html) the date doesn't matter much in not-blogs, same for tags and link. Description is useful for SEO purposes if you care for that.

And below, the content. By default you are expected to use reStructured text but Nikola supports a ton of formats, including Markdown, plain HTML, BBCode, Wiki, and Textile.

So, let's give the page a nicer title, and some fake content. Since the default Nikola theme (called "site") is based on bootstrap you can use anything you like from it:

.. title: Welcome To The Fake Site
.. slug: index
.. date: 2013/03/01 10:26:17
.. tags:
.. link:
.. description: Fake Site version 1, welcome page!

.. class:: hero-unit span6

.. admonition:: This is a Fake Site

    It pretends to be about things, but is really just an example.
    So, don't click this button, it leads nowhere.

    .. class:: btn

    Click Me!

.. class:: span5

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Mauris non nunc turpis.
Phasellus a ullamcorper leo. Sed fringilla dapibus orci eu ornare. Quisque
gravida quam a mi dignissim consequat. Morbi sed iaculis mi. Vivamus ultrices
mattis euismod. Mauris aliquet magna eget mauris volutpat a egestas leo rhoncus.
In hac habitasse platea dictumst. Ut sed mi arcu. Nullam id massa eu orci
convallis accumsan. Nunc faucibus sodales justo ac ornare. In eu congue eros.
Pellentesque iaculis risus urna. Proin est lorem, scelerisque non elementum at,
semper vel velit. Phasellus consectetur orci vel tortor tempus imperdiet. Class
aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos

[And more in the same vein]

TIP: Nice URLs

If you like your URLs without the ".html" then you want to create folders and put the pages in index.html inside them. Example:

nikola new_post -p pages/foo/index.txt

which will create a page you could access as "http://yoursite.com/foo"

And that's it. You will want to change the SIDEBAR_LINKS option to create a reasonable "menu" for your site, you will want to hack the theme (check nikola help bootswatch_theme for a quick & dirty solution), and you may want to add a blog later on, for company news or whatever.

TIP: So, how do I add a blog now?

First, change the post_pages option like this:

post_pages = (
    ("pages/*.txt", "", "story.tmpl", False),
    ("posts/*.txt", "blog", "post.tmpl", True),

And to avoid a conflict (because blogs try to generate /index.html:

INDEX_PATH = "blog"

Create a post with nikola new_post and that's it, you now have a blog in http://yoursite.com/blog (you may want to add links to it in SIDEBAR_LINKS of course).

You can see the finished site in http://notablog.ralsina.com.ar and its full configuration in http://ralsina.com.ar/listings/notablog/conf.py.html

I hope this was helpful!

Syndicated 2013-03-01 12:49:41 from Lateral Opinion

Load Testing Nikola

Nikola generates static sites, so load testing it is not very interesting, except as a benchmark for the difference between static and dynamic sites.

Today I was told about blitz.io and since a quick test is free, I thought, why not? The result is quite impressive: a cheap VPS, using gatling as a web server, which is almost configuration-free and not meant for extremely high loads, can handle roughly 9 million daily hits.

Let me say that again: 9 million hits. On a unconfigured $5 server. Here's the report

How much tuning does it take for a wordpress instance to serve that? On what hardware?

And that's only half the picture. Not only are Nikola's static pages incredibly light on your server, we have also spent a lot of effort trying to make individual pages load fast, for a better user experience. Some of the techniques used for fast-loading sites are:

  • Using webassets to bundle CSS and JS into single files.
  • Automatic support for CDNs for the common JS libraries
  • Support for transparently using HTML/CSS/JS/Image compression tools

So, if you try something like YSlow! on a Nikola site, it will give you a score of roughly 93 up to 98 (out of 100) depending on your webserver configuration.

BTW: I really want to get that up to 100. Really want it

So, remember, if your site can be served statically, it's going to be cheaper, faster, safer. And if you ever get 9 million hits a day, it will be available.

Blitz.io is sending me a t-shirt ;-)

Syndicated 2013-02-25 17:34:16 from Lateral Opinion

689 older entries...

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!