Skip to content

Commit 43ff316

Browse files
committed
It's 2025; use Ruff.
1 parent 7df5bea commit 43ff316

File tree

8 files changed

+100
-61
lines changed

8 files changed

+100
-61
lines changed

.github/workflows/python-package.yml

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# This workflow will install Python dependencies, run tests and lint with a variety of Python versions
22
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-python-with-github-actions
33

4-
name: PyTest & Flake8
4+
name: PyTest & Ruff
55

66
on:
77
push:
@@ -16,7 +16,7 @@ jobs:
1616
runs-on: ubuntu-latest
1717
strategy:
1818
matrix:
19-
python-version: [3.7, 3.8, 3.9, "3.10", "3.11"]
19+
python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"]
2020
steps:
2121
- uses: actions/checkout@v2
2222
- name: Set up Python ${{ matrix.python-version }}
@@ -32,19 +32,13 @@ jobs:
3232
echo "::set-env name=PATH::$PATH:$PWD/protoc/bin/"
3333
sudo apt-get install -qq libsnappy-dev
3434
python -m pip install --upgrade pip
35-
pip install flake8 pytest
35+
pip install ruff pytest
3636
pip install -r requirements.txt
3737
env:
3838
ACTIONS_ALLOW_UNSECURE_COMMANDS: 'true'
3939
- name: Build package
4040
run: make
41-
- name: Lint with flake8
42-
run: |
43-
# stop the build if there are Python syntax errors or undefined names
44-
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics --exclude keynote_parser/generated
45-
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
46-
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics --exclude keynote_parser/generated
41+
- name: Lint with ruff
42+
run: ruff check . --exclude keynote_parser/generated
4743
- name: Test with pytest
48-
run: |
49-
export PYTHONPATH=$PYTHONPATH:$(pwd)
50-
pytest --cov=keynote_parser
44+
run: PYTHONPATH=$PYTHONPATH:$(pwd) pytest --cov=keynote_parser

Makefile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ keynote_parser/generated/%_pb2.py: protos/%.proto keynote_parser/generated
1919

2020
keynote_parser/generated/__init__.py: keynote_parser/generated $(PROTO_CLASSES)
2121
touch $@
22-
# Huge hack for py3 support, see https://github.com/protocolbuffers/protobuf/issues/1491
23-
futurize --no-diffs --nobackups --both-stages --processes 4 -w keynote_parser/generated/
22+
python3 dumper/rewrite_imports.py keynote_parser/generated/*.py
2423

2524
clean:
2625
rm -rf keynote_parser/generated

dumper/protodump.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -249,7 +249,7 @@ def extract_proto_from_file(filename, descriptor_pool):
249249

250250
try:
251251
name_length, new_pos = _DecodeVarint(data, marker_start)
252-
except Exception as e:
252+
except Exception:
253253
# Expected a VarInt here, so if not, continue
254254
offset = suffix_position + len(PROTO_MARKER)
255255
continue
@@ -279,7 +279,7 @@ def extract_proto_from_file(filename, descriptor_pool):
279279
and proto_file.path != "google/protobuf/descriptor.proto"
280280
):
281281
yield proto_file
282-
except Exception as e:
282+
except Exception:
283283
pass
284284

285285
offset = marker_start + descriptor_length

dumper/rewrite_imports.py

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import argparse
2+
import re
3+
4+
REGEX = re.compile(r"^import (.*_pb2) as (.*__pb2)$")
5+
6+
7+
def main():
8+
parser = argparse.ArgumentParser()
9+
parser.add_argument("files", nargs="+")
10+
args = parser.parse_args()
11+
12+
for file in args.files:
13+
with open(file, "r") as f:
14+
content = f.read()
15+
content = REGEX.sub(r"import keynote_parser.generated.\1 as \2", content)
16+
with open(file, "w") as f:
17+
f.write(content)
18+
print(f"Rewrote {file}.")
19+
20+
21+
if __name__ == "__main__":
22+
main()

keynote_parser/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,3 @@
2222
__description__ = "A tool for manipulating Apple Keynote presentation files."
2323
__url__ = "https://github.com/psobot/keynote-parser"
2424
__new_issue_url__ = "https://github.com/psobot/keynote-parser/issues/new"
25-
__command_line_invocation__ = False

keynote_parser/bundle_utils.py

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,46 @@
1+
import inspect
12
import os
2-
import sys
3-
import warnings
43
import plistlib
4+
import sys
55
import urllib.parse
6-
from colorama import init as colorama_init
6+
import warnings
7+
78
from colorama import Fore
9+
from colorama import init as colorama_init
10+
811
from keynote_parser import (
9-
__version__,
10-
__supported_keynote_version__,
1112
__new_issue_url__,
12-
__command_line_invocation__,
13+
__supported_keynote_version__,
14+
__version__,
1315
)
1416
from keynote_parser.macos_app_version import MacOSAppVersion
1517

16-
DEFAULT_KEYNOTE_INSTALL_PATH = '/Applications/Keynote.app'
17-
VERSION_PLIST_PATH = 'Contents/version.plist'
18+
DEFAULT_KEYNOTE_INSTALL_PATH = "/Applications/Keynote.app"
19+
VERSION_PLIST_PATH = "Contents/version.plist"
1820

1921

2022
colorama_init()
2123

2224

2325
def get_installed_keynote_version():
2426
try:
25-
fp = open(os.path.join(DEFAULT_KEYNOTE_INSTALL_PATH, VERSION_PLIST_PATH), 'rb')
27+
fp = open(os.path.join(DEFAULT_KEYNOTE_INSTALL_PATH, VERSION_PLIST_PATH), "rb")
2628
except IOError:
2729
return None
2830
version_dict = plistlib.load(fp)
2931
return MacOSAppVersion(
30-
version_dict['CFBundleShortVersionString'],
31-
version_dict['CFBundleVersion'],
32-
version_dict['ProductBuildVersion'],
32+
version_dict["CFBundleShortVersionString"],
33+
version_dict["CFBundleVersion"],
34+
version_dict["ProductBuildVersion"],
3335
)
3436

3537

3638
class KeynoteVersionWarning(UserWarning):
3739
def __init__(self, installed_keynote_version):
3840
issue_title = "Please add support for Keynote %s" % installed_keynote_version
39-
new_issue_url = __new_issue_url__ + "?" + urllib.parse.urlencode({"title": issue_title})
41+
new_issue_url = (
42+
__new_issue_url__ + "?" + urllib.parse.urlencode({"title": issue_title})
43+
)
4044
super(UserWarning, self).__init__(
4145
(
4246
"KeynoteVersionWarning: "
@@ -97,7 +101,9 @@ def warn_once_on_newer_keynote(installed_keynote_version=None):
97101
if DID_WARN:
98102
return False
99103

100-
installed_keynote_version = installed_keynote_version or get_installed_keynote_version()
104+
installed_keynote_version = (
105+
installed_keynote_version or get_installed_keynote_version()
106+
)
101107
if not installed_keynote_version:
102108
return False
103109

@@ -113,5 +119,9 @@ def warn_once_on_newer_keynote(installed_keynote_version=None):
113119
return DID_WARN
114120

115121

116-
if not __command_line_invocation__ and "pytest" not in sys.modules:
122+
IS_INVOKED_ON_COMMAND_LINE = any(
123+
frame.function == "__main__" for frame in inspect.stack()
124+
)
125+
126+
if not IS_INVOKED_ON_COMMAND_LINE and "pytest" not in sys.modules:
117127
warn_once_on_newer_keynote()

keynote_parser/command_line.py

Lines changed: 38 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,73 @@
1-
from __future__ import print_function
2-
from __future__ import absolute_import
3-
import argparse
1+
from __future__ import absolute_import, print_function
42

5-
import keynote_parser
3+
import argparse
4+
from collections import Counter
65

7-
keynote_parser.__command_line_invocation__ = True # noqa
6+
from keynote_parser import __supported_keynote_version__, __version__
87

9-
from keynote_parser import __version__, __supported_keynote_version__
10-
from collections import Counter
11-
from .bundle_utils import warn_once_on_newer_keynote, get_installed_keynote_version
8+
from .bundle_utils import get_installed_keynote_version, warn_once_on_newer_keynote
129
from .file_utils import process
1310
from .replacement import Replacement, parse_json
1411

1512

1613
def parse_replacements(**kwargs):
17-
json_filename = kwargs.get('replacements')
14+
json_filename = kwargs.get("replacements")
1815
if json_filename:
1916
return parse_json(json_filename)
2017
else:
2118
return []
2219

2320

2421
def unpack_command(input, output=None, **kwargs):
25-
process(input, output or input.replace('.key', ''), replacements=parse_replacements(**kwargs))
22+
process(
23+
input,
24+
output or input.replace(".key", ""),
25+
replacements=parse_replacements(**kwargs),
26+
)
2627

2728

2829
def pack_command(input, output=None, **kwargs):
29-
process(input, output or (input + ".key"), replacements=parse_replacements(**kwargs))
30+
process(
31+
input, output or (input + ".key"), replacements=parse_replacements(**kwargs)
32+
)
3033

3134

3235
def ls_command(input, **kwargs):
33-
process(input, '-')
36+
process(input, "-")
3437

3538

3639
def cat_command(input, filename, **kwargs):
3740
process(
3841
input,
39-
'-',
42+
"-",
4043
subfile=filename,
4144
replacements=parse_replacements(**kwargs),
42-
raw=kwargs.get('raw'),
45+
raw=kwargs.get("raw"),
4346
)
4447

4548

4649
def replace_command(input, **kwargs):
47-
output = kwargs.get('output', None) or input
50+
output = kwargs.get("output", None) or input
4851
replacements = parse_replacements(**kwargs)
49-
find, _replace = kwargs.get('find'), kwargs.get('replace')
52+
find, _replace = kwargs.get("find"), kwargs.get("replace")
5053
if find and _replace:
5154
replacements.append(Replacement(find, _replace))
5255
if not replacements:
5356
print("WARNING: No replacements passed. No change.")
5457
return
55-
for ((old, new), count) in list(Counter(process(input, output, replacements)).items()):
58+
for (old, new), count in list(
59+
Counter(process(input, output, replacements)).items()
60+
):
5661
if count == 1:
5762
print("Replaced %s with %s." % (repr(old), repr(new)))
5863
else:
5964
print("Replaced %s with %s %d times." % (repr(old), repr(new), count))
6065

6166

6267
def add_replacement_arg(parser):
63-
parser.add_argument("--replacements", help="apply replacements from a json or yaml file")
68+
parser.add_argument(
69+
"--replacements", help="apply replacements from a json or yaml file"
70+
)
6471

6572

6673
def main():
@@ -76,38 +83,42 @@ def main():
7683
)
7784
% (__version__, __supported_keynote_version__, install_warning)
7885
)
79-
parser.add_argument('-v', '--version', action='version', version=__version__)
86+
parser.add_argument("-v", "--version", action="version", version=__version__)
8087

8188
subparsers = parser.add_subparsers()
8289

83-
parser_unpack = subparsers.add_parser('unpack')
90+
parser_unpack = subparsers.add_parser("unpack")
8491
parser_unpack.add_argument("input", help="a .key file")
8592
parser_unpack.add_argument("--output", "-o", help="a directory name to unpack into")
8693
add_replacement_arg(parser_unpack)
8794
parser_unpack.set_defaults(func=unpack_command)
8895

89-
parser_pack = subparsers.add_parser('pack')
96+
parser_pack = subparsers.add_parser("pack")
9097
parser_pack.add_argument("input", help="a directory of an unpacked .key file")
91-
parser_pack.add_argument("--output", "-o", help="a keynote file name to unpack into")
98+
parser_pack.add_argument(
99+
"--output", "-o", help="a keynote file name to unpack into"
100+
)
92101
add_replacement_arg(parser_pack)
93102
parser_pack.set_defaults(func=pack_command)
94103

95-
parser_ls = subparsers.add_parser('ls')
104+
parser_ls = subparsers.add_parser("ls")
96105
parser_ls.add_argument("input", help="a .key file")
97106
parser_ls.set_defaults(func=ls_command)
98107

99-
parser_cat = subparsers.add_parser('cat')
108+
parser_cat = subparsers.add_parser("cat")
100109
parser_cat.add_argument("input", help="a .key file")
101110
parser_cat.add_argument(
102111
"filename", help="a file within that .key file to cat, decoding .iwa to .yaml"
103112
)
104113
parser_cat.add_argument(
105-
"--raw", action='store_true', help="always return the original file with no decoding"
114+
"--raw",
115+
action="store_true",
116+
help="always return the original file with no decoding",
106117
)
107118
add_replacement_arg(parser_cat)
108119
parser_cat.set_defaults(func=cat_command)
109120

110-
parser_replace = subparsers.add_parser('replace')
121+
parser_replace = subparsers.add_parser("replace")
111122
parser_replace.add_argument("input", help="a .key file")
112123
parser_replace.add_argument("--output", "-o", help="a .key file to output to")
113124
parser_replace.add_argument("--find", help="a pattern to search for in text")
@@ -116,7 +127,7 @@ def main():
116127
parser_replace.set_defaults(func=replace_command)
117128

118129
args = parser.parse_args()
119-
if hasattr(args, 'func'):
130+
if hasattr(args, "func"):
120131
warn_once_on_newer_keynote()
121132
args.func(**vars(args))
122133
else:

tests/test_bundle_utils.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# -*- coding: utf-8 -*-
2+
import warnings
3+
24
import pytest
35

46
from keynote_parser import bundle_utils
@@ -10,6 +12,8 @@ def test_warn_on_old_version(capsys):
1012
with pytest.warns(bundle_utils.KeynoteVersionWarning):
1113
bundle_utils.warn_once_on_newer_keynote(installed_keynote_version=dummy_version)
1214

13-
# Second call/import should not warn
14-
with pytest.warns(None):
15+
# Second call/import should not warn:
16+
with warnings.catch_warnings():
17+
warnings.simplefilter("error")
18+
1519
bundle_utils.warn_once_on_newer_keynote(installed_keynote_version=dummy_version)

0 commit comments

Comments
 (0)