classification
Title: make csv.DictReader.__init__ use self.fieldnames
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.2, Python 3.3
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: berker.peksag, r.david.murray, serhiy.storchaka, tb
Priority: normal Keywords:

Created on 2012-10-22 08:27 by tb, last changed 2012-10-23 19:23 by r.david.murray. This issue is now closed.

Messages (7)
msg173500 - (view) Author: (tb) Date: 2012-10-22 08:27
The csv.DictReader contains a setter method for the fieldnames (@fieldnames.setter). However, the __init__ method does not make use of the setter method as it sets _fieldnames directly. To allow users correct/functional overriding of the fieldnames.setter method I would propose changing the line 

self._fieldnames = fieldnames 

to

self.fieldnames = fieldnames
msg173527 - (view) Author: Berker Peksag (berker.peksag) * (Python committer) Date: 2012-10-22 15:08
I think this is an invalid request.

See the usage of property decorator: http://docs.python.org/py3k/library/functions.html#property
msg173528 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2012-10-22 15:14
I think it is not an invalid request.  However, what is the use case?  Normally a class will manipulate the "real" variable, and the getter/setter is the public API.  Without a good use case it doesn't seem worth changing that bit of the init method.
msg173583 - (view) Author: (tb) Date: 2012-10-23 08:39
This is my use case:
I am creating a custom DictReader class for reading and accessing the columns white space and case insensitive. 
For this I created a dict subclass (DictInsensitive) with a custom __getitem__ method. DictReaderInsensitive.__next__ overrides the original DictReader.__next__ by returning a DictInsensitive. I also override the DictReader.fieldnames property to lower/strip all fieldnames.
See http://stackoverflow.com/a/12970460/1251007 for an example. 
This is all functional with the current csv.DictReader. All entries in DictReaderInsensitive.fieldnames are in lower case and without white space and by iterating over the lines I get dictionaries where I can access the keys white space/case insensitive.

Now, the problem is: If I want the check wether a specific fieldname is present in the input file, I have strip()/lower() "by hand":
    csv_in = DictReaderInsensitive(open(input_file, 'rU'))
    if "Fieldname to check".strip().lower() in csv_in.fieldnames

To do this automatically, I created a ListInsensitive as a subclass of list:
    class ListInsensitive(list):
        def __contains__(self, item):
            return list.__contains__(self, item.strip().lower())

Now I want csv.DictReader to use that new class. I thought of overwriting the setter method, but here lies the current problem. I can overwrite the setter method, but csv.DictReader does not use the setter method internally.

My setter method looks like this:
    @fieldnames.setter
    def fieldnames(self, value):
        if value == None:
            self._fieldnames = None
        else:
            self._fieldnames = ListInsensitive()
            for name in value:
                self._fieldnames.append(name.strip().lower())
msg173593 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2012-10-23 11:50
You can overwrite fieldnames getter.

    @property
    def fieldnames(self):
        if self._fieldnames is None:
            try:
                self._fieldnames = next(self.reader)
            except StopIteration:
                pass
        self.line_num = self.reader.line_num
        if not isinstance(self._fieldnames, ListInsensitive):
            self._fieldnames = ListInsensitive(name.strip().lower() for name in self._fieldnames)
        return self._fieldnames
msg173622 - (view) Author: (tb) Date: 2012-10-23 16:05
Okay, that makes my use case obsolete. Overwriting the getter method like this seems obvious ... Somehow this hasn't come to my mind.

Sorry for bothering. From my point of view, we can close this issue. Or is there another use case?
msg173634 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2012-10-23 19:23
It does seem more logical to implement this in the getter, now that Serhiy has pointed it out :)  So let's close this.

(Aside: if it were me, I'd move the mangling of the fieldnames into the ListInsensitive __init__ method.)
History
Date User Action Args
2012-10-23 19:23:07r.david.murraysetstatus: open -> closed
resolution: not a bug
messages: + msg173634
2012-10-23 16:05:39tbsetmessages: + msg173622
2012-10-23 11:50:03serhiy.storchakasetnosy: + serhiy.storchaka
messages: + msg173593
2012-10-23 08:39:09tbsetmessages: + msg173583
2012-10-22 15:14:43r.david.murraysetnosy: + r.david.murray
messages: + msg173528
2012-10-22 15:08:13berker.peksagsetnosy: + berker.peksag
messages: + msg173527
2012-10-22 14:06:34Ramchandra Aptesettitle: small fix to csv.DictReader.__init__ -> make csv.DictReader.__init__ use self.fieldnames
2012-10-22 14:06:01Ramchandra Aptesetversions: + Python 3.3
title: csv.DictReader -> small fix to csv.DictReader.__init__
2012-10-22 08:27:29tbcreate