Skip to content

Commit 6f943f7

Browse files
authored
Merge pull request #59 from phw/ruff-lint
Enabled code linting with ruff
2 parents d499685 + 56b53f5 commit 6f943f7

File tree

9 files changed

+89
-22
lines changed

9 files changed

+89
-22
lines changed

.github/workflows/lint.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: Linting
2+
on:
3+
push:
4+
paths: &path-list
5+
- '**/*.py'
6+
pull_request:
7+
paths: *path-list
8+
9+
jobs:
10+
ruff:
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@v6
14+
- name: Ruff lint
15+
uses: astral-sh/ruff-action@v3
16+
with:
17+
args: "check --output-format=github"

.pre-commit-config.yaml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
default_install_hook_types: [pre-commit, pre-push]
2+
repos:
3+
- repo: https://github.com/astral-sh/ruff-pre-commit
4+
rev: v0.14.13
5+
hooks:
6+
- id: ruff-check
7+
args: [--fix]
8+
- repo: local
9+
hooks:
10+
- id: pytest
11+
name: Run pytest
12+
entry: uv run --frozen pytest --exitfirst
13+
language: python
14+
types: [python]
15+
stages: [pre-push]
16+
pass_filenames: false
17+
always_run: true

discid/__init__.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,19 @@
3535

3636
__version__ = "1.3.0"
3737

38+
__all__ = [
39+
"LIBDISCID_VERSION_STRING",
40+
"FEATURES",
41+
"FEATURES_IMPLEMENTED",
42+
"Disc",
43+
"Track",
44+
"DiscError",
45+
"TOCError",
46+
"read",
47+
"put",
48+
"get_default_device",
49+
]
50+
3851

3952
# these constants are defined here so sphinx can catch the "docstrings"
4053

discid/disc.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232

3333
FEATURES_IMPLEMENTED = list(_FEATURE_MAPPING.keys())
3434

35-
def read(device=None, features=[]):
35+
def read(device=None, features=None):
3636
"""Reads the TOC from the device given as string
3737
and returns a :class:`Disc` object.
3838
@@ -123,14 +123,17 @@ def _get_error_msg(self):
123123
_LIB.discid_read_sparse.restype = c_int
124124
except AttributeError:
125125
pass
126-
def read(self, device=None, features=[]):
126+
def read(self, device=None, features=None):
127127
"""Reads the TOC from the device given as string
128128
129129
The user is supposed to use :func:`discid.read`.
130130
"""
131131
if "read" not in FEATURES:
132132
raise NotImplementedError("discid_read not implemented on platform")
133133

134+
if features is None:
135+
features = []
136+
134137
# only use features implemented on this platform and in this module
135138
self._requested_features = list(set(features) & set(FEATURES)
136139
& set(FEATURES_IMPLEMENTED))

discid/libdiscid.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from ctypes import c_void_p, c_char_p
2727
from ctypes.util import find_library
2828

29-
from discid.util import _encode, _decode
29+
from discid.util import _decode
3030

3131
_LIB_BASE_NAME = "discid"
3232
_LIB_MAJOR_VERSION = 0
@@ -155,7 +155,7 @@ def _get_features():
155155
features = ["read"] # no generic platform yet
156156
try:
157157
# test for ISRC/MCN API (introduced 0.3.0)
158-
_LIB.discid_get_mcn
158+
_LIB.discid_get_mcn # noqa: B018 (useless-expression)
159159
except AttributeError:
160160
pass
161161
else:

discid/util.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,26 @@
2222

2323
SECTORS_PER_SECOND = 75
2424

25-
def _encode(string):
25+
def _encode(string: str|bytes):
2626
"""Encode (unicode) string to byte string
2727
"""
28-
try:
28+
if isinstance(string, str):
2929
return string.encode()
30-
except AttributeError:
31-
# already byte string (Python 3)
30+
elif isinstance(string, bytes):
3231
return string
32+
raise TypeError('Unexpected type, expected string or bytes')
3333
# UnicodeDecodeError (Python 2) is NOT caught
3434
# device names should be ASCII
3535

36-
def _decode(byte_string):
36+
def _decode(byte_string: bytes|str):
3737
"""Decode byte string to (unicode) string
3838
"""
3939
# this test for bytes works on Python 2 and 3
40-
if type(byte_string) == type(b"test"):
40+
if isinstance(byte_string, bytes):
4141
return byte_string.decode()
42-
else:
43-
# probably mocked for sphinx
44-
return None
42+
elif isinstance(byte_string, str):
43+
return byte_string
44+
raise TypeError('Unexpected type, expected string or bytes')
4545

4646
def _sectors_to_seconds(sectors):
4747
"""Round sectors to seconds like done on MusicBrainz Server

doc/conf.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
1-
import sys, os
1+
import ctypes
2+
import sys
3+
import os
4+
5+
# to gather version information
6+
import discid
27

38
sys.path.insert(0, os.path.abspath('.')) # for extensions
49
sys.path.insert(0, os.path.abspath('..')) # for the code
@@ -9,12 +14,8 @@ class Mock(object):
914
def __call__(self, *args): return Mock()
1015
def __getattr__(cls, name): return Mock()
1116

12-
import ctypes
1317
ctypes.cdll.LoadLibrary = Mock()
1418

15-
# to gather version information
16-
import discid
17-
1819
# -- General configuration -----------------------------------------------------
1920

2021
needs_sphinx = "1.0"
@@ -121,4 +122,3 @@ def __getattr__(cls, name): return Mock()
121122
]
122123

123124
texinfo_domain_indices = False
124-

pyproject.toml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,14 @@ docs = [
3636
"Sphinx~=8.1.3",
3737
"sphinx-rtd-theme~=3.0.2",
3838
]
39+
dev = [
40+
"pre-commit>=4.5.1",
41+
"ruff>=0.14.13",
42+
]
43+
44+
[tool.ruff]
45+
src=["discid"]
46+
line-length=120
47+
48+
[tool.ruff.lint]
49+
select = ["E", "F", "W", "B"]

test_discid.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import unittest
88

99
import discid
10+
import discid.util
1011

1112
test_discs = [
1213
{
@@ -37,13 +38,18 @@ class TestModulePrivate(unittest.TestCase):
3738
# lots of encoding tests
3839
# not part of the actual API, but this is quite different in Python 2/3
3940
def test_encode(self):
40-
self.assertTrue(type(discid.util._encode("test")) is type(b"test"))
41+
self.assertTrue(type(discid.util._encode("test")) is bytes)
4142
self.assertEqual(discid.util._encode("test"), b"test")
43+
self.assertEqual(discid.util._encode(b"test"), b"test")
44+
with self.assertRaises(TypeError):
45+
discid.util._encode(42) # type: ignore
4246

4347
def test_decode(self):
44-
self.assertTrue(type(discid.util._decode(b"test"))
45-
is type(b"test".decode()))
48+
self.assertTrue(type(discid.util._decode(b"test")) is str)
4649
self.assertEqual(discid.util._decode(b"test"), "test")
50+
self.assertEqual(discid.util._decode("test"), "test")
51+
with self.assertRaises(TypeError):
52+
discid.util._encode(42) # type: ignore
4753

4854
def test_encoding(self):
4955
string = "test"

0 commit comments

Comments
 (0)