Skip to content

Commit c359890

Browse files
committed
Use Ruff + pre-commit for linting & formatting
1 parent 0ddb16d commit c359890

File tree

7 files changed

+84
-42
lines changed

7 files changed

+84
-42
lines changed

.github/workflows/test.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@ on:
77
branches: [master]
88

99
jobs:
10+
ruff: # https://docs.astral.sh/ruff
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v4
14+
- run: pip install --user ruff
15+
- run: ruff check --output-format=github
16+
1017
test:
18+
needs: ruff
1119
runs-on: ubuntu-latest
1220
strategy:
1321
fail-fast: false

.pre-commit-config.yaml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
exclude: ".*test-data.*"
2+
3+
repos:
4+
- repo: https://github.com/astral-sh/ruff-pre-commit
5+
rev: v0.6.9
6+
hooks:
7+
- id: ruff
8+
args: [--fix, --exit-non-zero-on-fix]
9+
- id: ruff-format
10+
11+
- repo: https://github.com/pre-commit/pre-commit-hooks
12+
rev: v5.0.0
13+
hooks:
14+
- id: check-added-large-files
15+
args: ["--maxkb=128"]
16+
- id: check-ast
17+
- id: check-byte-order-marker
18+
- id: check-case-conflict
19+
- id: check-docstring-first
20+
- id: check-executables-have-shebangs
21+
- id: check-json
22+
- id: check-merge-conflict
23+
- id: check-symlinks
24+
- id: check-xml
25+
- id: check-yaml
26+
args: ["--unsafe"]
27+
- id: debug-statements
28+
- id: detect-aws-credentials
29+
args: ["--allow-missing-credentials"]
30+
- id: detect-private-key
31+
- id: end-of-file-fixer
32+
- id: mixed-line-ending
33+
args: ["--fix=lf"]
34+
- id: trailing-whitespace
35+
- id: pretty-format-json
36+
args: ["--autofix", "--no-sort-keys", "--indent=4"]

README.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,11 @@ Contributing to bagit-python development
226226
Running the tests
227227
~~~~~~~~~~~~~~~~~
228228

229-
You can quickly run the tests by having setuptools install dependencies:
229+
You can quickly run the tests using the built-in unittest framework:
230230

231231
::
232232

233-
python setup.py test
233+
python -m unittest discover
234234

235235
If you have Docker installed, you can run the tests under Linux inside a
236236
container:

bagit.py

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def find_locale_dir():
140140
open_text_file = partial(codecs.open, encoding="utf-8", errors="strict")
141141

142142
# This is the same as decoding the byte values in codecs.BOM:
143-
UNICODE_BYTE_ORDER_MARK = "\uFEFF"
143+
UNICODE_BYTE_ORDER_MARK = "\ufeff"
144144

145145

146146
def make_bag(
@@ -422,8 +422,8 @@ def compare_manifests_with_fs(self):
422422

423423
def compare_fetch_with_fs(self):
424424
"""Compares the fetch entries with the files actually
425-
in the payload, and returns a list of all the files
426-
that still need to be fetched.
425+
in the payload, and returns a list of all the files
426+
that still need to be fetched.
427427
"""
428428

429429
files_on_fs = set(self.payload_files())
@@ -449,7 +449,7 @@ def payload_files(self):
449449
yield rel_path
450450

451451
def payload_entries(self):
452-
"""Return a dictionary of items """
452+
"""Return a dictionary of items"""
453453
# Don't use dict comprehension (compatibility with Python < 2.7)
454454
return dict(
455455
(key, value)
@@ -618,7 +618,9 @@ def is_valid(self, processes=1, fast=False, completeness_only=False):
618618
"""
619619

620620
try:
621-
self.validate(processes=processes, fast=fast, completeness_only=completeness_only)
621+
self.validate(
622+
processes=processes, fast=fast, completeness_only=completeness_only
623+
)
622624
except BagError:
623625
return False
624626

@@ -776,7 +778,10 @@ def validate_fetch(self):
776778

777779
# each parsed url must resolve to a scheme and point to a netloc
778780
# if the scheme is file, netloc is not necessary
779-
if not (all((parsed_url.scheme, parsed_url.netloc)) or parsed_url.scheme == "file"):
781+
if not (
782+
all((parsed_url.scheme, parsed_url.netloc))
783+
or parsed_url.scheme == "file"
784+
):
780785
raise BagError(_("Malformed URL in fetch.txt: %s") % url)
781786

782787
def _validate_contents(self, processes=1, fast=False, completeness_only=False):
@@ -851,11 +856,11 @@ def _validate_completeness(self):
851856
only_in_manifests, only_on_fs = self.compare_manifests_with_fs()
852857
for path in only_in_manifests:
853858
e = FileMissing(path)
854-
LOGGER.warning(force_unicode(e))
859+
LOGGER.warning(str(e))
855860
errors.append(e)
856861
for path in only_on_fs:
857862
e = UnexpectedFile(path)
858-
LOGGER.warning(force_unicode(e))
863+
LOGGER.warning(str(e))
859864
errors.append(e)
860865

861866
if errors:
@@ -906,7 +911,7 @@ def _validate_entries(self, processes):
906911
e = ChecksumMismatch(
907912
rel_path, alg, stored_hash.lower(), computed_hash
908913
)
909-
LOGGER.warning(force_unicode(e))
914+
LOGGER.warning(str(e))
910915
errors.append(e)
911916

912917
if errors:
@@ -963,7 +968,7 @@ def __init__(self, message, details=None):
963968

964969
def __str__(self):
965970
if len(self.details) > 0:
966-
details = "; ".join([force_unicode(e) for e in self.details])
971+
details = "; ".join([str(e) for e in self.details])
967972
return "%s: %s" % (self.message, details)
968973
return self.message
969974

@@ -988,7 +993,7 @@ def __str__(self):
988993
return _(
989994
'%(path)s %(algorithm)s validation failed: expected="%(expected)s" found="%(found)s"'
990995
) % {
991-
"path": force_unicode(self.path),
996+
"path": str(self.path),
992997
"algorithm": self.algorithm,
993998
"expected": self.expected,
994999
"found": self.found,
@@ -997,9 +1002,9 @@ def __str__(self):
9971002

9981003
class FileMissing(ManifestErrorDetail):
9991004
def __str__(self):
1000-
return _(
1001-
"%s exists in manifest but was not found on filesystem"
1002-
) % force_unicode(self.path)
1005+
return _("%s exists in manifest but was not found on filesystem") % str(
1006+
self.path
1007+
)
10031008

10041009

10051010
class UnexpectedFile(ManifestErrorDetail):
@@ -1138,7 +1143,7 @@ def _calc_hashes(args):
11381143
try:
11391144
f_hashes = _calculate_file_hashes(full_path, f_hashers)
11401145
except BagValidationError as e:
1141-
f_hashes = dict((alg, force_unicode(e)) for alg in f_hashers.keys())
1146+
f_hashes = dict((alg, str(e)) for alg in f_hashers.keys())
11421147

11431148
return rel_path, f_hashes, hashes
11441149

@@ -1161,7 +1166,7 @@ def _calculate_file_hashes(full_path, f_hashers):
11611166
except (OSError, IOError) as e:
11621167
raise BagValidationError(
11631168
_("Could not read %(filename)s: %(error)s")
1164-
% {"filename": full_path, "error": force_unicode(e)}
1169+
% {"filename": full_path, "error": str(e)}
11651170
)
11661171

11671172
return dict((alg, h.hexdigest()) for alg, h in f_hashers.items())
@@ -1187,11 +1192,11 @@ def _load_tag_file(tag_file_name, encoding="utf-8-sig"):
11871192

11881193
def _parse_tags(tag_file):
11891194
"""Parses a tag file, according to RFC 2822. This
1190-
includes line folding, permitting extra-long
1191-
field values.
1195+
includes line folding, permitting extra-long
1196+
field values.
11921197
1193-
See http://www.faqs.org/rfcs/rfc2822.html for
1194-
more information.
1198+
See http://www.faqs.org/rfcs/rfc2822.html for
1199+
more information.
11951200
"""
11961201

11971202
tag_name = None
@@ -1237,7 +1242,7 @@ def _make_tag_file(bag_info_path, bag_info):
12371242
values = [values]
12381243
for txt in values:
12391244
# strip CR, LF and CRLF so they don't mess up the tag file
1240-
txt = re.sub(r"\n|\r|(\r\n)", "", force_unicode(txt))
1245+
txt = re.sub(r"\n|\r|(\r\n)", "", str(txt))
12411246
f.write("%s: %s\n" % (h, txt))
12421247

12431248

@@ -1433,19 +1438,6 @@ def _decode_filename(s):
14331438
return s
14341439

14351440

1436-
def force_unicode_py2(s):
1437-
"""Reliably return a Unicode string given a possible unicode or byte string"""
1438-
if isinstance(s, str):
1439-
return s.decode("utf-8")
1440-
else:
1441-
return unicode(s)
1442-
1443-
1444-
if sys.version_info > (3, 0):
1445-
force_unicode = str
1446-
else:
1447-
force_unicode = force_unicode_py2
1448-
14491441
# following code is used for command line program
14501442

14511443

@@ -1531,7 +1523,10 @@ def _make_parser():
15311523
metadata_args = parser.add_argument_group(_("Optional Bag Metadata"))
15321524
for header in STANDARD_BAG_INFO_HEADERS:
15331525
metadata_args.add_argument(
1534-
"--%s" % header.lower(), type=str, action=BagHeaderAction, default=argparse.SUPPRESS
1526+
"--%s" % header.lower(),
1527+
type=str,
1528+
action=BagHeaderAction,
1529+
default=argparse.SUPPRESS,
15351530
)
15361531

15371532
parser.add_argument(
@@ -1574,7 +1569,9 @@ def main():
15741569
parser.error(_("--fast is only allowed as an option for --validate!"))
15751570

15761571
if args.completeness_only and not args.validate:
1577-
parser.error(_("--completeness-only is only allowed as an option for --validate!"))
1572+
parser.error(
1573+
_("--completeness-only is only allowed as an option for --validate!")
1574+
)
15781575

15791576
_configure_logging(args)
15801577

@@ -1593,7 +1590,9 @@ def main():
15931590
if args.fast:
15941591
LOGGER.info(_("%s valid according to Payload-Oxum"), bag_dir)
15951592
elif args.completeness_only:
1596-
LOGGER.info(_("%s is complete and valid according to Payload-Oxum"), bag_dir)
1593+
LOGGER.info(
1594+
_("%s is complete and valid according to Payload-Oxum"), bag_dir
1595+
)
15971596
else:
15981597
LOGGER.info(_("%s is valid"), bag_dir)
15991598
except BagError as e:

bench.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
"""
44
This is a little benchmarking script to exercise bagit.make_bag and
5-
bagit.validate using 1-8 parallel processes. It will download some images
5+
bagit.validate using 1-8 parallel processes. It will download some images
66
from NASA for use in bagging the first time it is run.
77
"""
88

pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,3 @@ known_first_party = "bagit"
3434
[tool.coverage.run]
3535
branch = true
3636
include = "bagit.py"
37-

test.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ def test_sha1_tagfile(self):
444444
bag = bagit.make_bag(self.tmpdir, checksum=["sha1"], bag_info=info)
445445
self.assertTrue(os.path.isfile(j(self.tmpdir, "tagmanifest-sha1.txt")))
446446
self.assertEqual(
447-
"f69110479d0d395f7c321b3860c2bc0c96ae9fe8",
447+
"3f7423acbb8395ff11dfeb16b4172e7ccc2c529e",
448448
bag.entries["bag-info.txt"]["sha1"],
449449
)
450450

0 commit comments

Comments
 (0)