Skip to content

Commit 125aefe

Browse files
authored
Merge pull request #2138 from Exirel/class-py3-style
sopel: use python3 style class and abc.ABC
2 parents 1d30887 + 9f83a59 commit 125aefe

File tree

23 files changed

+137
-136
lines changed

23 files changed

+137
-136
lines changed

sopel/bot.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545

4646
class Sopel(irc.AbstractBot):
4747
def __init__(self, config, daemon=False):
48-
super(Sopel, self).__init__(config)
48+
super().__init__(config)
4949
self._daemon = daemon # Used for iPython. TODO something saner here
5050
self.wantsrestart = False
5151
self._running_triggers = []
@@ -1199,7 +1199,7 @@ def restart(self, message):
11991199
self.quit(message)
12001200

12011201

1202-
class SopelWrapper(object):
1202+
class SopelWrapper:
12031203
"""Wrapper around a Sopel instance and a Trigger.
12041204
12051205
:param sopel: Sopel instance

sopel/config/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,15 +86,15 @@ class ConfigurationNotFound(ConfigurationError):
8686
:param str filename: file path that could not be found
8787
"""
8888
def __init__(self, filename):
89-
super(ConfigurationNotFound, self).__init__(None)
89+
super().__init__(None)
9090
self.filename = filename
9191
"""Path to the configuration file that could not be found."""
9292

9393
def __str__(self):
9494
return 'Unable to find the configuration file %s' % self.filename
9595

9696

97-
class Config(object):
97+
class Config:
9898
"""The bot's configuration.
9999
100100
:param str filename: the configuration file to load and use to populate this
@@ -279,7 +279,7 @@ def define_section(self, name, cls_, validate=True):
279279
)
280280
setattr(self, name, cls_(self, name, validate=validate))
281281

282-
class ConfigSection(object):
282+
class ConfigSection:
283283
"""Represents a section of the config file.
284284
285285
:param str name: name of this section

sopel/config/types.py

Lines changed: 15 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,19 @@
2525

2626
from __future__ import generator_stop
2727

28+
import abc
2829
import getpass
2930
import os.path
3031
import re
3132

3233
from sopel.tools import deprecated, get_input
3334

3435

35-
class NO_DEFAULT(object):
36+
class NO_DEFAULT:
3637
"""A special value to indicate that there should be no default."""
3738

3839

39-
class StaticSection(object):
40+
class StaticSection:
4041
"""A configuration section with parsed and validated settings.
4142
4243
This class is intended to be subclassed and customized with added
@@ -113,10 +114,7 @@ def configure_setting(self, name, prompt, default=NO_DEFAULT):
113114
setattr(self, name, value)
114115

115116

116-
# TODO: Make this a proper abstract class when dropping Python 2 support.
117-
# Abstract classes are much simpler to deal with once we only need to worry
118-
# about Python 3.4 or newer. (https://stackoverflow.com/a/13646263/5991)
119-
class BaseValidated(object):
117+
class BaseValidated(abc.ABC):
120118
"""The base type for a setting descriptor in a :class:`StaticSection`.
121119
122120
:param str name: the attribute name to use in the config file
@@ -196,18 +194,13 @@ def configure(self, prompt, default, parent, section_name):
196194

197195
return self._parse(value, parent, section)
198196

197+
@abc.abstractmethod
199198
def serialize(self, value, *args, **kwargs):
200-
"""Take some object, and return the string to be saved to the file.
201-
202-
Must be implemented in subclasses.
203-
"""
204-
raise NotImplementedError("Serialize method must be implemented in subclass")
199+
"""Take some object, and return the string to be saved to the file."""
205200

201+
@abc.abstractmethod
206202
def parse(self, value, *args, **kwargs):
207-
"""Take a string from the file, and return the appropriate object.
208-
209-
Must be implemented in subclasses."""
210-
raise NotImplementedError("Parse method must be implemented in subclass")
203+
"""Take a string from the file, and return the appropriate object."""
211204

212205
def __get__(self, instance, owner=None):
213206
if instance is None:
@@ -305,8 +298,7 @@ def __init__(self,
305298
serialize=None,
306299
default=None,
307300
is_secret=False):
308-
super(ValidatedAttribute, self).__init__(
309-
name, default=default, is_secret=is_secret)
301+
super().__init__(name, default=default, is_secret=is_secret)
310302

311303
if parse == bool:
312304
parse, serialize = _deprecated_special_bool_handling(serialize)
@@ -334,7 +326,7 @@ def configure(self, prompt, default, parent, section_name):
334326
if self.parse == _parse_boolean:
335327
prompt += ' (y/n)'
336328
default = 'y' if default else 'n'
337-
return super(ValidatedAttribute, self).configure(prompt, default, parent, section_name)
329+
return super().configure(prompt, default, parent, section_name)
338330

339331

340332
class BooleanAttribute(BaseValidated):
@@ -347,8 +339,7 @@ class BooleanAttribute(BaseValidated):
347339
If the ``default`` value is not specified, it will be ``False``.
348340
"""
349341
def __init__(self, name, default=False):
350-
super(BooleanAttribute, self).__init__(
351-
name, default=default, is_secret=False)
342+
super().__init__(name, default=default, is_secret=False)
352343

353344
def configure(self, prompt, default, parent, section_name):
354345
"""Parse and return a value from user's input.
@@ -417,7 +408,7 @@ class SecretAttribute(ValidatedAttribute):
417408
otherwise behaves like other any option.
418409
"""
419410
def __init__(self, name, parse=None, serialize=None, default=None):
420-
super(SecretAttribute, self).__init__(
411+
super().__init__(
421412
name,
422413
parse=parse,
423414
serialize=serialize,
@@ -498,7 +489,7 @@ class SpamSection(StaticSection):
498489

499490
def __init__(self, name, strip=True, default=None):
500491
default = default or []
501-
super(ListAttribute, self).__init__(name, default=default)
492+
super().__init__(name, default=default)
502493
self.strip = strip
503494

504495
def parse(self, value):
@@ -621,7 +612,7 @@ class ChoiceAttribute(BaseValidated):
621612
:type default: str
622613
"""
623614
def __init__(self, name, choices, default=None):
624-
super(ChoiceAttribute, self).__init__(name, default=default)
615+
super().__init__(name, default=default)
625616
self.choices = choices
626617

627618
def parse(self, value):
@@ -668,7 +659,7 @@ class FilenameAttribute(BaseValidated):
668659
:type default: str
669660
"""
670661
def __init__(self, name, relative=True, directory=False, default=None):
671-
super(FilenameAttribute, self).__init__(name, default=default)
662+
super().__init__(name, default=default)
672663
self.relative = relative
673664
self.directory = directory
674665

sopel/db.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ class PluginValues(BASE):
8181
value = Column(String(255))
8282

8383

84-
class SopelDB(object):
84+
class SopelDB:
8585
"""Database object class.
8686
8787
:param config: Sopel's configuration settings

sopel/irc/abstract_backends.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
# Licensed under the Eiffel Forum License 2.
44
from __future__ import generator_stop
55

6+
import abc
7+
68
from .utils import safe
79

810

9-
class AbstractIRCBackend(object):
11+
class AbstractIRCBackend(abc.ABC):
1012
"""Abstract class defining the interface and basic logic of an IRC backend.
1113
1214
:param bot: a Sopel instance
@@ -18,13 +20,14 @@ class AbstractIRCBackend(object):
1820
def __init__(self, bot):
1921
self.bot = bot
2022

23+
@abc.abstractmethod
2124
def is_connected(self):
2225
"""Tell if the backend is connected or not.
2326
2427
:rtype: bool
2528
"""
26-
raise NotImplementedError
2729

30+
@abc.abstractmethod
2831
def on_irc_error(self, pretrigger):
2932
"""Action to perform when the server sends an error event.
3033
@@ -34,14 +37,13 @@ def on_irc_error(self, pretrigger):
3437
On IRC error, if ``bot.hasquit`` is set, the backend should close the
3538
connection so the bot can quit or reconnect as required.
3639
"""
37-
raise NotImplementedError
3840

41+
@abc.abstractmethod
3942
def irc_send(self, data):
4043
"""Send an IRC line as raw ``data``.
4144
4245
:param bytes data: raw line to send
4346
"""
44-
raise NotImplementedError
4547

4648
def send_command(self, *args, **kwargs):
4749
"""Send a command through the IRC connection.

sopel/irc/isupport.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ def parse_parameter(arg):
143143
return (key, parser(value))
144144

145145

146-
class ISupport(object):
146+
class ISupport:
147147
"""Storage class for IRC's ``ISUPPORT`` feature.
148148
149149
An instance of ``ISupport`` can be used as a read-only dict, to store
@@ -196,7 +196,7 @@ def __setattr__(self, name, value):
196196
# make sure you can't set the value of any ISUPPORT attribute yourself
197197
if name == '_ISupport__isupport':
198198
# allow to set self.__isupport inside of the class
199-
super(ISupport, self).__setattr__(name, value)
199+
super().__setattr__(name, value)
200200
elif name in self.__isupport:
201201
# reject any modification of __isupport
202202
raise AttributeError("Can't set value for %r" % name)

sopel/irc/utils.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ def safe(string):
5959
return string
6060

6161

62-
class CapReq(object):
62+
class CapReq:
6363
"""Represents a pending CAP REQ request.
6464
6565
:param str prefix: either ``=`` (must be enabled),

sopel/logger.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class IrcLoggingHandler(logging.Handler):
1818
Implementation of a :class:`logging.Handler`.
1919
"""
2020
def __init__(self, bot, level):
21-
super(IrcLoggingHandler, self).__init__(level)
21+
super().__init__(level)
2222
self._bot = bot
2323
self._channel = bot.settings.core.logging_channel
2424

@@ -52,7 +52,7 @@ class ChannelOutputFormatter(logging.Formatter):
5252
Implementation of a :class:`logging.Formatter`.
5353
"""
5454
def __init__(self, fmt='[%(filename)s] %(message)s', datefmt=None):
55-
super(ChannelOutputFormatter, self).__init__(fmt=fmt, datefmt=datefmt)
55+
super().__init__(fmt=fmt, datefmt=datefmt)
5656

5757
def formatException(self, exc_info):
5858
"""Format the exception info as a string for output.

sopel/modules/admin.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,13 @@ def setup(bot):
5555

5656
class InvalidSection(Exception):
5757
def __init__(self, section):
58-
super(InvalidSection, self).__init__(self, 'Section [{}] does not exist.'.format(section))
58+
super().__init__(self, 'Section [{}] does not exist.'.format(section))
5959
self.section = section
6060

6161

6262
class InvalidSectionOption(Exception):
6363
def __init__(self, section, option):
64-
super(InvalidSectionOption, self).__init__(self, 'Section [{}] does not have option \'{}\'.'.format(section, option))
64+
super().__init__(self, 'Section [{}] does not have option \'{}\'.'.format(section, option))
6565
self.section = section
6666
self.option = option
6767

sopel/modules/currency.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,13 +86,13 @@ def setup(bot):
8686
class FixerError(Exception):
8787
"""A Fixer.io API Error Exception"""
8888
def __init__(self, status):
89-
super(FixerError, self).__init__("FixerError: {}".format(status))
89+
super().__init__("FixerError: {}".format(status))
9090

9191

9292
class UnsupportedCurrencyError(Exception):
9393
"""A currency is currently not supported by the API"""
9494
def __init__(self, currency):
95-
super(UnsupportedCurrencyError, self).__init__(currency)
95+
super().__init__(currency)
9696

9797

9898
def build_reply(amount, base, target, out_string):

0 commit comments

Comments
 (0)