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...
Yes, it is guaranteed stable across Python versions. The search order is called the Method Resolution Order, or MRO, and this order has been the same since Python 2.3.
For more details on how the order is determined, see the Python 2.3 Method Resolution Order documentation.
You can inspect the MRO by looking at the .__mro__
attribute of a given class; it is a tuple of the classes in method-resolution order.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With