Anything Else

Tuesday, July 31, 2007

Sanjay Dutt, You Were Wronged

TADA court ordered 6 years jail to Sanjay Dutt for possessing illegal weapons.

What he did, was a victim less crime. In US and many other countries he would not have been wrong at all. It might be debatable that possessing arms is wrong, but it would be completely wrong to say that there is no reason to possess one. It was after the riots in Mumbai that he acquired those arms, in self defense. What is immoral about it? Technically wrong, agreed, but immoral?
"I must say for every citizen, laws of the nation shall be respected. If you don't, I don't expect you to be called a moral person," Kode said.
 

So what he means is every person who is wrong on technical grounds is wrong on moral grounds, and technicality is the only definition of morality? Judge Kode himself later agrees that Mr Dutt's act was not immoral, why then the misleading argument?

Further:

Kode also observed it was an "eminently dangerous act" as the weapon possessed by Dutt was capable of mass destruction though the accused had not used the weapons.

I guess Sanjay Dutt had lighter and matches too, I guess it was "eminent" that he was going to set ablaze a few petrol pumps and buildings, and he had access to cars too, pedestal walkers should consider their death "eminent". Wouldn't it been easy for judges if possessing means of potential crime is enough to prove the guilt for crime, but we are lucky and thankful that so is not the case.
Kode said the character of the accused is very important while considering if they deserved relief under the POA(sic, POTA) Act. He pointed out that apart from possessing the weapons, Dutt was a close acquaintance of Anees Ibrahim and attended a party hosted by Dawood Ibrahim in Dubai.

The character of the accused. It is so easy to judge, isn't it, Dutt knew those criminals, he attended their parties, and was friends with them. Being friend with criminals is now criminal? What about his friends then? And his friends friends? Is prosecutor's case completely based on bull shit? He had gun, and I am full of shit, so please your honor punish him!

It was for self defense.

If there is any situation that will become better thanks to easy gun access, it is riots. Rioters don't use guns to riot. Rioters are general population, the person sitting next to you may have stabbed a few had he got a chance of being on the favorable side of mob. One has to understand such riot, they are not precursor to civil war, and unless they are precursor to civil war, any amount of guns in the mix will only defuse the situation. Can things go the civil war way? Civil war does not depend on possession of guns, it depends on the lack or dissatisfaction with governance. A gun shot is a serious affair, guns are registered, any shot scares the hell out of people, if I have one, and 20 people step on my door with torches and swords, they will be deterred by the gun. What if they had guns themselves? The stakes will be higher. If the rules of fight were that only knives and swords are allowed, fight will last much longer, and the outnumbered has no real chance of inflicting damage on the rioters, and rioters can march virtually without any consequence to 20 houses one by one. If guns were allowed, anyone shooting in the crowd will get someone, and at-least a death of rioter is guaranteed even if rioting against a single person. Police is no where to be found in those situation, you are on your own, and gun is your only defense. Sure if those 20 people out to murder me had guns, I can be killed sooner, but I get a chance to inflict some damage myself, that my kitchen knife will not give me. Those 20 will kill me no matter what, if they are empty handed, have ropes, knives, sword, or guns. I can kill *only* when I have gun. The problem is not gun, the problem is 20 people who decide to murder someone, and while state and police should do something about it, I should not be denied my right to self defense.

If you can't understand this, may be you can't understand.

Here is the Indian Arms Act 1959, on penalties page, these are the following sections that apply to this case:
27. Punishment for possessing arms, etc., with intent to use them for unlawful purpose
 
Whoever has in his possession any arms or ammunition with intent to use the same for any unlawful purpose or to enable any other person to use the same for any unlawful purpose shall, whether such unlawful purpose has been carried into effect or not, be punishable with imprisonment for a term which may extend to seven years, or with fine, or with both.

The intent to use the guns for unlawful purpose was not proved so this can not apply. Then:
28. Punishment for use and possession of firearms of firearms or imitation firearms in certain cases
Whoever makes or attempts to make any use whatsoever of a firearm or an imitation firearm with intent to resist or prevent the lawful arrest or detention of himself or any other person shall be punishable with imprisonment for a term which may extend to seven years, or with fine, or with both.

Explanation.---In this section the expression "limitation firearm" has the same meaning as in section 6.

Emphasis mine. This was also not the case.

Finally:
29. Punishment for knowingly purchasing arms, etc., from unlicensed person or for delivering arms, etc., to person not entitled to possess the same Whoever---

(a) purchases any firearms or any other arms of such class or description as may be prescribed or any ammunition from any other person knowing that such other person is not licensed or authorised under section 5; or

(b) delivers any arms or ammunition into the possession of another person without previously ascertaining that such other person is entitled by virtue of this Act or any other law for the time being in force to have, and is not prohibited by this Act or such other law from having, in his possession the same;

shall be punishable with imprisonment for a term which may extend to six months, or with fine of an amount which may extend to five hundred rupees, or with both.

This applies. 6 months.

Section 30 [Punishment for contravention of licence or rule] may or may not apply depending on the details of the case, but again, the punishment: 3 months.

I am not making this up, this is what he should be given, maximum of 6 months! He has already done more than a year in the jail.

Oh yeah, there is TADA, a law that has been repealed, that talks about terrorism, which does not apply here. Everything is wrong with this case.

Let me repeat what the judge said:

Kode, however, said the crimes committed by Dutt and his friends Adajania and Nulwalla were not "anti-social, ghastly, inhuman, immoral or pre-planned" and did not cause any harm to the general public.

Morally he does not deserve 6 years. He does not legally deserve 6 years for unlawful possession of arms, possession of arms act forces a upper limit of 6 months for very act he is accused of. He does not deserve to be punished like a terrorist, Judge says he had done nothing anit-social, terrorism would be anit-social one would say. Then why does he have to do 6 years instead of 6 months?

This is judiciaries desperate attempt to say, see we are still alive, we can punish with vengeance in high profile cases. His only crime is being high profile. This is not the case in which justice was done, and someone has to pay the price for this mistake. He has to go to jail because he attended some parties. And this happens when judiciary tries to make a statement about justice. Wonder what happens on day to day life there. 

Sad sad day today.

Label: India Calling


Monday, July 30, 2007

Thread Synchronization Mechanisms in Python

A must read article.

Labels: Python Programming


Sunday, July 29, 2007

dbviews in Django

Came across this comment:

Julian: what we did first was implementing just normal models in the models.py, but that always created the tables in the DB upon “syncdb” (which we deleted then and created views for). Actually I even wrote a patch for django where you can mark a model as “create_table=False” but the patch never made it in.

So we went another actually much better way, after discussing it a lot in the team. We simply did not create the models in models.py, which are used for syncdb but we create a file dbviews.py where we put the views’ models. This is very nice separation of code too.
The next step is writing the view itself, which we just did in pure SQL of course. I.e. if we have the model Forum and we want some specialized ForumActivity-view then we created a view “CREATE VIEW core_forumactivityview” (we are on mysql). We then fired that onto our DB and the model that matched it (make sure to use the same column names as the view does!!!) simply looks like this:

class ForumActiviy(models.Model):
    ….. all the fields
    class Meta:
        db_table = “core_forumactivityview”

now you can simply do

import project.core.dbviews

and they just look like models :-).
Depending on how you wrote the view you might even be able to update the data.

Smart! Learn about MySQL views here.

Labels: Python Programming Django


ThreadLocal Storage In Python

Python has a different semantics of threading.local compared to ThreadLocal in Java. The thing to know is threading.local is a class, and its instance can be used to storing data on it, and data will be unique per thread. Here is a demonstration of its use:

 >>> import threading, time, random
>>> td = threading.local()
>>> class C: pass
...
>>> ntd = C()
>>> class T(threading.Thread):
...     def run(self):
...             td.x = random.randint(0, 100)
...             ntd.x = random.randint(0, 100)
...             time.sleep(random.randint(0, 3))
...             print "td", td.x, "ntd", ntd.x
...             time.sleep(random.randint(0, 3))
...             print "td", td.x, "ntd", ntd.x
...             time.sleep(random.randint(0, 3))
...             print "td", td.x, "ntd", ntd.x
...
>>> ts = [T(), T(), T()]
>>> for t in ts:
...     t.start()
...
td 41 ntd 27
>>> td 41 ntd 72
td 47 ntd 72
td 41 ntd 72
td 97 ntd 72
td 47 ntd 72
td 97 ntd 72
td 97 ntd 72
td 47 ntd 72

As you can see, ntd, an instance of simple object, gets shared across all threads, and all threads see each others changes made on it. Where as td, which is an instance of threading.local has different set of data per thread. 

Labels: Python Programming


Python Import Gotcha And An Advice

In python a module can be imported multiple times, and only at the first import will it be really imported, and subsequently the same module will be returned. This plays a very important role in python, as all kind of singleton class patter or module level initializations that are to be guaranteed to executed only once, relies on this behavior. But this breakdowns when a module can be referenced via two different path. Here is a demonstration:

>>> from path import path
>>> path(".").abspath()
path(u'C:\\Documents and Settings\\amitu')
>>> path("t").mkdir()
>>> import os, sys
>>> os.chdir("t")
>>> path(".").abspath()
path(u'C:\\Documents and Settings\\amitu\\t')
>>> sys.path += [path("..")]
>>> file("t2.py","w").write("""
... print "loading module t2.py"
... """)
>>>
>>> import t2
loading module t2.py
>>> file("__init__.py", "w").write("")
>>> import t.t2
loading module t2.py
>>> from t import t2
>>> sys.modules["t2"]
<module 't2' from 't2.py'>
>>> sys.modules["t.t2"]
<module 't.t2' from 'C:\Documents and Settings\amitu\t\t2.pyc'>
>>>

As you can see the module is loaded twice, with different names. I discovered this when my signal handler was getting called twice in a django project. Further discussion here.  

To avoid this situation, be consistent when importing a module about its path. Either always use package_name.module_name or module_name. Or just make sure pythonpath never contains both a folder and its descendent. 

Labels: Python Programming


Friday, July 27, 2007

HowTo Create Thumbnails

Just dumping a script I just wrote for a friend.

import Image, sys # required PIL: http://www.pythonware.com/products/pil/
from optparse import OptionParser

parser = OptionParser()
parser.add_option("--input", help="Input image path.")
parser.add_option("--output", help="Output file name for the image.")
parser.add_option(
    "--width", default=45, type="int",
    help="Maximum width, in pixels."
)
parser.add_option(
    "--height", default=45, type="int",
    help="Maximum height, in pixels."
)

def main():
    (options, args) = parser.parse_args()
    img = Image.open(options.input)
    img.thumbnail(
        (options.width, options.height), Image.ANTIALIAS
    )
    img.convert("RGB").save(options.output)

if __name__ == "__main__":
    status = main()
    sys.exit(status) 

Python makes it easy. Maintains aspect ratio.

Labels: Python Programming


The Year Of Change

A comment on /.:

The year of change

(Score:5, Insightful)
by phantomfive (622387) on Friday July 27, @01:05AM (#20006527)
(http://cs.byuh.edu/~andrew | Last Journal: Tuesday July 17, @01:15PM)
This is awesome. I haven't felt so happy about the computer world since I was trying to get my commodore64 to flash the boarder colors as quickly as possible. We have Dell selling Linux, (and apparently it's selling well), we have Macintosh sales up 33% from the same quarter last year (and that's even WITH people waiting for Leopard to come out), and Vista adoption is slow. Suddenly it looks as though finally the innovation stranglehold that Microsoft has held over us for many years is coming to an end. I'm not saying Microsoft will go away, but cross-platform compatibility will become the rule, not the exception. It will be easy to choose whichever platform you like, without worrying about not being able to run half your applications. Freedom will be a realistic choice.
I suppose it was really inevitable in the long run, but I am happy to see the walls finally cracking.

Amen!


Thursday, July 26, 2007

Vim: Python Code Folding And My VIMRC

If you were curios about the "# {{{" and "# }}}" in my previous post about extending django user model, they are code folding markers. Getting code folding right in vim took me some time and learning, so here I am documenting the takeaways. Code folding, hiding parts of code that you are not working on, is really cool and helpful, and once you start using it, you can not live without it. Here is how to do it in vim.

Pick The Fold Method 

First of all, you have to decide the method for code folding. Vim offers many methods. First is manual, which is basic, you can fold any piece of text at your whim. This might be good for one off or free form texts. Then comes markers. This is my preferred approach for folding as it can be fairly arbitrary, and it can be preserved in version control and gets shared with multiple developers. Then there is folding by indentation, and language syntax. Both these will let you quickly fold things if you have not manually handpicked folding markers. 

Learn The Keys 

Once the method has been decided, then comes the commands, here is a short list:

  • zf create the fold, useful for manual and marker methods. Select any piece of text, [press v or shift-v, then use arrow keys], and then press zf. It will place the markers around the fold for you in marker mode; in case of manual, it will store fold location in memory. Remember f by saying this command "forms" the fold, or just remember fold :-)
  • zc close the fold at the cursor.
  • zo open the fold at the cursor.
  • zr  increment the fold level by one, so if all classes are folded, they will opened, but function definitions will be kept folded.
  • zm reverse of the above, if one or more function folds are open, they will be closed, but classes will be kept open.
  • zR open all folds.
  • zM close all folds.
  • zj and zk can be used to jump from one fold to another. 

Thats it, that is all you need to know about folding in vim, all commands start with z so they are easy to remember. Z represents a piece of folded paper. From my experience you will be only using zf, zo, zc, zj and zk, and these key combinations have been selected quite wisely to make it easy to remember. 

Configure Things

Here is my complete vimrc file, optimized for python source editing:

" enter spaces when tab is pressed:
set expandtab
" do not break lines when line lenght increases
set textwidth=0
" user 4 spaces to represent a tab
set tabstop=4
set softtabstop=4
" number of space to use for auto indent
" you can use >> or << keys to indent current line or selection
" in normal mode.
set shiftwidth=4
" Copy indent from current line when starting a new line.
set autoindent
" makes backspace key more powerful.
set backspace=indent,eol,start
" shows the match while typing
set incsearch
" case insensitive search
set ignorecase
" show line and column number
set ruler
" show some autocomplete options in status bar
set wildmenu

" automatically save and restore folds
au BufWinLeave * mkview
au BufWinEnter * silent loadview

" this lets us put the marker in the file so that
" it can be shared across and stored in version control.
set foldmethod=marker
" this is for python, put
" # name for the folded text # {{{
" to begin marker and
" # }}}
" close to end it.
set commentstring=\ #\ %s
" default fold level, all open, set it 200 or something
" to make it all closed.
set foldlevel=0

" share clipboard with windows clipboard
set clipboard+=unnamed

" set viminfo='100,f1
" minibufexplorer settings:j
let g:miniBufExplMapWindowNavArrows = 1
let g:miniBufExplMapCTabSwitchWindows = 1

syntax on

Enjoy! 

Labels: Python Programming Invented Here Tips n Tricks


Django: Extending User Model

One of first issue one faces with starting developing with django is extending User. There are three approaches various people are using. 

 User Profile

Django has a concept of UserProfile model. This is the recommended way to extend User model in django, recommended by the django book and django's official documentation. Lets say the name of your project is myproj, you create an app to manage the accounts user registration etc, lets call it accounts. After "startapp accounts" go to the accounts/models.py, and create a model:

# extending user # {{{
class UserProfile(models.Model):
    user = models.ForeignKey(User)
    openid = models.URLField(blank=True)

    def _get_comments(self):
        return Comment.objects.get(user=self, is_public=True)
        public_comments = property(_get_comments)
    del _get_comments

    class Admin: pass
# }}}

While this is enough to store more information about user, django adds a shortcut to access this user profile model more conveniently by calling user.get_profile() if in your settings.py file you add the following line:

AUTH_PROFILE_MODULE = 'accounts.UserProfile'

While this is easy to get started, and "official" way of doing things, it has one major drawback: you put your relations in user profile model. What I mean is, if for example you had a concept of friends, you will say:

# extending user # {{{
class UserProfile(models.Model):
    user = models.ForeignKey(User)
    openid = models.URLField(blank=True)
    friends = models.ManyToManyField('self', symmetrical=True)
    ...

# }}}

and to access it you will have to use something like:

# show_friends # {{{
@login_required
def show_friends(request, userid):
    user = get_object_or_404(User, id=userid)
    friends = user.get_profile().friends
    # do other things with friends and return
    return HttpResposne(
        ",".join(
            [
                friend.get_profile().username
                for friend in user.get_profile().friends
            ]
    )
# }}}

See the problem? You have to remember to call get_profile() at appropriate times, and this sounds a little less right. Some variable are user.XYZ where as some are user.get_profile().ABC, and you are friends with "user", and not his profile! Keeps me wanting a neater solution. Then there is the hassle of making sure that one to one relationship between User and UserProfile is maintained, which on deleting User, you have to delete UserProfile and vice versa.  

The replaces_module Method

This is an incredibly hacky but works with issues method that is on django's wiki on the same topic.

Lost-Theories Solution

I came across another solution for it via Jeff Craft 's lost-theories.com source code; that I am actually using for my current project. In this case he created a LostUser that has a foreignkey to django's User model, and uses LostUser throughout the code. 

class LostUser(models.Model):
    user = models.ForeignKey(User, unique=True)
    # Location info
    city = models.CharField(maxlength=200, blank=True)
    state = models.CharField(maxlength=200, blank=True)
    country = models.CharField(maxlength=200, blank=True)
    ...

The primary problem I faced was the lack of request.user in views and user object in template niceties. I solved that by writing the following middleware:

from vakow.accounts.models import MyUser

class MyUserMiddleware(object):
    def process_request(self, request):
        if request.user.is_authenticated():
            request.vuser = MyUser.objects.get(duser=request.user)
        else: request.vuser = None

and the following context-processor:

# context_processor # {{{
def context_processor(request):
    d = {
       'media_url': settings.MEDIA_URL,
    }
    d['duser'] = request.user
    if request.user.is_authenticated():
        d['vuser'] = request.vuser
    else: d['vuser'] = None
    return d
# }}}

This has the drawback of having to deal with two objects about a user, duser and vuser, where duser is an instance of django's User models, and vuser in my project's user extension. Such naming conventions helped in disambiguating what instance I am talking about, and since almost all aspect of my code worked with my user class, this was not really a problem. I had added a few properties in my derived class for username, email to query it from self.duser.username when self.username is requested. Life was good, and the only time I had any issues was when dealing with django's comment framework, as comment objects contained a foreignkey to duser, and not vuser. I hacked my comment to added a property vuser in Comment model. 

The Final Solution 

This is partially derived from the cool tip I got on Pythoneer. Here is what you can do:

# Extending User # {{{
User.add_to_class("openid", models.URLField(blank=True))
User._meta.admin.fields += (
    ("AmitCom Extensions", { 'fields': ('openid', ) }),
)

class UserExtension(object):
    def _get_comments(self):
        return Comment.objects.get(user=self, is_public=True)
    public_comments = property(_get_comments)
    del _get_comments

User.__bases__ = User.__bases__ + ( UserExtension, )
# }}}

This sounds the best solution to me. All fields, relations and custom methods are on User model and no multiple Models to keep track of.

PS: If you are curios about all the "# {{{" and "# }}}" in the code above, they are code folding markers, learn about code folding for python in vim here

Labels: Python Programming Invented Here Django


How "super" Works In Python

This is from Guido's paper Unifying types and classes in Python 2.2.

Cooperative methods and "super"

One of the coolest, but perhaps also one of the most unusual features of the new classes is the possibility to write "cooperative" classes. Cooperative classes are written with multiple inheritance in mind, using a pattern that I call a "cooperative super call". This is known in some other multiple-inheritance languages as "call-next-method", and is more powerful than the super call found in single-inheritance languages like Java or Smalltalk. C++ has neither form of super call, relying instead on an explicit mechanism similar to that used in classic Python. (The term "cooperative method" comes from "Putting Metaclasses to Work".)

As a refresher, let's first review the traditional, non-cooperative super call. When a class C derives from a base class B, C often wants to override a method m defined in B. A "super call" occurs when C's definition of m calls B's definition of m to do some of its work. In Java, the body of m in C can write super(a, b, c) to call B's definition of m with argument list (a, b, c). In Python, C.m writes B.m(self, a, b, c) to accomplish the same effect. For example:

class B:
def m(self):
print "B here"

class C(B):
def m(self):
print "C here"
B.m(self)
We say that C's method m "extends" B's method m. The pattern here works well as long as we're using single inheritance, but it breaks down with multiple inheritance. Let's look at four classes whose inheritance diagram forms a "diamond" (the same diagram was shown graphically in the previous section):
class A(object): ..
class B(A): ...
class C(A): ...
class D(B, C): ...

Suppose A defines a method m, which is extended by both B and C. Now what is D to do? It inherits two implementations of m, one from B and one from C. Traditionally, Python simply picks the first one found, in this case the definition from B. This is not ideal, because this completely ignores C's definition. To see what's wrong with ignoring C's m, assume that these classes represent some kind of persistent container hierarchy, and consider a method that implements the operation "save your data to disk". Presumably, a D instance has both B's data and C's data, as well as A's data (a single copy of the latter). Ignoring C's definition of the save method would mean that a D instance, when requested to save itself, only saves the A and B parts of its data, but not the part of its data defined by class C!

C++ notices that D inherits two conflicting definitions of method m, and issues an error message. The author of D is then supposed to override m to resolve the conflict. But what is D's definition of m supposed to do? It can call B's m followed by C's m, but because both definitions call the definition of m inherited from A, A's m ends up being called twice! Depending on the details of the operation, this is at best an inefficiency (when m is idempotent), at worst an error. Classic Python has the same problem, except it doesn't even consider it an error to inherit two conflicting definitions of a method: it simply picks the first one.

The traditional solution to this dilemma is to split each derived definition of m into two parts: a partial implementation _m, which only saves the data that is unique to one class, and a full implementation m, which calls its own _m and that of the base class(es). For example:

class A(object):
def m(self): "save A's data"
class B(A):
def _m(self): "save B's data"
def m(self): self._m(); A.m(self)
class C(A):
def _m(self): "save C's data"
def m(self): self._m(); A.m(self)
class D(B, C):
def _m(self): "save D's data"
def m(self): self._m(); B._m(self); C._m(self); A.m(self)

There are several problems with this pattern. First of all, there is the proliferation of extra methods and calls. But perhaps more importantly, it creates an undesirable dependency in the derived classes on details of the dependency graph of their base classes: the existence of A can no longer be considered an implementation detail of B and C, since class D needs to know about it. If, in a future version of the program, we want to remove the dependency on A from B and C, this will affect derived classes like D as well; likewise, if we want to add another base class AA to B and C, all their derived classes must be updated as well.

The "call-next-method" pattern solves this problem nicely, in combination with the new method resolution order. Here's how:

class A(object):
def m(self): "save A's data"
class B(A):
def m(self): "save B's data"; super(B, self).m()
class C(A):
def m(self): "save C's data"; super(C, self).m()
class D(B, C):
def m(self): "save D's data"; super(D, self).m()

Note that the first argument to super is always the class in which it occurs; the second argument is always self. Also note that self is not repeated in the argument list for m.

Now, in order to explain how super works, consider the MRO for each of these classes. The MRO is given by the __mro__ class attribute:

A.__mro__ == (A, object)
B.__mro__ == (B, A, object)
C.__mro__ == (C, A, object)
D.__mro__ == (D, B, C, A, object)

The expression super(C, self).m should only be used inside the implementation of method m in class C. Bear in mind that while self is an instance of C, self.__class__ may not be C: it may be a class derived from C (for example, D). The expression super(C, self).m, then, searches self.__class__.__mro__ (the MRO of the class that was used to create the instance in self) for the occurrence of C, and then starts looking for an implementation of method m following that point.

For example, if self is a C instance, super(C, self).m will find A's implementation of m, as will super(B, self).m if self is a B instance. But now consider a D instance. In D's m, super(D, self).m() will find and call B.m(self), since B is the first base class following D in D.__mro__ that defines m. Now in B.m, super(B, self).m() is called. Since self is a D instance, the MRO is (D, B, C, A, object) and the class following B is C. This is where the search for a definition of m continues. This finds C.m, which is called, and in turn calls super(C, self).m(). Still using the same MRO, we see that the class following C is A, and thus A.m is called. This is the original definition of m, so no super call is made at this point.

Note how the same super expression finds a different class implementing a method depending on the class of self! This is the crux of the cooperative super mechanism.

Quite cool indeed.

Labels: Python Programming


Django Master Class

If I have to call a piece of documentation: "mind blowing", this has to be it. You do any kind of web programming, you must read this. If you do django, you will know what all you can do, if not you will know what all can be done in a thought-out framework, and start considering switching or implementing part of it in your own. Read it now.

Labels: Python Programming Django Tips n Tricks


Wednesday, July 25, 2007

Learn Stargazing

I always wanted to learn star gazing, but never knew where to begin. This site teaches the absolute basics. Trust me you will want to go out and gaze after going through it.

Label: Science


Tuesday, July 24, 2007

Yahoo! Online Office Coming?

Just read this post by Jeremy, and some part of me is completely refusing the possibility that this is a mere praise to Google product. He is just building the groundwork for upcoming Yahoo! Office.

Label: Google


Monday, July 23, 2007

Reverse Pagination

You are all aware of object pagination, search results, your photo on flickr, stories on reddit, all have a next page/previous page paradigm. Django makes it trivially easy to create such pages by providing object_list generic view. There are some problems with the current implementation of pagination that we see around, page no 0/1 is assigned to the latest objects in the list. While in search result this makes little difference, in other cases it has a few consequences.

In reddit for example, you are on the main page, you see 25 stories there, you take 10 minutes to go through all of them, and click next. There is a good chance that 3-5 stories on the first page would have moved to now second page, and you will see them again. Not a good experience, but acceptable. You spend next 3-4 hours working, and click back to see the stories on the first page, you are taken to page 0, and there are good chances you have missed 12 stories that moved from first page to second, as your current page labelled second page became third. This is all quite confusing if you think about it. [I am assuming from this discussion the stories changing their relative rankings for simplicity, you can take example of flickr group photos, they also change rapidly, and order does not change there].

Another problem is, I am page on 26 of this flickr group, and I see some fellow has posted 8 nice photos to the group. I bookmark the page, and come back later/email it to a friend, and by the time the page is visited again, 100s of new photos has been added and the content of page 26 is now on page 29 or so, and I don't find what I was looking for.

The last consequence of this is caching difficulty. If a group has 5 thousand pages worth 30 photos each, and one more photo gets added, either the page number of the photos in each page will change for 5 thousand of those pages. This will happen on each photo being added, and there for the page can hardly be ever cached.

I propose a solution to this problem, I call it reverse pagination, and this blog is currently using a patched django to demonstrate it. In reverse pagination, page no 0/1 is assigned to the older page ever. When on reddit home page, and click next, you will not go to page 2, you will jump to page 20566 or something like that. The content of page 20566 will never change, only the content of latest page would be changing while new items are being added. This means all pages other than the main page can be cached for the rest of the life span of the website. And user will not face the other two problems I listed above.

Only downside is on the main page/latest page, you will upto 19 items if you paginate by 10 items per page.

Here is the patch for django. Enjoy!

Labels: Python Programming Invented Here Django


Tuesday, July 17, 2007

Structured Wiki

Openlibrary is to library as wikipedia was to encyclopedia. I am a fan of everyone contributing to build a good resource for the benefit of human kind at a large, but am not a fan of wiki. Structured data gets decompressed into globs of text. Am really glad openlibrary is not on that path:

infogami

... Infogami is a cleaner, simpler wiki. But unlike other wikis, it has the flexibility to handle different classes of data. Most wikis only let you store unstructured pages -- big blocks of text. Infogami lets you store semistructured data, just like ThingDB does, as well as use ThingDB's query powers to sort through it.

Each infogami page (i.e. something with a URL) has an associated type. Each type contains a schema that states what fields can be used with it and what format those fields are in. Those are used to generate view and edit templates which can then be further customized as a particular type requires.

The result, as you can see on the Open Library site, is that one wiki contains pages that represent books, pages that represent authors, and pages that are simply wiki pages, each with their own distinct look and edit templates and set of data.

I wrote about a similar structured wiki-sh idea sometime back, wikidBASE.

Imagine if the entire content of wikipedia was structured. Pages on people were really had a Person object belonging to it, with data_of_birth, first_name, last_name as fields that one can do queries on, do field search, sort things. Imagine the same for all Countries, Cities, Events, Company, Product etc with reasonable fields. That would have been HUGE!

Label: Programming


Monday, July 16, 2007

Seeing Yellow. Or Red?

Seeing Yellow:

When you print on a color laser printer, it's likely that you are also printing a pattern of invisible yellow dots. These marks exist to allow the printer companies and governments to track and identify you -- presumably as a way to combat money counterfeiting.

...

Most color laser printers made and sold today intentionally add invisible information to make it easier to determine where (and when) a particular document was printed. This seems to have been done as part of a secret deal between the United States Secret Service and the individual manufacturers. Some of the manufacturers have mentioned the existence of the tracking information in their documentation, and others haven't. None of them have explained exactly how it works or what information is conveyed. No law requires printer companies to help track printer users this way, and no law prevents them from stopping this practice or giving customers a solution to avoid being tracked.

This information is most famously known to be coded by patterns of yellow dots that the printers add to the background of all the pages they print. The yellow dots are hard to see with the naked eye, but can be seen under bright blue light or with a microscope. Their arrangement reveals which printer was used to print a particular document, and sometimes also shows when it was printed. Some of the codes have been understood while others are still mysterious, but none of the printer manufacturers has denied that the dots are intended to help track a particular document to a particular printer (or that they can actually be used for this purpose). This is a direct attack on the privacy of the owners and users of printers, and in particular, on their right to free, anonymous speech.

More details with EFF.

Is it really paranoia to ask "what if Microsoft Windows is similarly rigged, so that US can spy on India?" They have reasons and means and this establishes enough precedence. They would be idiots for if they are not trying.

Does India deserve right to keep something to itself?

Labels: India Calling Security n Privacy


Introducing JackAss: Keyboard Binding For Page Scroll

Gmail uses keyboard shortcuts "j" and "k" for jumping from one mail to next, while Google Reader uses them for opening consecutive blog posts. They are incredibly handy once you get used to them. In-fact once you get used to them you miss them everywhere.

Here is my girlfriend-not-free-for-movie-so-I-will-code project, jackass! It is a jQuery plugin, as well as a bookmarklet you can use, so that you can add j-k-keyboard-assignments on any page you come across.

Instructions for bookmarklet: jackassify current page.

Firefox: Drag and drop the above link to bookmark menu or bookmark toolbar.

IE: Right click on the above link, and select add to favorites.

Then go to any page, locate the above link in your bookmarks/favorites, and click on it.

If you like it, you may want to install it as Greasemonkey script.

PS: You can just click on the above link to see it get applied on my blog, and press "j" and "k" keys to experiment.

Labels: Programming Invented Here


Sunday, July 15, 2007

Nyayapati Gautam: Fast Track Courts for Politicians

Came across this innovative idea on The India Story:

... In the article “Ten commandments for Dr. Singh”, Swaminathan has come out with, “Thou shalt propose a law giving seniority to all cases of elected legislators over all others.”

I think it is a brilliant suggestion. More so because of its utter simplicity. I wonder why our founding fathers did not think of this simple bit of legislation. Maybe they never imagined that a day would come when the state legislatures and also the Parliament would play host to people we would rather have behind bars.

...

Now if getting elected to any official position becomes a catalyst for all the pending cases against them to be brought to the front burner, then only the most brain dead of criminals would like to be involved in the political process.

I would go further to suggest that all state legislatures and the Parliament should have a fast track court established on their premises to try the worthies who have broken the law. Why should courts be located inside State Assemblies? Can’t justice be served from the current premises of the High Courts? Of course it can. Just can’t resist the idea that as Legislators enter the Assembly they can also see the Annexe of the High Court and know for certain that they can’t escape a visit to its premises if they run foul of the law.

And for career politicians who have a lot of frivolous cases registered against them, there is nothing to despair. Because all the law would say is that, “all your cases will be fast tracked and tackled by a special court”. So in case of complaints that are completely frivolous or are obviously the result of leading an agitation against some policy of the government they could also get some judicial respite. Immediately. And such a rule should be welcomed by those politicians who claim that they are being victimized.

This proposal should get more attention.

Labels: India Calling Security n Privacy


Saturday, July 14, 2007

On Privacy

As a follow up to my yesterday's post, I was looking for replies to my comment in Schneier's blog. The very first comment was:

One of the suggested responses to "I've got nothing to hide" is "can I see your credit card bills for the last year?" Good luck trying that when you're pulled over by a cop or when the FBI is at your door.

It is quite easy to make people agree that it makes sense to have privacy from one another.

It is much harder to disprove the notion that "I've got nothing to hide from the government," and I don't see this essay addressing the question why individuals need privacy from the government.

This reinforces my argument that privacy advocates are not doing their job well enough. If I was to do this job, about the first thing I will do is create awareness about the difference between the notion of privacy against government vs the privacy against citizens/private firms/marketers. These are so different concept when you are talking about privacy, these should have been two different words, and yet a 25 page paper written in support of privacy, that is trying to define it, evaluate its value, could not point this out. Half page long bullet list of taxonomy of privacy and such a basic thing missing, this is failure to me.

I will do the needful, I call privacy against government "absolute privacy" and privacy against citizens/private firms: "general privacy", or just privacy. This is the first taxonomy one should understand before one starts making further arguments for or against privacy. A lot of arguments in favor of privacy are only applicable to general privacy, and are wrongly used against absoulte privacy.

Moving on:

@Amit:

The government is not forced to collect data under the covers, it chooses to do so. This is not a problem of privacy, but of a government which is not the servant of the people (as it should be, at least in a democracy or realanarchy), but has its very own agenda.

In the same way, one could argue that governmental torture should be legalized, as otherwise the government will still torture, but secretly (IIRC this argument came up on this blog before).

Kristine

P.S: The "terrorist" horseman of the apocalypse is a bit overused, especially in conjunction with "might potentially help". So it does not scare me

Let me repeat why I feel government is forced to collect data under covers: privacy is a very abused term, privacy advocates to blame mostly, and the masses are not educated. I trust politician much less than security advocates(who have failed in my thesis), if privacy-loss has widespread negative connotation in public, government would be tempted to avoid disclosing, this is the nature of democracy.

Torture is real, privacy is made up paranoia, if you differ, I will give you my gmail password, and you courier me your chopped fingers. :-)

Terrorism is a funny business, if Americans have had enough of calling themselves victims of terrorism, may be, just may be, they should consider the countries really suffering from terrorism, like India for example. 10 years of evidence of direct support by Pakistan in Kashmir, and the American press still calls terrorism in India "freedom struggle". Imagine millions of suffering because an entire state being victim of real terrorism, and then compare with flukes like 911 that had just few thousand dead, years ago, you may get some perspective. Anyways, coming back to topic.

Let me summarize my position. Privacy is an important issue. General privacy should be my constitutional right, no one should have right to post my emails or phone call records, on internet for example. This is not freedom of speech. This is not a IP/copyright issue. This is a privacy issue. This is missing today. Absolute privacy, governments should have right and means to do data-mining, to go through my emails and phone records, to study demographic trends, to look for unusual activities. We as society has to come up with systems and norms to make sure these things do not get misused. If government singles me out, it is an abuse. If government does not take suitable precautions to keep my data safe, or shares it with private parties, it is an abuse. We should help build public awareness towards these issues, and participate in government's data warehouse building projects with suitable gaurds to avoid the real issues. This is missing too. A knee jerk, "privacy is the holy grail, anything else and you are totalitarian government in making" argument would only hurt privacy in the long run.

Labels: India Calling Security n Privacy


Friday, July 13, 2007

Featured Django Project: i18ndynamic

I am a huge fan of django. And after their recent unicode improvements, they have become really good option of i18n enabled sites, or sites that are available in multiple languages. So now the interface can be in more than one language, django will select the default website language based on browser settings, and allows user to select their language preferences if they want. Only missing piece was translating data. While django's translation utilities support translating data in database, but something was missing, the capability to for example, store description of a book, for example, in different languages. i18ndynamic is exactly what was needed.

Labels: Python Programming Django


Privace Debate: I Have Nothing To Hide Argument

Schneier links to a 25 page paper about why privacy is important, and how "I have nothing to hide, so its okay for govt to collect data on me, to fight against terrorists" argument is invalid. At-least it is supposed to "exposes its faulty underpinnings". 12 pages into it, after reading 1 million times that this argument is not valid, I am yet to see any strong argument. Schneier and group trying to brain wash people about something that might potentially help stop terrorists?

Why is privacy required? Do we need privacy? Is it our right? It would have been a good thing had there been reasons to call privacy a fundamental right, but there isn't. If you have nothing to hide, you have nothing to worry about. This is fundamental.

I am an advocate of privacy actually, but when I see criticism of data mining projects in the name of privacy, it sounds more like security analysts/watchdogs are taking the wishful simpler but wrong way out of "privacy is fundamental therefore data mining is wrong" approach, where as they should be pointing out the details of the programs. The reasons are simple, if I have to tell a common person that government is doing something wrong, I would rather want my argument to be one sentence long rather than one para or a book long. Common people have short attention span, they know anyone, who has invested anything in any field of expertise, will want everyone to know how valuable whatever they know is, is to everybody. Basic human psychology, common people understand it, and will take the experts opinion with a grain of salt.

It is wrong for security experts to call privacy card. For one there is the cause vs the champions thing going on, you take the cause of privacy, and make lame arguments in its support, all privacy supporters suffer the loss. The fact of matter is government has been collecting information on us. The automobile registration papers, the passport, the death and birth certificate, the tax papers. They are going to keep collecting information on us, no sane person would try to argue government should stop collecting any of the information I mentioned above for example. Information collection is the part of life, and we have to live with it. We have to live with the concept that there should be a comprehensive information collection system. Years of privacy advocates have really made that system sound so bad, that instead of developing such a system openly, taking citizen interest and feedback into account, government has to do this under the covers. Should government do it? Yes. Is it possible that there can be problems with the implementation? Yes. Why not there be a open source project about the same. But privacy advocates will just kill that project, and force government to do it under covers, which actually leads to systems that are under scrutinized, and bad for the privacy in the first place.

Let there be a data collection agency. Let everyone public or private collecting data on citizens operate under the laws governed by such an agency. Let security experts participate in building such an agency taking into account the concerns of government/law enforcement and citizens alike. Let privacy have a chance.

Labels: India Calling Security n Privacy


Thursday, July 5, 2007

JQuery Plugin: Masked Input

I love jquery. And I love innovation. Check their demo. Really cool.

Labels: Programming Tips n Tricks


Condensed TV

From slahsdot:

CNN is reporting on a (relatively) new website called the Minisode Network that allows users to watch popular television shows that have been strategically condensed down to somewhere between four and six minutes.

"Don't think of the Minisode Network as a brand-new Web site. Think of it as a long-overdue public service. That is, who among us hasn't felt the double-edged sword of our media age: So much video from TV, DVDs, the Internet and even cell phones ... but too little time to watch it all? The Minisode Network has a solution. Launched in June as a broadband channel on the MySpace site, it offers, for our streaming pleasure, episodes of vintage Sony Pictures Television series like 'Silver Spoons,' 'Starsky & Hutch,' 'Diff'rent Strokes' and even Ricki Lake's talk show."

Now this is innovation! :-)


Wednesday, July 4, 2007

Bush A War Criminal?

It would be a sad world to live in if history remembers him as anything else.

Label: Security n Privacy