Ruby koans

I had a great time today with Ruby Koans. It took me about 5 hours in all. A good way to spend a Sunday afternoon I suppose.

These Ruby Koans are a great way to go on a quick journey through a lot of Ruby’s common features. You basically have to edit tests in order to get them working. It’s mostly reading tests actually, but the fact that you have to fill in some blanks keeps the mind from wandering. There are also a couple of exercises which imply a bit more coding.

I have a good knowledge of Python and have worked with Ruby in the past on a little Rails project. I had forgotten anything I knew about Ruby though. Yesterday, I don’t think I would’ve been able to write a foobaz in Ruby without looking for help online. This proved to be a welcome refresher. Solving these koans gives a great tour of Ruby. As I went through them I kept thinking of how I would do those things with Python. I really like Python’s philosophy and maybe solving all these ruby koans has made me appreciate Python’s simplicity and predictability a bit more. Ruby allows for a lot more flexibility however and the koans left me to wonder at what amazing feats this language could accomplish.

I wouldn’t recommend this to a beginner however. While I think I now have a pretty good idea of what the language can do, there were no whys or recommendations about all these features. Maybe it would be a good starting point (or a dive) for someone coming from a similar language (like Python), before moving on to a good Ruby book. The website claims that they teach culture in addition to Ruby. I would’ve liked more of that. Maybe it was too subtle for me, but I didn’t notice anything other than some references to oriental philosophy: test_assert_truth has damaged your karma. You have not yet reached enlightenment ...

There are a lot of ports of the Ruby Koans. There’s one for python and there are also a bunch for functional languages: Clojure, F#, Haskell and Scala. These look like a lot of fun, maybe I’ll try them next week.

Comments

Cum să peticești un rpm (patch rpm)

O să vă descriu cum am aplicat un petec pentru unul dintre pachetele pentru care sunt responsabil la fedora: calibre, în timp ce așteptam să-mi vină pizza http://www.fedoraproject.ro/am-lansat-fedora-12-avans . Petecul este răspunsul la un bug report: https://bugzilla.redhat.com/show_bug.cgi?id=537525 . Calibre verifică de fiecare dată când este pornit dacă pe situl oficial a apărut o nouă versiune și dacă a apărut, îl anunță pe utilizator printr-un pop-up că trebuie să actualizeze aplicația. Cum fedora are propriul management al pachetelor și deci și al actualizărilor, este recomandat ca pachetele noi să fie instalate folosind yum; deci mesajul trebuie eliminat.

Mai întâi trebuie să descărcăm sursele actuale ale rpm-ului (în momentul în care am scris patchul, în repo-uri cea mai recentă versiune era 0.6.21-1, acum ar trebui să fie una cu patchul deja aplicat):

  $ yumdownloader --source calibre

și să le despachetăm:

  $ rpm -ivh calibre-0.6.21-1.fc12.src.rpm

Comanda va crea un nou director rpmbuild, cu subdirectoarele SPECS și SOURCES. În SPECS avem fișierul care ține toate informațiile despre cum se va construi pachetul: calibre.spec, iar în SOURCES avem sursele pachetului și toate patchurile pe care le-am creat până acum:

  $ tree rpmbuild/
  rpmbuild/
  |-- SOURCES
  |   |-- calibre-0.6.21-nofonts.tar.gz
  |   |-- calibre-cssprofiles.patch
  |   |-- calibre-manpages.patch
  |   `-- generate-tarball.sh
  `-- SPECS
  `-- calibre.spec

Mai avem de făcut un pas, ca să putem umbla prin sursele programului. Trebuie să dezarhivăm arhiva calibre-0.6.21-nofonts.tar.gz. Următoarea comandă dezarhivează și aplică patchurile pe care le avem deja:

  $ cd rpmbuild/SPECS
  $ rpmbuild -bp calibre.spec

Au apărut mai multe directoare după comanda asta:

  $ ls rpmbuild/
  BUILD  BUILDROOT  RPMS  SOURCES  SPECS  SRPMS

Cel care ne interesează este BUILD, în care au apărut sursele peticite ale programului.

Atunci când e pornit, dacă există o versiune mai nouă, calibre va afișa următorul mesaj în fereastra pop-up:

calibre has been updated to version 0.6.24. See the new features. Visit the download page?

Ca să aflăm din ce fișier vine fereastra de pop-up putem să căutăm pur și simplu o parte din textul de mai sus în sursele calibre:

  $ cd rpmbuild/BUILD/calibre/
  $ find .|xargs grep "has been updated"

Dacă ignorăm fișierele de localizare, vom afla sursa pop-up-ului:

  ./calibre/src/calibre/gui2/main.py:                    _('%s has been updated to version %s. '

Mergând în fișierul respectiv vedem că acel cod face parte dintr-o funcție numită update_found:

 
  def update_found(self, version):
  os = 'windows' if iswindows else 'osx' if isosx else 'linux'
  url = 'http://%s.kovidgoyal.net/download_%s'%(__appname__, os)
  self.latest_version = '

Ne interesează ca modificarea pe care o vom aduce să fie cât mai lizibilă pentru cei care vor modifica pachetul nostru mai târziu și să fie cât mai ușor de revenit la versiunea nemodificată. Dacă ne uităm mai atent în main, găsim următorul cod:

  if not opts.no_update_check:
  self.update_checker = CheckForUpdates()
  QObject.connect(self.update_checker,
  SIGNAL('update_found(PyQt_PyObject)'), self.update_found)
  self.update_checker.start()

Codul verifică dacă programul a fost pornit cu opțiunea no_update_check. Ar complica prea mult lucrurile dacă am modifica programul în așa fel încât să pornească de fiecare dată cu opțiunea asta așa că mai bine comentăm codul aici, ca să nu mai verifice opțiunea și deci să nu mai caute niciodată update-uri. E soluția cea mai simplă.

Ca să facem un petec ca la carte, vom face așa:

Facem o copie a fișierului main.py:

  $ cd ~/rpmbuild/BUILD/calibre/src/calibre/gui2/
  $ cp main.py main.py.no_update
  După care modificăm *fișierul inițial* și comentăm codul respectiv așa:
  # if not opts.no_update_check:
  #     self.update_checker = CheckForUpdates()
  #     QObject.connect(self.update_checker,
  #             SIGNAL('update_found(PyQt_PyObject)'), self.update_found)
  #     self.update_checker.start()

Ca să generăm petecul vom folosi gendiff din directorul de deasupra directorului rădăcină:

    $ cd ~/rpmbuild/BUILD
    $ gendiff calibre .no_update
    diff -up calibre/src/calibre/gui2/main.py.no_update calibre/src/calibre/gui2/main.py
    --- calibre/src/calibre/gui2/main.py.no_update	2009-11-16 14:21:55.200387171 +0200
    +++ calibre/src/calibre/gui2/main.py	2009-11-16 14:22:10.400510757 +0200
    @@ -221,11 +221,11 @@ class Main(MainWindow, Ui_MainWindow, De
    self.latest_version = ' '
    self.vanity.setText(self.vanity_template%dict(version=' ', device=' '))
    self.device_info = ' '
    -        if not opts.no_update_check:
    -            self.update_checker = CheckForUpdates()
    -            QObject.connect(self.update_checker,
    -                    SIGNAL('update_found(PyQt_PyObject)'), self.update_found)
    -            self.update_checker.start()
    +        # if not opts.no_update_check:
    +        #     self.update_checker = CheckForUpdates()
    +        #     QObject.connect(self.update_checker,
    +        #             SIGNAL('update_found(PyQt_PyObject)'), self.update_found)
    +        #     self.update_checker.start()
    ####################### Status Bar #####################
    self.status_bar = StatusBar(self.jobs_dialog, self.system_tray_icon)
    self.setStatusBar(self.status_bar)

Totul arată bine, deci putem să-l punem în surse:

  $ gendiff calibre .no_update > ~/rpmbuild/SOURCES/calibre-no-update.patch

Acum trebuie să modificăm spec-ul, adăugând un nou petec, incrementând release-ul, menționând motivul pentru petec și scriind modificarea în Changelog:

  @@ -1,6 +1,6 @@
  Name:           calibre
  Version:        0.6.21
  -Release:        1%{?dist}
  +Release:        2%{?dist}
  Summary:        E-book converter and library management
  Group:          Applications/Multimedia
  License:        GPLv3
  @@ -18,6 +18,7 @@
  Source1:        generate-tarball.sh
  Patch0:         %{name}-cssprofiles.patch
  Patch1:         %{name}-manpages.patch
  +Patch2:         %{name}-no-update.patch
  BuildRoot:      %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
  BuildRequires:  python >= 2.6
  @@ -72,6 +73,9 @@
  # don't append calibre1 to the name of the manpages. No need to compress either
  %patch1 -p1 -b .manpages
  +# don't check for new upstream version (that's what packagers do)
  +%patch2 -p1 -b .no-update
  +
  # dos2unix newline conversion
  %{__sed} -i 's/\r//' src/calibre/web/feeds/recipes/*
  @@ -239,6 +243,9 @@
  %{_mandir}/man1/*
  %changelog
  +* Sat Nov  29 2009 Ionuț C. Arțăriși 

Gata. Asta a fost tot :). Acum putem reconstrui pachetul cu noile patchuri:

  $ cd ~/rpmbuild/SPECS/
  $ rpmbuild -ba calibre.spec

Și putem reinstala noul pachet:

  $ su -c "yum localinstall -y --nogpgcheck ~/rpmbuild/RPMS/x86_64/calibre-0.6.21-2.fc12.x86_64.rpm"
Comments

The Productive Programmer

Today I read The Productive Programmer .

I’ve already got a bunch of books piled up and waiting to be read, some of which I’ve reached the middle of and some of which I’ve read only the introduction to. I was bored today and this looked like an easy read that I could drop at any time. It is an easy read, but the fact is, it’s very catchy. It draws you in and doesn’t want to be let go. It’s a great way to spend half a day.

This could have been another one of those “94 things you need to know” books, but I think this title is way better. The tips are divided into 2 big sections and a few separate chapters within each one, giving the book some structure. One of the strange things about it is that its advice spans across 3 different platforms (*nix, OS X and Windows) and they’re all mingled together in the same chapter. I was put off by this at first, but after I’d gotten into the book a bit I realized that it is, in fact, a good idea. The whole theme of the book is programmer productivity and the reason it has this title and not a cheesy title with numbers like “94.3 productivity tips for programmers” is that the tips aren’t what’s important. The book is there to hit people in the head with and open their minds. You aren’t supposed to just use the tips provided, that’s unimportant. What’s important is that you have a shock and realize that you’ve been the wrong kind of lazy as a programmer. You’ve stopped automating, you’ve become a machine; in the author’s own words, computers have started “getting together late at night to make fun of their users”. As soon as I realized what this book was really about, I started reading the Windows tips as well. I also stopped a few times to look in my distro’s repository for tools that I had known of, but never used before, only now understanding their true purpose. There are many applications that seem just trendy at first, until you realize that even a small productivity boost is a big productivity boost. (Go check out gnome-do , I’d heard about it years ago, but never tried it until now).
The book contains tips ranging from application launchers, Firefox’s magic address bar, bash scripting commands to office productivity tips for killing distractions. Once again, the mindset is important, not the tips themselves. The big take-away from this book is beginning to constantly judge everything you do as a programmer. This isn’t new advice (at least for those who have read The Pragmatic Programmer”, which by the way is mentioned several times in this book), but I find it’s better emphasized in this book. At one point in the book, the author explains how it took his team one hour to devise a Ruby script to automate some simple task that would’ve required 10 minutes if done manually and finally only needed doing 5 times. One could say there was a loss in productivity, but as the author points out, one would be wrong. Those 50 minutes would’ve been spent with the brain turned off, whereas the hour writing the script was spent learning, focusing, practicing, gaining knowledge that can later be used on a different project. Some of us would probably have gotten bored in those 50 minutes and fallen into procrastination. That doesn’t happen when you’ve got a complex problem to solve.
That was the first part of the book, Mechanics. The second part, Practice is a bit harder to read, as it’s not just disparaged tips on very different applications. They’re quite two separate books actually. The majority of the examples in Part IIare java (they’re mostly readable even for someone who doesn’t speak the exact dialect of OOP that java uses) and this part is mostly about software construction as Steve McConnell would say, but it’s also about Java. I learned a new acronym: YAGNI which basically means that thinking ahead is bad. This is probably one of the advices that I feel the least guilty about, but which I sometime observe in people around me. Never program a feature you don’t urgently have a need for.
One of the good points of this book is the originality with which the ideas are expressed. Most of these ideas aren’t new, especially to anyone who’s read other software engineering books. The text is spiced up with little narratives of different adventures from the author’s experience as a consultant and there is also an Ancient Philosophers chapter and an explanation of the PacMan game’s way of functioning (although I didn’t understand how that’s supposed to make the game less enjoyable).

Comments

Fedora Business Cards

A few days ago, me and a few friends from Fedora Romania decided we’d like some fedora business cards for the upcoming eLiberatica conference. Ian Weller had already developed an official template and even created a cool python generator script and packaged it.

The problem, however, was that it only supported US-style business cards which are a bit smaller than the Romanian/Central European ones. Live and learn… It seems that there are a lot of different sizes actually.

So I got my hacking hat and dived in. The code was quite nice to look at and easy to understand. The XML in the svg templates is quite easy to hack, too. Especially when using tools like python’s minidom . It makes working with python and XML taste like javascript dom manipulation which is quite nice.

Everything went smooth, I renamed a few tags, made some modifiable (for height and width), but then I had to make the blue strip on the right of the front of the business card extendable1 . There is no way in XML to align an element to the right so I spent about an hour coming up with a sweet solution. Instead of having a big white background on which I would apply the blue band, I made a big blue background and made the white background just a little narrower. Because the white background was on top of the blue one, it could get aligned to the left (x=0, y=0 in XML) and cover just the part that needed to be white, and left a blue band at the right. Problem solved. Hoo-grah!

Now I’m waiting for an answer to the patch that I sent to bugzilla. Hopefully it’ll be accepted and will be available in Fedora, soon, so that others may enjoy and cherish the coolness that it be!

Comments
Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 Unported License.