Subclassing ConfigParser

G

Greg Krohn

I'm trying to subclass ConfigParser so I can use a custom __read method (the
custom format doesn't conform to RFC 822) when needed. Needless to say, it's
not working as expected.

In the following code, I bind __read_ini to __read and override __read so it
can choose between __read_ini and __read_custom. But it seems that
__read_custom never gets called when I expect it to aways be called. I have
a feeling this has to do with me not entirely understanding magic atributes
and name mangling. Anyone have ideas?


greg



from ConfigParser import ConfigParser

class CustomConfigParser(ConfigParser):
def __init__(self, defaults=None):
ConfigParser.__init__(self, defaults)

#Replace the normal __read with my custom __read
#while keeping the normal one around if I need it
self.__read_ini = ConfigParser._ConfigParser__read
ConfigParser._ConfigParser__read = self.__read

def __read(self, fp, fpname):
#Eventually this will decide between __read_custom
#and __read_ini, etc.
self.__read_custom(fp, fpname)

def __read_custom(self, fp, fpname):
print "__read_custom" #This never gets printed.

cp = CustomConfigParser()
cp.read('config.ini')
print cp.sections()
 
M

Michael Amrhein

Greg said:
I'm trying to subclass ConfigParser so I can use a custom __read method (the
custom format doesn't conform to RFC 822) when needed. Needless to say, it's
not working as expected.

In the following code, I bind __read_ini to __read and override __read so it
can choose between __read_ini and __read_custom. But it seems that
__read_custom never gets called when I expect it to aways be called. I have
a feeling this has to do with me not entirely understanding magic atributes
and name mangling. Anyone have ideas?


greg



from ConfigParser import ConfigParser

class CustomConfigParser(ConfigParser):
def __init__(self, defaults=None):
ConfigParser.__init__(self, defaults)

#Replace the normal __read with my custom __read
#while keeping the normal one around if I need it
self.__read_ini = ConfigParser._ConfigParser__read
ConfigParser._ConfigParser__read = self.__read

def __read(self, fp, fpname):
#Eventually this will decide between __read_custom
#and __read_ini, etc.
self.__read_custom(fp, fpname)

def __read_custom(self, fp, fpname):
print "__read_custom" #This never gets printed.

cp = CustomConfigParser()
cp.read('config.ini')
print cp.sections()
Hi Greg,
are you sure you have a file 'config.ini' in your current working
directory? ConfigParser is silently ignoring files which cannot be
opened, so that _read is not called!

BTW, you did not mention the Python version you are using. In Python 2.3
the method you overwrite is named '_read', not '__read' (so there is no
name mangling). This is one drawback of overwriting "private" methods,
when the author renames or removes them, your code is broken.

Anyway, your method of overwriting the method is a bit complicated . You
can do it much easier: just overwrite _read and call the original method
when appropriate:

class CustomConfigParser(ConfigParser):
def __init__(self, defaults=None):
ConfigParser.__init__(self, defaults)
def _read(self, fp, fpname):
if ... # your criteria for custom ini
then return self._read_custom(fp, fpname)
else return ConfigParser._read(self, fp, fpname)

def _read_custom(self, fp, fpname):
...

Michael
 
G

Greg Krohn

Michael Amrhein said:
Hi Greg,
are you sure you have a file 'config.ini' in your current working
directory? ConfigParser is silently ignoring files which cannot be
opened, so that _read is not called!

I was getting a ParsingError that showed the line it was choking on, so I
know it was finding the file.
BTW, you did not mention the Python version you are using. In Python 2.3
the method you overwrite is named '_read', not '__read' (so there is no
name mangling). This is one drawback of overwriting "private" methods,
when the author renames or removes them, your code is broken.

I _was_ using ActivePython 2.2 (2.3 isn't out yet). I downloaded the 2.3
regular distro last night because I read ConfigParser was cleaned up, but I
haven't had time to mess around with it much.
Anyway, your method of overwriting the method is a bit complicated . You
can do it much easier: just overwrite _read and call the original method
when appropriate:

class CustomConfigParser(ConfigParser):
def __init__(self, defaults=None):
ConfigParser.__init__(self, defaults)
def _read(self, fp, fpname):
if ... # your criteria for custom ini
then return self._read_custom(fp, fpname)
else return ConfigParser._read(self, fp, fpname)

def _read_custom(self, fp, fpname):
...

Michael

Yes, this is great! Everything is working as expected now. Originally I was
expecting code like yours to work in 2.2 and when it didn't I tried all
sorts of elaborate hacks. What a mess. Thank you very much for your reply.

greg
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top