Skip to content

Commit 38b02a8

Browse files
authored
Merge pull request #61 from phw/add-type-hints
Added relevant type hints to public API
2 parents 78bbe2b + 1fe4470 commit 38b02a8

File tree

7 files changed

+105
-74
lines changed

7 files changed

+105
-74
lines changed

discid/disc.py

Lines changed: 32 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@
3131
FEATURES_IMPLEMENTED = list(_FEATURE_MAPPING.keys())
3232

3333

34-
def read(device=None, features=None):
34+
def read(
35+
device: str | bytes | None = None, features: list[str] | None = None
36+
) -> "Disc":
3537
"""Reads the TOC from the device given as string
3638
and returns a :class:`Disc` object.
3739
38-
That string can be either of :obj:`str <python:str>` or :obj:`bytes`.
40+
The device string can be either of :obj:`str <python:str>` or :obj:`bytes`.
3941
However, it should in no case contain non-ASCII characters.
4042
If no device is given, a default, also given by :func:`get_default_device`
4143
is used.
@@ -48,27 +50,31 @@ def read(device=None, features=None):
4850
A :exc:`DiscError` exception is raised when the reading fails,
4951
and :exc:`NotImplementedError` when libdiscid doesn't support
5052
reading discs on the current platform.
53+
54+
:param device: the device name to use or :obj:`None` for using the default device
55+
:param features: list of features to enable ("read" will always be assumed)
5156
"""
5257
disc = Disc()
5358
disc.read(device, features)
5459
return disc
5560

5661

57-
def put(first, last, disc_sectors, track_offsets):
62+
def put(first: int, last: int, disc_sectors: int, track_offsets: list[int]) -> "Disc":
5863
"""Creates a TOC based on the information given
5964
and returns a :class:`Disc` object.
6065
61-
Takes the `first` track and `last` **audio** track as :obj:`int`.
62-
`disc_sectors` is the end of the last audio track,
63-
normally the total sector count of the disc.
64-
`track_offsets` is a list of all audio track offsets.
65-
6666
Depending on how you get the total sector count,
6767
you might have to subtract 11400 (2:32 min.) for discs with data tracks.
6868
6969
A :exc:`TOCError` exception is raised when illegal parameters
7070
are provided.
7171
72+
:param first: number of the first audio track
73+
:param last: number of the last audio track
74+
:param disc_sectors: the end of the last audio track, normally the total
75+
sector count of the disc
76+
:param track_offsets: list of all audio track offsets
77+
7278
.. seealso:: :musicbrainz:`Disc ID Calculation`
7379
"""
7480
disc = Disc()
@@ -125,7 +131,9 @@ def _get_error_msg(self):
125131
except AttributeError:
126132
pass
127133

128-
def read(self, device=None, features=None):
134+
def read(
135+
self, device: str | bytes | None = None, features: list[str] | None = None
136+
) -> bool:
129137
"""Reads the TOC from the device given as string
130138
131139
The user is supposed to use :func:`discid.read`.
@@ -162,7 +170,9 @@ def read(self, device=None, features=None):
162170
_LIB.discid_put.argtypes = (c_void_p, c_int, c_int, c_void_p)
163171
_LIB.discid_put.restype = c_int
164172

165-
def put(self, first, last, disc_sectors, track_offsets):
173+
def put(
174+
self, first: int, last: int, disc_sectors: int, track_offsets: list[int]
175+
) -> bool:
166176
"""Creates a TOC based on the input given.
167177
168178
The user is supposed to use :func:`discid.put`.
@@ -282,21 +292,21 @@ def _get_mcn(self):
282292
return None
283293

284294
@property
285-
def id(self):
295+
def id(self) -> str:
286296
"""This is the MusicBrainz :musicbrainz:`Disc ID`,
287297
a :obj:`str <python:str>` object.
288298
"""
289299
return self._get_id()
290300

291301
@property
292-
def freedb_id(self):
302+
def freedb_id(self) -> str:
293303
"""This is the :musicbrainz:`FreeDB` Disc ID (without category),
294304
a :obj:`str <python:str>` object.
295305
"""
296306
return self._get_freedb_id()
297307

298308
@property
299-
def submission_url(self):
309+
def submission_url(self) -> str | None:
300310
"""Disc ID / TOC Submission URL for MusicBrainz
301311
302312
With this url you can submit the current TOC
@@ -313,7 +323,7 @@ def submission_url(self):
313323
return url
314324

315325
@property
316-
def toc_string(self):
326+
def toc_string(self) -> str:
317327
"""The TOC suitable as value of the `toc parameter`
318328
when accessing the MusicBrainz Web Service.
319329
@@ -337,33 +347,30 @@ def toc_string(self):
337347
return toc_string
338348

339349
@property
340-
def first_track_num(self):
350+
def first_track_num(self) -> int:
341351
"""Number of the first track"""
342352
return self._get_first_track_num()
343353

344354
@property
345-
def last_track_num(self):
355+
def last_track_num(self) -> int:
346356
"""Number of the last **audio** track"""
347357
return self._get_last_track_num()
348358

349359
@property
350-
def sectors(self):
360+
def sectors(self) -> int:
351361
"""Total length in sectors"""
352362
return self._get_sectors()
353363

354364
length = sectors
355365
"""This is an alias for :attr:`sectors`"""
356366

357367
@property
358-
def seconds(self):
368+
def seconds(self) -> int:
359369
"""Total length in seconds"""
360-
if self.sectors is None:
361-
return None
362-
else:
363-
return _sectors_to_seconds(self.sectors)
370+
return _sectors_to_seconds(self.sectors)
364371

365372
@property
366-
def mcn(self):
373+
def mcn(self) -> str | None:
367374
"""This is the Media Catalogue Number (MCN/UPC/EAN)
368375
369376
It is set after the `"mcn"` feature was requested on a read
@@ -373,7 +380,7 @@ def mcn(self):
373380
return self._get_mcn()
374381

375382
@property
376-
def tracks(self):
383+
def tracks(self) -> list[Track]:
377384
"""A list of :class:`Track` objects for this Disc."""
378385
tracks = []
379386
assert self._success
@@ -382,7 +389,7 @@ def tracks(self):
382389
return tracks
383390

384391
@property
385-
def cddb_query_string(self):
392+
def cddb_query_string(self) -> str:
386393
"""A CDDB query string suitable for querying CDDB servers.
387394
388395
This is a :obj:`str <python:str>` object

discid/libdiscid.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ def _get_version_string():
132132
_LIB.discid_get_default_device.restype = c_char_p
133133

134134

135-
def get_default_device():
135+
def get_default_device() -> str:
136136
"""The default device to use for :func:`read` on this platform
137137
given as a :obj:`str <python:str>` object.
138138
"""

discid/track.py

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,26 @@
1818
"""Track class"""
1919

2020
from ctypes import c_char_p, c_int, c_void_p
21+
from typing import TYPE_CHECKING
2122

2223
from discid.libdiscid import _LIB
2324
from discid.util import _decode, _sectors_to_seconds
2425

26+
if TYPE_CHECKING:
27+
from .disc import Disc
28+
2529

2630
class Track(object):
27-
"""Track objects are part of the :class:`Disc` class."""
31+
"""Track objects are part of the :class:`Disc` class.
32+
33+
:param disc: the :class:`Disc` object
34+
:param number: the track number
35+
"""
2836

29-
def __init__(self, disc, number):
37+
def __init__(self, disc: "Disc", number: int):
3038
self._disc = disc
3139
self._number = number
32-
assert self._disc._handle.value is not None
40+
assert self._disc._handle and self._disc._handle.value is not None
3341

3442
def __str__(self):
3543
assert self._disc._success
@@ -68,33 +76,33 @@ def _get_track_isrc(self):
6876
return None
6977

7078
@property
71-
def number(self):
79+
def number(self) -> int:
7280
"""The track number"""
7381
return self._number
7482

7583
@property
76-
def offset(self):
84+
def offset(self) -> int:
7785
"""The track offset"""
7886
return self._get_track_offset()
7987

8088
@property
81-
def sectors(self):
89+
def sectors(self) -> int:
8290
"""The track length in sectors"""
8391
return self._get_track_length()
8492

8593
length = sectors
8694
"""This is an alias for :attr:`sectors`"""
8795

8896
@property
89-
def seconds(self):
97+
def seconds(self) -> int:
9098
"""Track length in seconds"""
9199
return _sectors_to_seconds(self.sectors)
92100

93101
@property
94-
def isrc(self):
102+
def isrc(self) -> str | None:
95103
"""The International Standard Recording Code
96104
97-
This will be `None` when the `"isrc"` feature was not requested
105+
This will be :obj:`None` when the `"isrc"` feature was not requested
98106
or not supported, otherwise this is a :obj:`str <python:str>` object.
99107
"""
100108
return self._get_track_isrc()

discid/util.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
SECTORS_PER_SECOND = 75
2323

2424

25-
def _encode(string: str | bytes):
25+
def _encode(string: str | bytes) -> bytes:
2626
"""Encode (unicode) string to byte string"""
2727
if isinstance(string, str):
2828
return string.encode()
@@ -33,7 +33,7 @@ def _encode(string: str | bytes):
3333
# device names should be ASCII
3434

3535

36-
def _decode(byte_string: bytes | str):
36+
def _decode(byte_string: bytes | str) -> str:
3737
"""Decode byte string to (unicode) string"""
3838
# this test for bytes works on Python 2 and 3
3939
if isinstance(byte_string, bytes):

doc/conf.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,23 @@ def __getattr__(cls, name):
1919
return Mock()
2020

2121

22-
ctypes.cdll.LoadLibrary = Mock()
22+
ctypes.cdll.LoadLibrary = Mock() # type: ignore
2323

2424
# -- General configuration -----------------------------------------------------
2525

2626
needs_sphinx = "1.0"
2727

2828
extensions = [
2929
"sphinx.ext.autodoc",
30+
"sphinx.ext.autosummary",
3031
"sphinx.ext.coverage",
3132
"sphinx.ext.extlinks",
3233
"sphinx.ext.intersphinx",
34+
"sphinx_autodoc_typehints",
3335
]
3436
source_suffix = ".rst"
3537
master_doc = "index"
36-
exclude_patterns = ["_build"]
38+
exclude_patterns = ["_build", ".venv"]
3739

3840
# General information about the project.
3941
project = "python-discid"

pyproject.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ Changelog = "https://github.com/metabrainz/python-discid/blob/master/CHANGES.rst
3333
[dependency-groups]
3434
test = ["pytest"]
3535
docs = [
36-
"Sphinx~=8.1.3",
37-
"sphinx-rtd-theme~=3.0.2",
36+
"Sphinx>=8.1.3",
37+
"sphinx-autodoc-typehints>=3.0.1",
38+
"sphinx-rtd-theme>=3.0.2",
3839
]
3940
dev = [
4041
"pre-commit>=4.5.1",

0 commit comments

Comments
 (0)