Thursday, 10 September 2009

How to mount *.bin disk image on Linux/Mac (without *.cue file)

First, you need binchunker - a utitily to convert the bin/cue pair into an iso image. It is available on macports and should be easy to get on most linux distros.

Now, you need to prepare your *.cue file. Suppose the you have a "blah.bin" file. Enter following text into "blah.cue":

FILE “blah.bin” BINARY
TRACK 01 MODE1/2352
INDEX 01 00:00:00
Now, enter the following spell:
bchunk blah.bin blah.cue blah.iso
There, you have it.

Thanks to these guys for help.

Thursday, 14 May 2009

Reporting assertions as a way for test parametrization

There's been a discussion recently on Testing In Pyton mailing list on introducing test parametrization. Here's my approach to the problem.

The idea, instead of finding a way to generate test methods, is to promote assertions to report the results in similar manner that testmethods do. In order to achieve that, I had to override few methods in TestCase, but the resulting API looks quite clean.
You can grab the source from here. And here's an example. Run this:

import unittest
from reporting_assertion import TestCase, reporting

class MyTestCase(TestCase):
@reporting
def some_assertion(self, a, b):
assert a == b
def test_example(self):
for x in (1, 2, 3):
self.some_assertion(x, 2)

if __name__ == "__main__":
unittest.main()
In order to get this report:
$ python example.py   
FF.
======================================================================
FAIL: test_example.some_assertion(1, 2) (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/[path]/reporting_assertion/reporting_assertion.py", line 12, in wrapper
ret = assertion(self, *args, **kwargs)
File "example.py", line 8, in some_assertion
assert a == b
AssertionError

======================================================================
FAIL: test_example.some_assertion(3, 2) (__main__.MyTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/[path]/reporting_assertion/reporting_assertion.py", line 12, in wrapper
ret = assertion(self, *args, **kwargs)
File "example.py", line 8, in some_assertion
assert a == b
AssertionError

----------------------------------------------------------------------
Ran 1 test in 0.001s

FAILED (failures=2)


This approach has few drawbacks. You can't collect assertions when doing collect-only run, it's tightly coupled with TestCase implementation (needs to know how to report results), and - for the same reason - it works only for assertions bound to TestCase instance (the decorator has an optional _self= keyword argument for decorating unbound assertions, but the results are not reusable across TestCase instances). The last problem is __str__ evaluation: if the objects under have side-effects in this method, you might get quite unexpected results.

It is, however quite powerful: the data fed into the assertions is generated in the code itself (so the parameters don't need to be static). It's also very easy to use: just decorate your assertion in order to get the reports.

Monday, 9 February 2009

Quote

I read git magic today and found a link to the original thread on LKML. One of neat quotes in there is a line from Linus' post dated 8th of April 2005:

"git" is really trivial, written in four days. Most of that was not actually spent coding, but thinking about the data structures.

Monday, 2 February 2009

Generic constructor assertion

It is quite common to write such initializers:

class Foo(object):
def __init__(self, a, b):
self.a = a
self.b = b
Why not test it in a generic way?
import inspect

def assert_simple_constructor(klass):
allargs = inspect.getargspec(klass.__init__)[0]
args = allargs[1:] # skipping self
instance = klass(*args)
for argname in args:
assert hasattr(instance, argname) # skipped the message
assert getattr(instance, argname) == argname # to keep short

Sunday, 25 January 2009

Why "Why 'Why OO Sucks' Sucks"... exposes ignorance

A year and a half ago, I wrote a blog post which questioned some statements from Joe Armstrong's 'Why OO Sucks' article. While I still can't agree with all the article, I can see what he *really* meant and what I misunderstood then.

So let's get back to the original article and its statements:

1. Data structure and functions should not be bound together.

My response to that went mainly along the lines of "but that's how people tend to think, isn't it". However, what I think now is... well why not? Even in functional languages functions that handle specific types of data know the details of the data, so in order to understand the function you need to know what the data looks like. In order to use that function you need to feed it with the specific type of data it needs. Not so separate anymore?

Binding data and functions in OO languaged serves mainly two purposes: either to give some specific view or attribute of an instance (in which case they're nothing more than a convenient interface pure function calls) or to change the instance's inner state (to which I'll get back later).

2. Everything has to be an object.

Again, I said it's comfortable and natural to consider data as objects, but what I didn't know by then was the difference between classes and data types. I didn't know yet about pattern matching and other ways of working with immutable data. All those techniques make working with it equally comfortable and natural (maybe in more mathematical spirit, but I doubt it should be a disadvantage for anyone).

A little wiser now, I'm quite convinced that this argument comes down again to objects having private state. If there was an OO language where all objects would have to be immutable, I think the need of turning every piece of data into an object wouldn't be so painful.

3. In an OOPL data type definitions are spread out all over the place.

OK, here I was silly. First, I wrote "OO laguages" while *clearly* thinkng "Java" (well, that was the single OO language I knew then). Second: I totally forgot about inheritance.

What I think now is that there's no much difference here between OO and functional languages. If you consider inheritance as a specific case of composition (which it is) you get an equivalent of nested data types with functions handling one type are using other functions to handle the other. Not much difference from functional languages.

4. Objects have private state.

Ah, so here we have it. After playing a bit with functional languages I learnt that state, while unavoidable, is in fact a nasty bastard. Joe Armstrog doesn't like the way the state problem was solved in OO languages. They go along the lines of "yeah... we have state, but don't mind it. As long as you give us correct requests you'll be fine", which isn't true because giving correct requests (calling correct methods) requires to know the state in the first place.

The functional languages tend to use pure functions what lets them access the state only when neccessary (and FPL desingers solve the state problem in several different interesting ways).

To be honest. I kind of agree with that now. I don't like mutable objects. You never know what to expect from them :)

Ah, and my arguments here were also quite silly. First: I felt already that state is not so good, but only in the context of multithreading. Second: I was a fan of information hiding and working with tightly encapsulated data. While I'm not saying that encapsulation is bad (on the contrary!), I think I understand it differently now.

Encapsulation is not putting something in black box and forcing others not to see the its inner parts. It's rather finding a "sweet spot" in control flow: the interface that would be convenient enough for anyone to use without a need to look deeper. In other words: I don't associate encapsulation with information hiding anymore.

Concluding this longish article: I still don't agree with the statements of Joe Armstrong's article - in particular: the quiet assumption that a good language is a functional language. But I have to admit that my former article was based mainly on ignorance and misunderstanding Joe Armstrong's arguments.

And I still don't like the conspiration theory in the last paragraph there :)

Monday, 19 January 2009

ilen for Python

Today I came across what turned out to be not-so-common need. I wanted to get the length of the generator. Before you comment - yes, I know generators can yield infinite sequences, and that might be one of the reasons why such a function is nowhere to be found. However, if one knows what one's doing it can be of some use. After all, calling list() constructor on iterables is equally risky. Of course, the function is trivial, but managed to give me that that-must-be-somewhere-already feeling. It wasn't :(

def ilen(sequence):
result = 0
for _ in sequence:
result += 1
return result
BTW. I think itertools is my favourite Python module, what's yours?

Thursday, 1 January 2009

Howcome so many 8s?

Below, you can see plot of the results of the following code:

import sys
for x in range(200):
print x, sys.getrefcount(x)
I read recently that integers less than 256 are being interned by CPython interpreter, so I took a look at how they are used. First 80 integers has about 20 refs, with much bigger number for the initial couple of numbers. Then the refcount is usually less than 10. For some reason, there is a whole lot of references to the number 8.



EDIT: I didnt' notice the 8's leap on debian machine. It's reproducible though on my mac.