Skip to content

Commit 2da12ad

Browse files
authored
Add Python linting and formatting checks (hellt#18)
* Lint and reformat with ruff * Change unnecessary f-string in tests * Add ruff to cicd.yml Add ruff for Python linting and formatting * Split out linting and formatting in cicd.yml * Update cicd.yml - step names describe themselves * Format line length * Add diff option to ruff format in cicd.yml
1 parent d2b4ccd commit 2da12ad

File tree

4 files changed

+70
-38
lines changed

4 files changed

+70
-38
lines changed

.github/workflows/cicd.yml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,38 @@ on:
1111
types: ["created"]
1212

1313
# GOAL:
14+
# - run ruff job on pushes to main branch or v* tag
15+
# - run ruff job on PRs against main branch
16+
# - run ruff job on Release creation
1417
# - run test job on pushes to main branch or v* tag
1518
# - run test job on PRs against main branch
1619
# - run test job on Release creation
1720
# - run docker job on the above events when the triggered actor is the repo owner
1821
# - run docker job on Release creation (ex: maybe a maintainer that isn't repo owner)
1922

2023
jobs:
24+
ruff:
25+
runs-on: ubuntu-latest
26+
steps:
27+
- name: Check out repository code
28+
uses: actions/checkout@v4
29+
30+
- name: Run Ruff linter
31+
uses: astral-sh/ruff-action@v1
32+
with:
33+
args: "check"
34+
changed-files: "true"
35+
36+
- name: Run Ruff formatter
37+
uses: astral-sh/ruff-action@v1
38+
with:
39+
args: "format --check --diff"
40+
changed-files: "true"
41+
2142
test:
2243
runs-on: ubuntu-latest
44+
needs:
45+
- "ruff"
2346
strategy:
2447
matrix:
2548
python-version: ["3.9", "3.10", "3.11", "3.12"]

fnsort.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def parse_arguments():
3838
action="store_true",
3939
help="Fix adjacent footnotes by adding a space between them",
4040
)
41-
41+
4242
parser.add_argument(
4343
"--keepnames",
4444
action="store_true",
@@ -86,8 +86,10 @@ def space_adjacent_references(text):
8686

8787
# slice the string to separate preceding character from inline reference
8888
# ex: s[^4]
89-
text = re.sub(note_re, f"{repl[0]} {repl[1:]}", text, flags=re.MULTILINE)
90-
89+
text = re.sub(
90+
note_re, f"{repl[0]} {repl[1:]}", text, flags=re.MULTILINE
91+
)
92+
9193
return text
9294

9395

@@ -117,7 +119,9 @@ def sort_footnotes(text, args):
117119
else:
118120
# Make a list of the footnote-references in order of appearance in the original footnotes in text.
119121
# This is not the order of the footnote contents, but the order of the footnote references in the text.
120-
newlabels = [f"[^{i+1}]: {labels[j]}" for (i, j) in enumerate(order)]
122+
newlabels = [
123+
f"[^{i+1}]: {labels[j]}" for (i, j) in enumerate(order)
124+
]
121125
except KeyError as e:
122126
# add custom exception to improve error output
123127
raise MissingFootnoteError(

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[tool.ruff]
2+
# Set the maximum line length to 79.
3+
line-length = 79

tests/test_footnote_sorting.py

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
def set_command_line_args(args):
8-
""" Set (what would otherwise be) command-line arguments """
8+
"""Set (what would otherwise be) command-line arguments"""
99
return argparse.Namespace(**args)
1010

1111

@@ -32,25 +32,22 @@ def setUpClass(self):
3232
# allow for full diff output
3333
# self.maxDiff = None
3434

35-
3635
def test_replace_reference(self):
37-
""" Inline reference replacement """
36+
"""Inline reference replacement"""
3837
# use the link regex from the fnsort import
39-
38+
4039
# "search" function only returns the first match
4140
match = fnsort.link.search(self.text)
4241
order = ["1", "3", "4", "2"]
4342

4443
# hedgehogs[^1]
45-
self.assertEqual(
46-
fnsort.replace_reference(match, order),
47-
"s[^1]"
48-
)
49-
44+
self.assertEqual(fnsort.replace_reference(match, order), "s[^1]")
5045

5146
def test_footnote_sort(self):
52-
""" Entire footnote sort process """
53-
self.assertEqual(fnsort.sort_footnotes(self.text, self.args), self.expected_text)
47+
"""Entire footnote sort process"""
48+
self.assertEqual(
49+
fnsort.sort_footnotes(self.text, self.args), self.expected_text
50+
)
5451

5552

5653
class TestDuplicates(unittest.TestCase):
@@ -73,29 +70,34 @@ def setUpClass(self):
7370
# allow for full diff output
7471
# self.maxDiff = None
7572

76-
7773
def test_replace_references_with_dups(self):
78-
""" Multiple reference replacements with duplicate tags """
74+
"""Multiple reference replacements with duplicate tags"""
7975
# find all matches
8076
matches = fnsort.link.finditer(self.text)
8177
order = ["1", "3", "2", "5", "4"]
8278

8379
# should be seven regex matches in duplicates.md
8480
expected = [
85-
"s[^1]", "s[^2]", " [^1]", "s[^3]", "s[^4]", "s[^5]", " [^2]"
81+
"s[^1]",
82+
"s[^2]",
83+
" [^1]",
84+
"s[^3]",
85+
"s[^4]",
86+
"s[^5]",
87+
" [^2]",
8688
]
8789

8890
# multiple assertions
8991
for i, match in enumerate(matches):
9092
self.assertEqual(
91-
fnsort.replace_reference(match, order),
92-
expected[i]
93+
fnsort.replace_reference(match, order), expected[i]
9394
)
9495

95-
9696
def test_footnote_sort_with_dups(self):
97-
""" Entire footnote sort process with duplicate tags """
98-
self.assertEqual(fnsort.sort_footnotes(self.text, self.args), self.expected_text)
97+
"""Entire footnote sort process with duplicate tags"""
98+
self.assertEqual(
99+
fnsort.sort_footnotes(self.text, self.args), self.expected_text
100+
)
99101

100102

101103
class TestFootnotesMustBeLast(unittest.TestCase):
@@ -118,9 +120,8 @@ def setUpClass(self):
118120
# allow for full diff output
119121
# self.maxDiff = None
120122

121-
122123
def test_footnote_sort_trailing_text(self):
123-
""" [negative test] Entire footnote sort process with text after the footnotes """
124+
"""[negative test] Entire footnote sort process with text after the footnotes"""
124125

125126
"""
126127
negative test
@@ -130,7 +131,9 @@ def test_footnote_sort_trailing_text(self):
130131
131132
in short this is not expected to return the desired output
132133
"""
133-
self.assertNotEqual(fnsort.sort_footnotes(self.text, self.args), self.expected_text)
134+
self.assertNotEqual(
135+
fnsort.sort_footnotes(self.text, self.args), self.expected_text
136+
)
134137

135138

136139
class TestAdjacentFootnotes(unittest.TestCase):
@@ -154,24 +157,23 @@ def setUpClass(self):
154157
# allow for full diff output
155158
# self.maxDiff = None
156159

157-
158160
def test_adjacent_inline_reference_spacing(self):
159-
""" Test spacing out adjacent inline references """
160-
with open(f"tests/adjacent/adjacent_spacing.md") as fh:
161+
"""Test spacing out adjacent inline references"""
162+
with open("tests/adjacent/adjacent_spacing.md") as fh:
161163
spacing_text = fh.read()
162164

163165
self.assertEqual(
164-
fnsort.space_adjacent_references(self.text),
165-
spacing_text
166+
fnsort.space_adjacent_references(self.text), spacing_text
166167
)
167168

168-
169169
def test_adjacent_footnote_sort(self):
170-
""" Entire footnote sort process with adjacent footnote references """
170+
"""Entire footnote sort process with adjacent footnote references"""
171171
if self.args.adjacent:
172172
self.text = fnsort.space_adjacent_references(self.text)
173173

174-
self.assertEqual(fnsort.sort_footnotes(self.text, self.args), self.expected_text)
174+
self.assertEqual(
175+
fnsort.sort_footnotes(self.text, self.args), self.expected_text
176+
)
175177

176178

177179
class TestKeepFootnoteNames(unittest.TestCase):
@@ -192,13 +194,14 @@ def setUpClass(self):
192194
# allow for full diff output
193195
# self.maxDiff = None
194196

195-
196197
def test_keep_footnote_names(self):
197-
""" Entire footnote sort process while retaining footnote names """
198+
"""Entire footnote sort process while retaining footnote names"""
198199
if self.args.adjacent:
199200
self.text = fnsort.space_adjacent_references(self.text)
200201

201-
self.assertEqual(fnsort.sort_footnotes(self.text, self.args), self.expected_text)
202+
self.assertEqual(
203+
fnsort.sort_footnotes(self.text, self.args), self.expected_text
204+
)
202205

203206

204207
class TestMissingFootnotes(unittest.TestCase):
@@ -219,7 +222,6 @@ def setUpClass(self):
219222
# allow for full diff output
220223
# self.maxDiff = None
221224

222-
223225
def test_missing_footnotes(self):
224226
"""
225227
[negative test] Entire footnote sort process with missing footnotes and inline references

0 commit comments

Comments
 (0)