I have a project which uses SafeConfigParser and I want it to be Python2 and 3 compatible. Now, SafeConfigParser is deprecated since Python 3.2 and I find the deprecation warning annoying. So I went about my business to remedy that.
First (and much older, already solved problem): SafeConfigParser is an old-style class in Python2 so I cannot call super in my descendant class. To have a more consistent behaviour, I wrote the following:
try:
# Python 2
class ConfigResolverBase(object, SafeConfigParser):
"""
A default "base" object simplifying Python 2 and Python 3
compatibility.
"""
pass
except TypeError:
# Python 3
class ConfigResolverBase(SafeConfigParser):
"""
A default "base" object simplifying Python 2 and Python 3
compatibility.
"""
pass
This worked fine to make the class new-style if necessary. To get rid of the DeprecationWarning I changed the code into this:
if sys.hexversion < 0x030000F0:
# Python 2
class ConfigResolverBase(object, SafeConfigParser):
"""
A default "base" object simplifying Python 2 and Python 3
compatibility.
"""
pass
else:
# Python 3
class ConfigResolverBase(ConfigParser):
"""
A default "base" object simplifying Python 2 and Python 3
compatibility.
"""
pass
Along the way I also fixed a line I missed to change earlier:
@@ -275,7 +276,7 @@ class Config(ConfigResolverBase):
have_default = False
try:
- value = SafeConfigParser.get(self, section, option, **kwargs)
+ value = super(Config, self).get(section, option, **kwargs)
return value
except (NoSectionError, NoOptionError) as exc:
if have_default:
And that change caused an interesting error:
AttributeError: 'Config' object has no attribute '_sections'
Which let me to believe that __init__ of ConfigParser was not called. And indeed making the following change fixed that:
- class ConfigResolverBase(object, SafeConfigParser):
+ class ConfigResolverBase(SafeConfigParser, object):
My code is now working fine for both Python 2 and 3, but whant I am unsure about is: Is the proxy returned by super always the same?" In my case I inherit from both object and SafeConfigParser. Swapping the two bases in my class definition made super return the right one. But is this guaranteed to be stable across all Python implementations on all platforms? Or should I explicitly call SafeConfigParser.get(self, ...)? Which is after-all the "old way" of calling the base...