Search Results: "morph"

20 March 2009

Mike Hommey: WebKit 1.1.3 in experimental

You may have noticed, or not, but WebKit 1.1.3, which has been released a few days ago, is available in experimental. The great news is that we now have a real maintenance team, because I now have a co-maintainer, who actually did most of the work getting the 1.1.x releases in shape for experimental. Now, some JavaScript performance figures, as I have been doing for most WebKit releases I uploaded to the archive, with a recap of previous episodes: All there tests have obviously been run on the same machine, under the same conditions. The machine in question is my x86-64 laptop, which means all these test are with a x86-64 binary. This also means the last release, 1.1.3, doesn t take advantage of the Just In Time JavaScript compiler, which is only available on x86 binaries. With the x86 binaries under a x86 personality chroot, I get under one second: But, in the last few days, I ve been working on getting JIT first to build and then to work on x86-64 linux, and with the help of folks on the webkit-dev list, that just happened. And the result is just wow. (Note that a few tests are actually slower than on x86) That s so many times faster than what we had a year ago that it s almost unbelievable. Expect the next upstream release, planned for some time in the near future, to have my patches applied. In the meanwhile, you can get them here and here.

31 December 2008

Joachim Breitner: Handling explicit and implicit recusion in Haskell data

For a while I have been pondering over a problem that arises when your functionally written program has some state with cross references for example a list of users, each of which uses a number of computers, and a list of computers, each having an owner. Implicit referencing For doing queries on such data, it would be convenient if every reference is just the referenced object itself. Although we would visualize this as a graph, semantically, it is more like an infinite tree. This is possible in Haskell, due to laziness, and if you create the data structure cleverly, it even uses constant memory, no matter how deep you enter this infinite tree (a recent post of mine talks about this). A possible data definition would be:
data User = User  
userName :: String,
uses :: [Computer]

data Computer = Computer
computerName :: String,
owner :: User -- references the Users

data State = State [User] [Computer]

testState = let user = User "Conrad" [computer]
computer = Computer "Z3" user
in State [user] [computer]
Explicit referencing But such a representation is very unsuitable for updates (at least I can t think if a nice way of updating such a graph without breaking the internal cross-references) and serialization, which is a must for a HAppS based application. So what one would probably start with is this data structure:
data User = User  
userId :: Int,
userName :: String,
uses :: [Int] -- references the Computers

data Computer = Computer
computerId :: Int,
computerName :: String,
owner :: Int -- references the Users

data State = State [User] [Computer]

testState = State
[User 0 "Conrad" [1]]
[Computer 1 "Z3" 0]
I think the semantics of this are clear. Note that the referencing is currently not type-safe, but this can be provided by phantom types. Maybe I ll write more about that later. Now imaging you want to display the information about the first computer with your web application. You extract the information with let State _ cs = testState in head cs and pass that to your templating engine. But what if your template wants to display the name of the owner? It only has access to his userId. You would either need to know what information the template will ever need, extract that from the state beforehand and pass it along, or give the template access to the whole state. In that case, though, there has to be lookup-logic in your output code, which is also not nice. Woudln t it be nice if you could, in your application logic, work with the explicit references, which are easy to modify and store, but somehow turn that into the implicit referencing? Duplicated representation One way would be to have two unrelated sets of data structures, ExplicitState, ExplicitUser, ExplicitComputer, which use explicit identifiers to reference each other, and ImplicitState,... which are defined as the first representation of our state. It is then mostly trivial to write a function that converts ExplicitState to ImplicitState. The big disadvantage of this is that you have to maintain these two different hierarchies. It also means that every function on the state has to be defined twice, which often almost identical code. Clearly, this is not desirable. Annotated representation It would be more elegant if the state is stored in one data type that, controlled by a type parameter, comes in the one or the other representation. To do that, we need two types: One that contains a value, and one that contains just a reference:
newtype Id v = Id v deriving (Show, Typeable, Data)
newtype Ref v = Ref Int deriving (Show, Typeable, Data)
Then we need to adjust our data definitions, to make use of these. (I ll leave out the names, to keep the code smaller)
data User ref = User  
userId :: Int,
uses :: [ref (Computer ref)]

data Computer ref = Computer
computerId :: Int,
owner :: ref (User ref)

data State ref = State [User ref] [Computer ref]
Here we introduce a type parameter ref , which will later be either Id or Ref. Note that now a reference also states the object it is a reference for, which greatly increases type safety. Functions on these data types that don t work with the references will be polymorphic in the ref type parameter, so only need to be written once. A User Id is a complete user with all related data, while User Ref is a user with only references. And a Ref (User Ref) is reference to a user, which contains references... Not so kind kinds Did you notice the lack of a deriving clause? Our data structures have the relatively peculiar kind ((* -> *) -> *), which makes it hard for the compiler to derive instances for things like Show. But we already know that we will only use Id or Ref for the type variable, so we can use ghc s StandaloneDeriving language extension and have these instances created:
deriving instance Show (User Id)
deriving instance Show (User Ref)
deriving instance Show (Computer Id)
deriving instance Show (Computer Ref)
deriving instance Show (State Id)
deriving instance Show (State Ref)
Toggling a type parameter The next step is to write the conversion function. It will have type
unrefState :: State Ref -> State Id
For that, and for later, we need lookup functions:
unrefUserRef :: State Id -> Ref (User Ref) -> Id (User Id)
unrefUserRef (State l _) (Ref i) = Id $ fromJust $
find (\u@(User i' _) -> i == i') l
unrefComputerRef :: State Id -> Ref (Computer Ref) -> Id (Computer Id)
unrefComputerRef (State _ l) (Ref i) = Id $ fromJust $
find (\u@(Computer i' _) -> i == i') l
These expect a State (with implicit referencing) and a reference, and look up this reference. The function unrefState then looks like this:
unrefState :: State Ref -> State Id
unrefState (State us cs) =
let unrefState = State (map (unrefUser unrefState) us)
(map (unrefComp unrefState) cs)
in unrefState
where unrefUser :: State Id -> User Ref -> User Id
unrefUser s (User i refs) = User i (map (unrefComputerRef s) refs)

unrefComp :: State Id -> Computer Ref -> Computer Id
unrefComp s (Computer i ref) = Computer i (unrefUserRef s ref)
Note how we tie the knot in the let expression. This is the trick that ensures constant memory consumption, because every reference points back to the same place in memory. Satisfied already? So what do we have? We have no duplication of data types, we can write general functions, and we can resolve the explicit referencing. We can also easily write functions like unrefUser :: State Ref -> User Ref -> User Id, which transform just a part of the state. But writing unrefState is very tedious when the State becomes more complex. Each of the other unrefSomething functions are very similar, but need to be written anyways. This is unsatisfactory. What we want, is a generic function, something like
gunref :: State Ref -> a Ref -> a Id
which, given a state with explicit references, replaces all explicit references in the first argument (which could be State Ref or User Ref or anything like that) with implicit ones. This function can not exist, because we would not know anything about a and b. But maybe we can do this:
gunref :: (Data (a Id), Data (a Ref)) =>  State Ref -> a Ref -> a Id
Typeable and Data Before being able to do so, we need to derive Data for our types. We can start with
deriving instance Data (User Id)
deriving instance Data (User Ref)
deriving instance Data (Computer Id)
deriving instance Data (Computer Ref)
deriving instance Data (State Id)
deriving instance Data (State Ref
but that will complain about missing Typeable instances. Unfortunately, ghc s deriver for Typeable (even the stand-alone-one), does not handle our peculiar kind, so we need to do it by hand. With some help from quicksilver on #haskell, I got it to work:
instance Typeable1 ref => Typeable (User ref) where
typeOf _ = mkTyConApp (mkTyCon "User") [typeOf1 (undefined :: ref ())]
instance Typeable1 ref => Typeable (Computer ref) where
typeOf _ = mkTyConApp (mkTyCon "Computer") [typeOf1 (undefined :: ref ())]
instance Typeable1 ref => Typeable (State ref) where
typeOf _ = mkTyConApp (mkTyCon "State") [typeOf1 (undefined :: ref ())]
everywhere is not enough Turning to the documentation of Data.Generics, I notice with some disappointment that there is no function that is able to change a type they all seem to replace a value by another value of the same type. But the functions gfoldl and gunfold sounded like they could be used for this. Warning: What comes now is a very non-haskellish hack that subverts the type system, just to get the job done. Please read it with a healthy portion of distrust. If you know of a cleaner way of doing that, please tell me! Wrapped Data I want to do some heavy type hackery, so I need to disable haskell s type system. There is Data.Dynamic, but not even that is enough, as we need to carry a type s Data instance around as well. So let s wrap that up:
data AData where AData :: Data a => a -> AData
instance Show AData where show (AData a) = "<" ++ show (typeOf a) ++ ">"

fromADataE :: forall b. Data b => AData -> b
fromADataE (AData d) = case cast d of
Just v -> v
Nothing -> error $ "Type error, trying to convert " ++
show (typeOf d) ++ " to " ++
show (typeOf (undefined :: b)) ++ "."
There is also a function that converts an AData back to a normal type, if possible. If it s not possible, then there is a bug in our code, so we give an informative error message. AData transformers Similar to everywhere, we want to have transformers that combinable. They need to have the change to convert an arbitrary value, but also signal that they could not convert something (and this something has to be recursed into). I came up with this:
type ADataT = AData -> Maybe AData

extADT :: forall a b. (Data a, Data b) => ADataT -> (a -> b) -> ADataT
extADT at t a@(AData v) = case cast v of
Just x -> Just (AData (t x))
Nothing -> at a

doNothing :: ADataT
doNothing = const Nothing
ADataT is the type for such a transformer. doNothing will not transform anything, and extADT can be used to add any function to the list of tried transformers, in the spirit of extT. The ugly part To apply such a transformer, I want to use this function, which I ll describe in the code comments:
everywhereADT :: forall a b. (Data a, Data b) => ADataT -> a -> b

-- first check if we can transform this value already
everywhereADT f v = case f (AData v) of
-- if so, coerce it to the users requested type, which hopefully goes well
Just r -> fromADataE r
-- if not, we need to recurse into the data structure
Nothing -> recursed

-- for that, we first need to figure out the arguments to the
-- constructor. We store them in the untyped list
where args :: [AData]
(Const args) = gfoldl k z v
-- gfoldl lets us have a look at each argument. We wrap it in AData
-- and append it to the list
k (Const args) arg = Const (AData arg : args)
z start = Const []

-- We need the data constructor of the input data type. If the user did not want
-- it to be transformed, it will be the same
c = toConstr v

-- To give better error messages, we make sure that the outmost type constructor
-- of the requested type actually has the data constructor we were given. Otherwise
-- gunfold will complain in a non-helpful way
input_type = dataTypeRep (constrType c)
output_type = dataTypeRep (dataTypeOf (undefined :: b))

recursed = if input_type /= output_type
then error $ "Can not convert <" ++ show input_type ++ ">"++
" to <" ++ show output_type ++ ">."
-- the types match, so we assemble the output type, using gunfold
else snd (gunfold k' z' c)
k' :: forall b r . Data b => ([AData], b -> r) -> ([AData],r)

-- we start by reversing the input list
z' start = (reverse args,start)

-- then we call us recursively on the argument and feed the result
-- to the output constructor
k' ((AData a) : args, append) = (args, append (everywhereADT f a))

-- Used for folding (we don t need to retain the original constructor)
data Const a b = Const a
What a beast! But surprisingly, it works. Here are some examples. Note that I always have to specify the requested output type:
bool2Int :: Bool -> Int
bool2Int False = 0
bool2Int True = 1

*Main> everywhereADT (doNothing extADT bool2Int) True :: Int
1
*Main> everywhereADT (doNothing extADT bool2Int) True :: ()
*** Exception: Type error, trying to convert Int to ().
*Main> everywhereADT (doNothing extADT bool2Int) (True,False) :: (Int,Int)
(1,0)
*Main> everywhereADT (doNothing extADT bool2Int) ([True,False],True,()) :: ([Int],Int,())
([1,0],1,())
*Main> everywhereADT (doNothing extADT bool2Int) ([True,False],True,()) :: [()]
*** Exception: Can not convert to .
*Main> everywhereADT (doNothing extADT bool2Int) [True] :: [Bool]
[*** Exception: Type error, trying to convert Int to Bool.
I hope this code does not inflict too much pain on any Haskell-loving reader. I know I violated the language, but I didn t know how to do it better (at least not without using Template Haskell). I also know that this is not very good performance wide: Every single value in the input will be deconstructed, type-compared several times and re-assembled. If that is an issue, then this function should only be used for prototyping. Almost done To apply this to our state, we only need to glue it to our lookup functions from above:
gunref :: (Data (a Id), Data (a Ref)) =>  State Ref -> a Ref -> a Id
gunref s w = let unrefState = gunref' unrefState s
in gunref' unrefState w

gunref' :: (Data (a Id), Data (a Ref)) => State Id -> a Ref -> a Id
gunref' unrefState = everywhereADT unref'
where unref' = doNothing extADT
unrefUserRef unrefState extADT
unrefComputerRef unrefState
Now we have a generic unreferencer. I set the type a bit more specific than necessary, to make it safe to use (under the assumption that the list of lookup functions is complete and will not leave any Ref in the output).
*Main> testState 
State [User userId = 0, uses = [Ref 1] ] [Computer computerId = 1, owner = Ref 0 ]
*Main> gunref testState testState
State [User userId = 0, uses = [Id (Computer computerId = 1, owner = Id (User userId = 0,
uses = [Id (Computer computerId = 1, owner = Id (User userId = 0, uses = ..
Oh, and by the way, if you want to test this code, you ll need at least:
 -# LANGUAGE DeriveDataTypeable, FlexibleInstances, GADTs,
FlexibleContexts, StandaloneDeriving, ScopedTypeVariables #-

Romain Beauxis: Fun with liquidsoap and video..

The other day, I wanted to prepare some videos of my favorite reggae and soul tunes for uploading them to YouTube.. My goal was very simple: prepare a video with a static image and the music I wanted to upload.. After briefly digging for a simple software to do that, which I could not found, I said "hey, why not doing it with liquidsoap !". Well, that is fairly easy ! Video support in liquidsoap is very young, but the amount of things that can be done is already quite important, so I though this would be an interesting example.. All you have to do is to prepare a PPN version of the picture, using convert /path/to/image.jpeg /path/to/image.ppn and have the mp3 or ogg file in an other place... From the scripting point of view, the only difficult thing is to have liquidsoap stop at the end of the song.. As liquidsoap is mainly a streaming language, it is not designed to be able to stop easily. It should be made better soon, but for now I had to use a special trick: compose sequentially the song with a blank source. On the blank source, I add special metadata such that the output file is reopened with a new title when the song has ended. Eventually, the shutdown is triggered when adding the new metadata on the blank source. Here is the code:
# Log to stdout
set("log.file",false)
set("log.stdout",true)
# Disable real-time processing, to process with the maximun speed
set("root.sync",false)
# Enable video
set("frame.video.channels",1)

# The video source using a static image
s = video.image(width=240,height=240,x=40,"/tmp/bla.ppm")
# The audio song.
audio = single("/tmp/bla.mp3")
# The special metadata function, that
# also triggers the shutdown..
def end_meta(_) =
shutdown ()
[("title","prout")]
end
# This is the blank source
bl = map_metadata(insert_missing=true,update=false,end_meta,blank())
# And the final source: the sequence song and blank added
# with the video of the static image..
final = add([sequence([audio,bl]),s])
# Output to a theora file, reopen on new metadata..
output.file.theora(reopen_on_metadata=true,"/tmp/$(title).ogv",
final)
The result is just what I wanted (surprisingly !): The other videos can be found here.

26 December 2008

Sandro Tosi: Biggest -doc packages

After loosing a lot of time (because I couldn't remember awk syntax correctly), now I know what are the biggest -doc packages in sid:

$ egrep "Package:.*-doc ^Size" /var/lib/dpkg/available grep -A1 "doc" grep -v "^--$" awk ' if ( $1 ~ "Package:" ) pkg = $2 else print $2" "pkg ' sort -n tail -n 3
77647098 vtk-doc
86947420 libxmpp4r-ruby-doc
107700626 sofa-doc

don't say it's ugly, I know ;)

What's the purpose of this? I wanted to know what medal new version (0.98.5) of python-matplotlib-doc package would win, and that would be silver!!

$ ls -l python-matplotlib-doc_0.98.5-1_all.deb
-rw-r--r-- 1 morph morph 91141234 2008-12-16 10:39 python-matplotlib-doc_0.98.5-1_all.deb

I really hope to reduce it before upload it...

23 December 2008

Emilio Pozuelo Monfort: Collaborative maintenance

The Debian Python Modules Team is discussing which DVCS to switch to from SVN. Ondrej Certik asked how to generate a list of commiters to the team s repository, so I looked at it and got this:
emilio@saturno:~/deb/python-modules$ svn log egrep "^r[0-9]+ cut -f2 -d sed s/-guest// sort uniq -c sort -n -r
865 piotr
609 morph
598 kov
532 bzed
388 pox
302 arnau
253 certik
216 shlomme
212 malex
175 hertzog
140 nslater
130 kobold
123 nijel
121 kitterma
106 bernat
99 kibi
87 varun
83 stratus
81 nobse
81 netzwurm
78 azatoth
76 mca
73 dottedmag
70 jluebbe
68 zack
68 cgalisteo
61 speijnik
61 odd_bloke
60 rganesan
55 kumanna
52 werner
50 haas
48 mejo
45 ucko
43 pabs
42 stew
42 luciano
41 mithrandi
40 wardi
36 gudjon
35 jandd
34 smcv
34 brettp
32 jenner
31 davidvilla
31 aurel32
30 rousseau
30 mtaylor
28 thomasbl
26 lool
25 gaspa
25 ffm
24 adn
22 jmalonzo
21 santiago
21 appaji
18 goedson
17 toadstool
17 sto
17 awen
16 mlizaur
16 akumar
15 nacho
14 smr
14 hanska
13 tviehmann
13 norsetto
13 mbaldessari
12 stone
12 sharky
11 rainct
11 fabrizio
10 lash
9 rodrigogc
9 pcc
9 miriam
9 madduck
9 ftlerror
8 pere
8 crschmidt
7 ncommander
7 myon
7 abuss
6 jwilk
6 bdrung
6 atehwa
5 kcoyner
5 catlee
5 andyp
4 vt
4 ross
4 osrevolution
4 lamby
4 baby
3 sez
3 joss
3 geole
2 rustybear
2 edmonds
2 astraw
2 ana
1 twerner
1 tincho
1 pochu
1 danderson
As it s likely that the Python Applications Packaging Team will switch too to the same DVCS at the same time, here are the numbers for its repo:

emilio@saturno:~/deb/python-apps$ svn log egrep "^r[0-9]+ cut -f2 -d sed s/-guest// sort uniq -c sort -n -r
401 nijel
288 piotr
235 gothicx
159 pochu
76 nslater
69 kumanna
68 rainct
66 gilir
63 certik
52 vdanjean
52 bzed
46 dottedmag
41 stani
39 varun
37 kitterma
36 morph
35 odd_bloke
29 pcc
29 gudjon
28 appaji
25 thomasbl
24 arnau
20 sc
20 andyp
18 jalet
15 gerardo
14 eike
14 ana
13 dfiloni
11 tklauser
10 ryanakca
10 nxvl
10 akumar
8 sez
8 baby
6 catlee
4 osrevolution
4 cody-somerville
2 mithrandi
2 cjsmo
1 nenolod
1 ffm
Here I m the 4th most committer :D And while I was on it, I thought I could do the same for the GNOME and GStreamer teams:
emilio@saturno:~/deb/pkg-gnome$ svn log egrep "^r[0-9]+ cut -f2 -d sed s/-guest// sort uniq -c sort -n -r
5357 lool
2701 joss
1633 slomo
1164 kov
825 seb128
622 jordi
621 jdassen
574 manphiz
335 sjoerd
298 mlang
296 netsnipe
291 grm
255 ross
236 ari
203 pochu
198 ondrej
190 he
180 kilian
176 alanbach
170 ftlerror
148 nobse
112 marco
87 jak
84 samm
78 rfrancoise
75 oysteigi
73 jsogo
65 svena
65 otavio
55 duck
54 jcurbo
53 zorglub
53 rtp
49 wasabi
49 giskard
42 tagoh
42 kartikm
40 gpastore
34 brad
32 robtaylor
31 xaiki
30 stratus
30 daf
26 johannes
24 sander-m
21 kk
19 bubulle
16 arnau
15 dodji
12 mbanck
11 ruoso
11 fpeters
11 dedu
11 christine
10 cpm
7 ember
7 drew
7 debotux
6 tico
6 emil
6 bradsmith
5 robster
5 carlosliu
4 rotty
4 diegoe
3 biebl
2 thibaut
2 ejad
1 naoliv
1 huats
1 gilir

emilio@saturno:~/deb/pkg-gstreamer$ svn log egrep "^r[0-9]+ cut -f2 -d sed s/-guest// sort uniq -c sort -n -r
891 lool
840 slomo
99 pnormand
69 sjoerd
27 seb128
21 manphiz
8 he
7 aquette
4 elmarco
1 fabian
Conclusions:
- Why do I have the full python-modules and pkg-gstreamer trees, if I have just one commit to DPMT, and don t even have commit access to the GStreamer team?
- If you don t want to seem like you have done less commits than you have actually done, don t change your alioth name when you become a DD ;) (hint: pox-guest and piotr in python-modules are the same person)
- If the switch to a new VCS was based on a vote where you have one vote per commit, the top 3 commiters in pkg-gnome could win the vote if they chosed the same! For python-apps it s the 4 top commiters, and the 7 ones for python-modules. pkg-gstreamer is a bit special :)

21 December 2008

Julien Blache: This project should remain open and openminded

David, I m not saying it lightly: the end goal is censorship, no matter how nicely you try to put it. The goal is to discourage people from posting. They call it peer pressure , which is nothing else but the politically correct equivalent expression for intimidation . The end result is censorship. The idea of censoring the mailing lists has actually been mentioned very clearly in the recent discussions on -devel, and I never thought it would go past that, but it s actually happening. By the way, this could actually morph into a shitty karma system that wouldn t let you post past your monthly allowance and credit earned . How s that for you? You refer to those +1/-1 mails; I find them silly, annoying, useless and a waste of bandwidth and CPU time. That used to be called a me too and generally despised and frowned upon. If you actually want to score posts or posters, get a decent MUA and set up its scoring system the way you like. But keep that to yourself. As Aigars told, there are mail to web forum gateways (more like rendering engines for a mail archive, actually) that will present mails to a list in a crappy web forum of some sort that will come with all kind of crap like scoring, karma and whatever. There s an essential difference between web forums and our mailing lists, though: forums of this kind use nicknames all over the place, our mailing lists use real names. There are privacy issues involved, and I m not giving up on that, either. You want to stop flamewars? Stop replying, especially to tell how intolerable it is and other shit. Just let the damn thing die already. Funny how the well-meaning people are feeling harassed on the mailing lists when they, themselves, are harassing people they disagree with. We don t all have the same views, culture etc. We re not all friends, and we probably never will be. Guess what? It s OK! Get over it and work with each other, because that is what we are here for. If you (general) can t get over it, I m afraid this Project is not the appropriate place for you. Imposing a monoculture of politically correct crap is not an answer to the perceived problems .

13 December 2008

Gunnar Wolf: Startups here and there

David Welgon has a nice post regarding his opinions on pros and cons on running a startup in Europe (Italy) and the USA (SF/Bay area). The first of the Italy cons got my attention:
Less of a startup culture and mentality. It's more typical to get a "job for life" and hang on to it for all you're worth. Many Italians are tremendously creative, industrious, inventive people, but are going to find it more difficult to express that in some form of business.
I know I am unlike many people, specially in this field... But anyway. I live in Mexico. Many factors in The Way Things Work are pushing people towards having an enterpeneur mentality - And what you see as a point against, I see as a very big advantage.
Some people have what it takes to run a business, and that's great. However, I think it is wrong to assume most people will benefit from running their own business - And specially in a country as mine. I cannot speak much about Europe, but from what you say, it confirms it is a good model of what I'd like Mexico to morph into.
Too many people start their companies with dreams of glory, thinking they have something to differentiate from the rest of the marketplace - and they lack it. So instead of enriching an existing company with more, and better focused, technical talent, they will end up making it poorer with yet another generic company with nothing new to offer, paying famelic wages to their employees, finding a way to skip the social security payments. And there are lots of legal ways to do so in Mexico - and a growing segment of the population has neither health care nor retirement savings, as this makes their day-to-day incomes substantially more juicy... But the future will bite them hard. Well, not only them - It will bite all of us. I still think we will inevitably, sooner or later, evolve into a more caring society, a society where the strong protects the weak, where it (via the State, the government) ensures nobody has under the minimum needed to have a decent life.
And, although I am essentialy a Socialist at heart, I do recognize there is place for people getting more money than others - After all, courage and creativity should be encouraged, and true enterpeneurs should get compensed for what they give to the society - But the ridiculous, stupid differences we get to see, specially in third world countries (remember that the world's richest man, Carlos Slim, lives on the same city I do, and around ~15 years ago even lived less than five blocks away from me... But I do have close family where having food daily on the table is far from a fact) are something that should disappear for good.
Loyalty to your employer and long-term job commitment are two values I hold very dear, and hope to be able to practice. So far, I have worked for eight years for UNAM (1999-2003 and 2005-present), and I hope to continue here for many years to come. I was just talking about this with a friend - The payment itself is far less than what I could get somewhere else, but the work conditions and long-term viability are more than enough to repay for the difference. And I am sure many of my friends and acquintances would be much better off if they stopped prioritizing getting more money now in respect to leading a better, richer life - And, of course, if we all valued more giving back to the society, as we will probably all need to ask from it sooner or later.

13 November 2008

Sandro Tosi: Parse Python files for "import" statements

My goal is to collect all the import statements in a Python code tree to identify what modules are needed to run that piece of code. So let's start from the lower level: parse one file for its import.

One simple solution could be to grep (or re.compile) something like "import (.*) from (.*) import .*" but what for import statement like:
from  import (
ABC,
DEF,
GHI)
or multiple import on one line?

So, if I had to rewrite the Python interpreter parser, why not use that exact parser?

I started with the parser module, but its output is not so parsable :) even if you can recall the structure (i.e. import statements are at nodes with id = 282, with imported module at id = 287 and so on). It's really powerful, but too low level for this task.

But there is another interesting module: compiler (it's deprecated in 2.6 and removed in 3.0, but I'm working with 2.5, so it's fine). Using parseFile and some objects from compiler.ast, I wrote a simple script that parses a file given in input and prints out the modules imported with "import mod" or with "from mod import xxx".

Suggestions are always welcome :)

UPDATE: please note that conditional imports are included in the list and the calls to __import__ are ignored.

31 October 2008

Andrew McMillan: Graphics in OpenOffice.org: SVG, EPS and WMF

When Heather designed a logo for me for Morphoss she did it with a bitmap editor, naturally enough because that's the tool she's most familiar with using. I'd rather not use a bitmap as the source format for the logo though, because it will degrade when it gets resized, so I redrew it as a vector graphic. One of the best free, open-source tools around for vector graphics seems to be Inkscape and I've mucked around with it for many years, so I naturally used that. Once you have a logo though, you naturally want to use it in documents, and the importing of SVG graphics into OpenOffice.org documents is a long-outstanding bug (let alone embedding SVG graphics) so I needed to convert them to another format. It's actually the most requested feature in OOo, appearing twice in the top 10, and even spawning an external SVG importer project. Since both programs support encapsulated postscript I was able to save the logo from Inkscape as .eps and use it directly in OpenOffice.org. While this initially seemed satisfactory, after a few weeks of using documents with the .eps logo embedded in them I started to get annoyed with the strange pauses when my CPU was maxed out while paging up and down. I was sure that that had not happened in the past when I was using a logo in WMF format, which OOo inevitably has to support well for compatibility with other Office Suites. After some searching around for more complicated ways to convert SVG or EPS to WMF, I discovered that what I could do was simply to open the EPS in OpenOffice.org draw, and save it from there as a WMF. This seems to work well, for my purposes anyway, so now when I use my logo in my OpenOffice.org documents I don't see any annoying slowdown paging up and down within the document, and I didn't have to download the SVG importer for OpenOffice.org either. Well alright, I did download the SVG importer as well, but my logo didn't look nearly so good without it's text, and with everything displaced up and to the right at various offsets!

11 October 2008

Andrew McMillan: Shiny New Laptop

After a few years of only buying laptops with Intel hardware, today I bought something totally different. It's not really what I wanted (which was an HP HDX 16t) but I get the feeling that none of these 16" HD 1080 laptops will make it to New Zealand for a while yet, and the NZ dollar has done such a nosedive recently that it's better not to wait any longer. In the places that hold stock there seem to be some good specials around at the moment, and as the owner of a new free, open-source consulting business (i.e: a cheap bastard) I went shopping for the cheapest dual-core I could find with a half-decent screen, and I found the Asus X53K for $999 (USD$589) at Dick Smith, including a 2G ram upgrade to take it to 3G. It's entirely non-intel, with a 2GHz Turion dual-core, ATI Radeon X2300 with 1440x900 panel, Atheros AR2425 wifi and 160G HD. I'd bought a replacement 320G hard drive even before I got the laptop, so now I have a pristine, unbooted 160G hard drive with the install files for some other OS on it - no doubt I'll find a use for the disk, at least! Since AMD got ATI to release all their chip documentation earlier this year I felt able to shell out for this, rather than the extra $100 for the model next to it, and it was nice too to get home and find that Atheros have recently released the HAL for their a/b/g chips. Which presumably means that they haven't done so for their 'n' chipsets, and I should continue to steer clear of that technology for a while yet... I'm running Debian GNU/Linux 'Sid' on the Asus X53K and, everything pretty much just works out of the box. My installation process was to rsync the old laptop onto a new disk, and boot the new laptop from that - after compiling a new kernel more appropriate to the changed hardware. After overcoming my own stupidity in not syncing the /dev/ underneath udev, which I easily googled my way out of, the only problem I've found so far is that the free radeon driver doesn't do 3d for me. Presumably the non-free ones would, but they won't compile against my 2.6.27 kernel so I don't know for sure. Fortunately I don't use 3d for anything so it's not a huge inconvenience to me. With 3G RAM and a fast 320G hard drive the laptop actually is an upgrade for me, too, and it has a webcam too, which I expect I'll look at in much the same way as I did the fingerprint reader on the old laptop. It will be good to finally hand that old one back to Catalyst, too, who have given me the flexibility to take my time on this. Now to try and peel off all these stickers without damaging anything!

1 September 2008

Gunnar Wolf: Think little

Back from Argentina, back from DebConf. As always, the ~3 weeks I spent there were really great, in as many fronts as I can imagine or describe. But I won't go into that now - For the purposes of this posting, the single thing that I got out of DebConf was looking with envy at all the people that had something that used to be called a sub-notebook some time ago, and now morphed into the more modern(?) name netbook.
Several people were seen with their tiny Asus Eee machines, of various models. And I definitively decided I want one - I was quite close to buying one in Argentina, as they are readily for sale there (surprisingly, in Mexico Asus sells motherboards, but no netbooks)... But I've always prefered waiting or paying a little premium for having an on-country seller and warranty.

Back home, Pooka told me that several stores in Mexico do sell the Acer Aspire One. After a little research, I decided to go for it. Office Depot sells the AAO for MX$4500 (around US$450). The only model they carry comes with Windows XP installed (instead of Linpus Linux), which is a shame I thoroughly repeated to the vendor - But it does come with 1GB RAM and 120GB HDD, much better for my needs than the other model, with 512MB RAM and 8GB SSD. This is, after all, a full (although very small) machine. It has an Intel Atom 270 CPU - I haven't yet measured how it fares, but it feels quite responsive so far for typical desktop tasks.
But what made me really happy about it is the Debian support. The only tricky part was to get the installer going, as it does not have a CD drive to boot from (and I didn't want to completely overwrite my only available USB stick's data). Don't try installing Debian Etch, as its kernel will not support the built-in Realtek RTL8101E network card (maybe etch-and-a-half's kernel does?). My greatest ally in this was, of course, the wiki.debian.org article on the Acer One - I rebooted with Lenny's debian-installer, and everything was smooth from that point on. Propietary firmware is required for the wireless AR5007 card and webcam, but -exactly as documented in the wiki- they are covered respectively by madwifi and linux-uvc.
I did a very regular install, with basically the default desktop and notebook setup. I continue to be amazed... Everything just works! It is not even fun, there are no funny drivers to recompile, no bang-your-head-against-the-wall... Even suspend-to-RAM. It just works.
The only glitch I found so far is that, after suspend-to-RAM, the madwifi module must be removed and reloaded to have wireless network. This is a well-known glitch that can be easily worked around. But besides that, it is... as easy as it gets. And, at such a price, and under 1Kg weight... This computer will get used to go out with me quite often! Battery life is just 2 hours, but for most situations, it's more than enough.

22 July 2008

Andrew Pollock: [tech] Looking for a new colo for my server

Unfortunately the free ride I've had for the last oh, gee, it must be something like four years, is coming to an end, so I have to find somewhere else to co-locate daedalus. Thanks Ben, you've saved me a packet! The first step is to figure out roughly how much traffic this thing is doing. Fortunately I've been running Argus on it for donkey's ages, so I should be able to figure that part out. Then I have to find a colo facility, (preferably in Brisbane, to avoid too much dicking about with moving the hardware), which won't charge me an arm and a leg for traffic. I'd prefer a flat monthly fee if possible. I also need to do some soul searching to decide if it's even worthwhile continuing to keep a physical server. I could move my mail to Google Apps, the photos to Picasa, but I kind of like my blog the way it is. I spent a non-trivial amount of money of daedalus about 3 years ago. It's a grunty server. It seems something of a shame to get rid of it, but I could potentially get a virtual server a lot more cheaply. The other option would be to try and generate sufficient income with it to cover its costs, but that has all sorts of tax implications, not to mention having to maintain a service level agreement. I really don't have the time or inclination to be doing all of that on the side. All stuff to think about. I have an amorphous month to move my server, so if anyone out there has suggestions on a colo provider in Brisbane, please drop me a line.

6 July 2008

Mike Hommey: webkit 1.0.1 in unstable

There has finally been an official webkit release for the Gtk+ port, and I finally took the necessary time to package it. As you can guess from the screenshot above, it now has plugins support. It is also ber fast. You can compare with previous results for both gecko and webkit.

17 June 2008

Kapil Paranjape: A flipping trick

I have been trying to find a good way to explain the fact that the fundamental group of the group of rotations in dimension 3 is isomorphic to the multiplicative group +1,-1 . The first step is to identify the group of rotations with the configurations of a person standing vertically on the surface of the earth. In other words, each configuration is a point on a sphere and a direction (along the sphere) at that point. The above statement above can then be translated as follows. Consider all trajectories which start and end with me standing in Ecuador (on the equator) facing north. One such trajectory has me turning clockwise on my heels, while another has me turning anti-clockwise instead. Then the above statement says that there is a "continous deformation" of the first trajectory into the second! One problem is that explaining the term "continous deformation" is not easy! However, the following proof explains what one has in mind. Consider all circular tracks that have me travelling towards my right while facing a point (exactly) north of Ecuador. When this point becomes the north pole, I am travelling towards my right on the equator facing north. Similarly, consider all circular tracks that have me travelling towards my right while facing away from a point that is exactly south of Ecuador. When this point becomes the south pole, I am again travelling towards my right on the equator facing north. On the other hard, consider what happens as the centre of the circular track comes close to Ecuador and ends up somewhere near my shoes. In the first case, I am turning anti-clockwise on my heels, while in the second, I am turning clockwise on my heels! I am sure that there much better and more striking ways of explaining this to a lay audience, but I'm still looking for them ... Perhaps, I need to travel to Ecuador to get a better idea. To do that and come back to India, I need to find a hospital that will give me a Yellow Fever vaccination. Anyone knows one?

7 June 2008

Dirk Eddelbuettel: Into the sunset

I finally got around to dropping four old computers off to recycling. Triton, a community college nearby, had a recycling event where students volunteered, and so I finally got around to dropping two generations of old computers off. Old computers, I hear you ask, well how old? Real old. The older two were from an age where the bios didn't yet boot off cdroms -- circa 1995. We had bought those in Kingston just off the Queen's campus. These were respectively a pentium 90 and a pentium 100, which still have traces on the web as miles.econ.queensu.ca (e.g. in a number of Debian changelogs) and rosebud.sps.queensu.ca which was of course Lisa's office machine and for a while the only internet address showing SPS. The next two were purchased around 1999 in Toronto on College St just north of U of T's main St George campus. Those, an AMD k6-2 300 and a Celeron overclocked to 450 MHz (woot :) lived happily in the basement of our Toronto home, forming the first lan I built. If I recall they were initially connected using a crossed ethernet cable and a second nic to the ISP. Oh boy. At least those latter two still boot off Knoppix. And do they ever feel slow. To think now just how many Debian packages I must have built on at least three of these over the years... And each machine must have gotten at least five decent years of usage out of them. One of the second generation computers eventually morphed into the kids play computer but even retired from that a while ago. In any event, it was good to have them recycled, and also good to have been able to do so without paying a fee as is increasingly common. So cheers to Triton. I may be back in a few years as there are still a few computers spread across the house.

9 May 2008

Amaya Rodrigo: Of life and vermin

One morning, when Gregor Samsa woke from troubled dreams, he found himself transformed in his bed into a horrible vermin. -- Metamorphosis by Franz Kafka

12 April 2008

Mike Hommey: xulrunner++, webkit++

I uploaded xulrunner 1.9~b5-1 yesterday, and today was webkit’s turn, with an upload of svn revision 31841, which happens to be the last revision on trunk as of writing. Thanks to Mark Rowe, the most problematic crashers I experienced with webkit while preparing this upload have been fixed in revisions 31821 and 31787. This had the side effect to delay the upload enough that we now have the benefit of improved SVG animations support, and CSS gradients. For those who like numbers, you can take a look at the Sunspider results for xulrunner 1.9~b5 (running mybrowser ; very similar results to what I got with 1.9~b4), and Sunspider results for webkit r31842 (when you compare to previous results for webkit r27674, there are significant improvements). For another kind of numbers:
~/git/xulrunner$ git diff upstream/1.9... filterdiff -x b/debian/* -x a/configure diffstat tail -1
36 files changed, 507 insertions(+), 291 deletions(-)
Compared to:
~/git/xulrunner$ git diff upstream/1.9...1.9+b4-1 filterdiff -x b/debian/"*" -x a/configure diffstat tail -1
53 files changed, 932 insertions(+), 466 deletions(-)
~/git/webkit$ git diff upstream... filterdiff -x b/debian/* diffstat tail -1
1 file changed, 4 deletions(-)
Compared to:
~/git/webkit$ git diff upstream...0+svn27674-4 filterdiff -x b/debian/* diffstat tail -1
17 files changed, 61 insertions(+), 18 deletions(-)
Somehow, I prefer to work on webkit…

3 April 2008

Joachim Breitner: Distance Map Morpher

In my last blog entry, I was asking for algorithms to morph a picture so that contour lines would become circles. I then started to write some python/gtk/cairo code to actually visualize my thought. It came out relatively pretty, so I made the GUI around it usable (although far from nice, I guess) and put the current, early version in a darcs repostory (DarcsWeb browser available).
This is a screenshot (click for full version) of a map of my part of town, shamlessly stolen off the internet. The red shading shows the distance from the thick point of the graph the redder, the closer. On the right the image is morphed so that all points on a circle around the center have the same distance to it. The blue shape on the left and the blue circle on the right are points with distance 205.Below the user canCurrently, there is one algorithm to determine the distance of a point to the center: Travel along the graph to the most suitable edge, leave at the point closest to the target and then go crossroads , which comes at a greater cost.There are some things to do, most notable:Comments and patches are, as always, welcome. If you want to try it out make sure you have python2.5, pygtk and numeric-python installed.

Joachim Breitner: How to make contour lines circles?

Dear lazyweb, I have a question with regard to image manipulation. Given an rectangle image with a continous function on it (in my case, walking distance from a certain point), I can easily draw the contour lines of the function, i.e. for a given distance from the center mark all points that have this distance. This looks very similar to the contour lines of height map. I d like to morph this image now that all these contour lines are circles around the centers, but I don t have a good idea how to do that with a minimum amount of distorting. Any suggestions or pointers to algorithms are welcome.

31 March 2008

Eric Warmenhoven: Rewriting as a learning tool

So a year and a half ago, I mentioned I was trying to learn Haskell, and I still am. It’s been going much more slowly than I hoped, since I haven’t really spent any time on it. I never write anything new anymore! So I decided to rewrite something I had previously written myself, need be damned. So I chose the RSS aggregator I wrote, harsh. harsh hasn’t changed in eleven months (and that change was just about making the location of its configuration file configurable), but I still remembered how it worked pretty closely; at least enough that I didn’t have to really go searching through its code too much. That’s probably also a function of how small harsh is; in terms of lines of code (excluding blank lines):
  config.c: 139
  cookie.c: 221
 display.c: 709
    feed.c: 577
    list.c: 96
    list.h: 16
    main.c: 96
    main.h: 84
     md5.c: 360
     md5.h: 76
     rss.c: 120
     xml.c: 276
     xml.h: 17
     total: 2787
It uses expat to parse the HTML, libnbio for socket management (which is available in Debian), and ncurses for the UI. It doesn’t have any sort of threading (libnbio does a good job of making sure that, other than DNS lookups, there’s never anything going on long enough to prevent responsiveness). About its only feature is that it will use my cookies.txt file, so that I can see my LiveJournal friends’ protected entries. I originally wrote harsh in about a day or two. It was really easy because of the 2800 lines, about 850 of them had been written in some of my other projects (list.c/h and xml.c/h) or are standard (md5.c/h). I was also really familiar with the three helper libraries from writing grim (my IM client) and stark (a tool for viewing GnuCash data files). As a learning exercise, rewriting harsh in Haskell was excellent. It’s incredibly small, does a lot of standard things (like networking and console UI), and doesn’t do a lot of non-standard things (like an AIM client does). I got to play with the Haskell light-weight threads and STM; I learned how to create a Debian Haskell package; I learned how to use ghci as a debugger with breakpoints; and I’m much more comfortable with monads and with the language in general. It did take me significantly longer to write than the C version, though that’s more due to me having to learn not just the language but some libraries along the way (like HTTP, Vty, and HaXml). I still think that it would take me just as long to write the Haskell version as the C version, but I’m still much more comfortable with C, and imperative programming in general. From a code size perspective, the Haskell version is about one-sixth the size (excluding comments):
Config.lhs: 53
  Feed.lhs: 144
 Harsh.lhs: 272
  Util.lhs: 26
     total: 495
However, that’s not a very fair comparison. In the C version, md5.c/h are included in the total count, when really they should be considered a standard library (and on the Haskell side, I used Data.Hash.MD5 from MissingH). On the C side, I did all of the HTTP request and response processing myself (which is what more than half of feed.c is about), while on the Haskell side I left that to an HTTP client library. Excluding all those things though, the Haskell version is still about one-fourth the size. Anyway, I put the Haskell version of harsh up here. If any Haskell hackers out there could take a look at it and let me know what I’m doing wrong or oddly, I’d appreciate it.

Next.

Previous.