Skip to content

Commit 21a58bb

Browse files
committed
ci: Add a lot of opinionated linters
Add a pre-commit configuration to apply a collection of linting and formatting plugins. These will be automatically run by tox in CI, but can also be setup to run as a pre-commit action in the local repo. Highlights: * Use black for code formatting * Use isort for import formatting * Add a number of flake8 plugins including bugbear
1 parent b56a2b6 commit 21a58bb

15 files changed

+343
-191
lines changed

.pre-commit-config.yaml

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
default_language_version:
2+
python: python3.11
3+
repos:
4+
- repo: https://github.com/pre-commit/pre-commit-hooks
5+
rev: v4.4.0
6+
hooks:
7+
- id: check-ast
8+
- id: check-builtin-literals
9+
- id: check-docstring-first
10+
- id: check-merge-conflict
11+
- id: check-yaml
12+
- id: check-toml
13+
- id: debug-statements
14+
- id: end-of-file-fixer
15+
- id: trailing-whitespace
16+
- id: name-tests-test
17+
- repo: https://github.com/asottile/add-trailing-comma
18+
rev: v3.1.0
19+
hooks:
20+
- id: add-trailing-comma
21+
args: ["--py36-plus"]
22+
- repo: https://github.com/asottile/pyupgrade
23+
rev: v3.13.0
24+
hooks:
25+
- id: pyupgrade
26+
args: ["--py37-plus"]
27+
- repo: https://github.com/PyCQA/isort
28+
rev: 5.12.0
29+
hooks:
30+
- id: isort
31+
args: ["--profile", "black", "--filter-files"]
32+
- repo: https://github.com/psf/black
33+
rev: 23.9.1
34+
hooks:
35+
- id: black
36+
- repo: https://github.com/asottile/blacken-docs
37+
rev: 1.16.0
38+
hooks:
39+
- id: blacken-docs
40+
additional_dependencies: [black==23.9.1]
41+
- repo: https://github.com/pre-commit/pygrep-hooks
42+
rev: v1.10.0
43+
hooks:
44+
- id: rst-backticks
45+
- repo: https://github.com/tox-dev/tox-ini-fmt
46+
rev: "1.3.1"
47+
hooks:
48+
- id: tox-ini-fmt
49+
args: ["-p", "lint"]
50+
- repo: https://github.com/PyCQA/flake8
51+
rev: 6.1.0
52+
hooks:
53+
- id: flake8
54+
additional_dependencies:
55+
- flake8-bugbear==23.3.12
56+
- flake8-comprehensions==3.11.1
57+
- flake8-pytest-style==1.7.2
58+
- flake8-unused-arguments==0.0.13
59+
- flake8-noqa==1.3.1
60+
- pep8-naming==0.13.3
61+
- flake8-pyproject==1.2.3
62+
- repo: https://github.com/PyCQA/doc8
63+
rev: v1.1.1
64+
hooks:
65+
- id: doc8
66+
- repo: meta
67+
hooks:
68+
- id: check-hooks-apply
69+
- id: check-useless-excludes

HISTORY.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ UNRELEASED
44
* Require irc>=20.0.0
55
* Convert to hatchling build system backend
66
* Replace Travis CI with GitHub Actions
7+
* Use pre-commit for linter checks
8+
* Use black for code formatting
9+
* Use isort for import formatting
10+
* Add a number of flake8 plugins including bugbear
711

812
v0.2.0
913
------

docs/conf.py

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
11
#!/usr/bin/env python3
2-
# -*- coding: utf-8 -*-
32
import datetime
43
import importlib.metadata
54

65
import sphinx_rtd_theme
76

87
extensions = [
9-
'sphinx.ext.autodoc',
10-
'sphinx.ext.intersphinx',
11-
'sphinx.ext.viewcode',
8+
"sphinx.ext.autodoc",
9+
"sphinx.ext.intersphinx",
10+
"sphinx.ext.viewcode",
1211
]
1312

1413
intersphinx_mapping = {
15-
'python': ('https://docs.python.org/3', None),
16-
'irc': ('https://python-irc.readthedocs.io/en/stable/', None),
14+
"python": ("https://docs.python.org/3", None),
15+
"irc": ("https://python-irc.readthedocs.io/en/stable/", None),
1716
}
1817

1918
# General information about the project.
@@ -25,13 +24,13 @@
2524
_origin_date = datetime.date(2017, 2, 19)
2625
_today = datetime.date.today()
2726

28-
copyright = f'{_origin_date.year}-{_today.year} {author} and contributors'
27+
copyright = f"{_origin_date.year}-{_today.year} {author} and contributors"
2928
release = version
3029

31-
master_doc = 'index'
32-
pygments_style = 'sphinx'
33-
html_theme = 'sphinx_rtd_theme'
30+
master_doc = "index"
31+
pygments_style = "sphinx"
32+
html_theme = "sphinx_rtd_theme"
3433
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
35-
html_static_path = ['_static']
34+
html_static_path = ["_static"]
3635

37-
suppress_warnings = ['image.nonlocal_uri']
36+
suppress_warnings = ["image.nonlocal_uri"]

examples/nickserv.py

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
#
32
# This file is part of IRC Bot Behavior Bundle (IB3)
43
# Copyright (C) 2017 Bryan Davis and contributors
@@ -23,11 +22,10 @@
2322
from ib3.auth import NickServ
2423
from ib3.connection import SSL
2524

26-
2725
logging.basicConfig(
2826
level=logging.DEBUG,
29-
format='%(asctime)s %(name)s %(levelname)s: %(message)s',
30-
datefmt='%Y-%m-%dT%H:%M:%SZ'
27+
format="%(asctime)s %(name)s %(levelname)s: %(message)s",
28+
datefmt="%Y-%m-%dT%H:%M:%SZ",
3129
)
3230
logging.captureWarnings(True)
3331

@@ -36,31 +34,33 @@ class TestBot(NickServ, SSL, Bot):
3634
pass
3735

3836

39-
if __name__ == '__main__':
37+
if __name__ == "__main__":
4038
parser = argparse.ArgumentParser(
41-
description='Example bot with NickServ auth')
42-
parser.add_argument('nick')
43-
parser.add_argument('password')
44-
parser.add_argument('channel')
39+
description="Example bot with NickServ auth",
40+
)
41+
parser.add_argument("nick")
42+
parser.add_argument("password")
43+
parser.add_argument("channel")
4544
parser.add_argument(
46-
'-u', '--username',
47-
help='Account name if different than nick',
45+
"-u",
46+
"--username",
47+
help="Account name if different than nick",
4848
)
4949
args = parser.parse_args()
5050

5151
bot = TestBot(
52-
server_list=[('irc.libera.chat', 6697)],
52+
server_list=[("irc.libera.chat", 6697)],
5353
nickname=args.nick,
5454
realname=args.nick,
5555
username=args.username,
5656
ident_password=args.password,
57-
channels=[args.channel]
57+
channels=[args.channel],
5858
)
5959
try:
6060
bot.start()
6161
except KeyboardInterrupt:
62-
bot.disconnect('KeyboardInterrupt!')
62+
bot.disconnect("KeyboardInterrupt!")
6363
except Exception:
64-
logging.getLogger('root').exception('Killed by unhandled exception')
65-
bot.disconnect('Exception!')
64+
logging.getLogger("root").exception("Killed by unhandled exception")
65+
bot.disconnect("Exception!")
6666
raise SystemExit()

examples/saslbot.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
#
32
# This file is part of IRC Bot Behavior Bundle (IB3)
43
# Copyright (C) 2017 Bryan Davis and contributors
@@ -26,24 +25,24 @@
2625
import ib3.connection
2726
import ib3.nick
2827

29-
3028
logging.basicConfig(
3129
level=logging.DEBUG,
32-
format='%(asctime)s %(name)s %(levelname)s: %(message)s',
33-
datefmt='%Y-%m-%dT%H:%M:%SZ'
30+
format="%(asctime)s %(name)s %(levelname)s: %(message)s",
31+
datefmt="%Y-%m-%dT%H:%M:%SZ",
3432
)
3533
logging.captureWarnings(True)
3634

37-
logger = logging.getLogger('saslbot')
35+
logger = logging.getLogger("saslbot")
3836

3937

4038
class SaslBot(ib3.auth.SASL, ib3.nick.Regain, ib3.connection.SSL, ib3.Bot):
4139
"""Example bot showing use of SASL auth, REGAIN, and SSL encryption."""
40+
4241
def on_privmsg(self, conn, event):
4342
self.do_command(conn, event, event.arguments[0])
4443

4544
def on_pubmsg(self, conn, event):
46-
args = event.arguments[0].split(':', 1)
45+
args = event.arguments[0].split(":", 1)
4746
if len(args) > 1:
4847
to = irc.strings.lower(args[0])
4948
if to == irc.strings.lower(conn.get_nickname()):
@@ -54,27 +53,28 @@ def do_command(self, conn, event, cmd):
5453
if to == conn.get_nickname():
5554
to = event.source.nick
5655

57-
if cmd == 'disconnect':
56+
if cmd == "disconnect":
5857
self.disconnect()
59-
elif cmd == 'die':
58+
elif cmd == "die":
6059
self.die()
6160
else:
62-
conn.privmsg(to, 'What does "{}" mean?'.format(cmd))
61+
conn.privmsg(to, f'What does "{cmd}" mean?')
6362

6463

65-
if __name__ == '__main__':
66-
parser = argparse.ArgumentParser(description='Example bot with SASL auth')
67-
parser.add_argument('nick')
68-
parser.add_argument('password')
69-
parser.add_argument('channel')
64+
if __name__ == "__main__":
65+
parser = argparse.ArgumentParser(description="Example bot with SASL auth")
66+
parser.add_argument("nick")
67+
parser.add_argument("password")
68+
parser.add_argument("channel")
7069
parser.add_argument(
71-
'-u', '--username',
72-
help='Account name if different than nick',
70+
"-u",
71+
"--username",
72+
help="Account name if different than nick",
7373
)
7474
args = parser.parse_args()
7575

7676
bot = SaslBot(
77-
server_list=[('irc.libera.chat', 6697)],
77+
server_list=[("irc.libera.chat", 6697)],
7878
nickname=args.nick,
7979
realname=args.nick,
8080
username=args.username,
@@ -84,8 +84,8 @@ def do_command(self, conn, event, cmd):
8484
try:
8585
bot.start()
8686
except KeyboardInterrupt:
87-
bot.disconnect('KeyboardInterrupt!')
87+
bot.disconnect("KeyboardInterrupt!")
8888
except Exception:
89-
logger.exception('Killed by unhandled exception')
90-
bot.disconnect('Exception!')
89+
logger.exception("Killed by unhandled exception")
90+
bot.disconnect("Exception!")
9191
raise SystemExit()

pyproject.toml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,3 +52,12 @@ build.targets.sdist.include = [
5252

5353
[tool.hatch.version]
5454
source = "vcs"
55+
56+
[tool.black]
57+
line_length = 88
58+
target_version = ["py37"]
59+
60+
[tool.isort]
61+
known_first_party = ["ib3", "tests"]
62+
line_length = 88
63+
profile = "black"

src/ib3/__init__.py

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
#
32
# This file is part of IRC Bot Behavior Bundle (IB3)
43
# Copyright (C) 2017 Bryan Davis and contributors
@@ -19,8 +18,8 @@
1918
import logging
2019

2120
import irc.bot
22-
from jaraco.stream import buffer
2321
import irc.client
22+
from jaraco.stream import buffer
2423

2524
logger = logging.getLogger(__name__)
2625

@@ -32,11 +31,11 @@ class Bot(irc.bot.SingleServerIRCBot):
3231
UTF-8 encoding handling for inbound messages. This is a nice base to start
3332
from when adding other IB3 mixins.
3433
"""
34+
3535
def __init__(self, *args, **kwargs):
3636
# A UTF-8 only world is a nice dream but the real world is all yucky
3737
# and full of legacy encoding issues that should not crash our bot.
38-
buffer.LenientDecodingLineBuffer.errors = 'replace'
39-
irc.client.ServerConnection.buffer_class = \
40-
buffer.LenientDecodingLineBuffer
38+
buffer.LenientDecodingLineBuffer.errors = "replace"
39+
irc.client.ServerConnection.buffer_class = buffer.LenientDecodingLineBuffer
4140

42-
super(Bot, self).__init__(*args, **kwargs)
41+
super().__init__(*args, **kwargs)

0 commit comments

Comments
 (0)