1
- # vim: set fileencoding=utf-8 :
2
1
"""
3
2
This module is a wrapper around the MediaInfo library.
4
3
"""
4
+
5
+ from __future__ import annotations
6
+
5
7
import ctypes
6
8
import json
7
9
import os
10
12
import sys
11
13
import warnings
12
14
import xml .etree .ElementTree as ET
13
- from typing import Any , Dict , List , Optional , Tuple , Union
14
-
15
- try :
16
- from importlib import metadata
17
- except ImportError :
18
- import importlib_metadata as metadata # type: ignore
15
+ from importlib import metadata
16
+ from typing import Any , overload
19
17
20
18
try :
21
19
__version__ = metadata .version ("pymediainfo" )
@@ -50,23 +48,25 @@ class Track:
50
48
All available attributes can be obtained by calling :func:`to_data`.
51
49
"""
52
50
53
- def __eq__ (self , other ): # type: ignore
51
+ def __eq__ (self , other : object ) -> bool :
52
+ if not isinstance (other , Track ):
53
+ return False
54
54
return self .__dict__ == other .__dict__
55
55
56
- def __getattribute__ (self , name ): # type: ignore
56
+ def __getattribute__ (self , name : str ) -> Any :
57
57
try :
58
58
return object .__getattribute__ (self , name )
59
59
except AttributeError :
60
60
pass
61
61
return None
62
62
63
- def __getstate__ (self ): # type: ignore
63
+ def __getstate__ (self ) -> dict [ str , Any ]:
64
64
return self .__dict__
65
65
66
- def __setstate__ (self , state ): # type: ignore
66
+ def __setstate__ (self , state : dict [ str , Any ]) -> None :
67
67
self .__dict__ = state
68
68
69
- def __init__ (self , xml_dom_fragment : ET .Element ):
69
+ def __init__ (self , xml_dom_fragment : ET .Element ) -> None :
70
70
self .track_type = xml_dom_fragment .attrib ["type" ]
71
71
repeated_attributes = []
72
72
for elem in xml_dom_fragment :
@@ -104,10 +104,10 @@ def __init__(self, xml_dom_fragment: ET.Element):
104
104
except ValueError :
105
105
pass
106
106
107
- def __repr__ (self ): # type: ignore
107
+ def __repr__ (self ) -> str :
108
108
return "<Track track_id='{}', track_type='{}'>" .format (self .track_id , self .track_type )
109
109
110
- def to_data (self ) -> Dict [str , Any ]:
110
+ def to_data (self ) -> dict [str , Any ]:
111
111
"""
112
112
Returns a dict representation of the track attributes.
113
113
@@ -157,10 +157,12 @@ class MediaInfo:
157
157
<Track track_id='1', track_type='Text'>
158
158
"""
159
159
160
- def __eq__ (self , other ): # type: ignore
160
+ def __eq__ (self , other : object ) -> bool :
161
+ if not isinstance (other , MediaInfo ):
162
+ return False
161
163
return self .tracks == other .tracks
162
164
163
- def __init__ (self , xml : str , encoding_errors : str = "strict" ):
165
+ def __init__ (self , xml : str , encoding_errors : str = "strict" ) -> None :
164
166
xml_dom = ET .fromstring (xml .encode ("utf-8" , encoding_errors ))
165
167
self .tracks = []
166
168
# This is the case for libmediainfo < 18.03
@@ -173,59 +175,59 @@ def __init__(self, xml: str, encoding_errors: str = "strict"):
173
175
for xml_track in xml_dom .iterfind (xpath ):
174
176
self .tracks .append (Track (xml_track ))
175
177
176
- def _tracks (self , track_type : str ) -> List [Track ]:
178
+ def _tracks (self , track_type : str ) -> list [Track ]:
177
179
return [track for track in self .tracks if track .track_type == track_type ]
178
180
179
181
@property
180
- def general_tracks (self ) -> List [Track ]:
182
+ def general_tracks (self ) -> list [Track ]:
181
183
"""
182
184
:return: All :class:`Track`\\ s of type ``General``.
183
185
:rtype: list of :class:`Track`\\ s
184
186
"""
185
187
return self ._tracks ("General" )
186
188
187
189
@property
188
- def video_tracks (self ) -> List [Track ]:
190
+ def video_tracks (self ) -> list [Track ]:
189
191
"""
190
192
:return: All :class:`Track`\\ s of type ``Video``.
191
193
:rtype: list of :class:`Track`\\ s
192
194
"""
193
195
return self ._tracks ("Video" )
194
196
195
197
@property
196
- def audio_tracks (self ) -> List [Track ]:
198
+ def audio_tracks (self ) -> list [Track ]:
197
199
"""
198
200
:return: All :class:`Track`\\ s of type ``Audio``.
199
201
:rtype: list of :class:`Track`\\ s
200
202
"""
201
203
return self ._tracks ("Audio" )
202
204
203
205
@property
204
- def text_tracks (self ) -> List [Track ]:
206
+ def text_tracks (self ) -> list [Track ]:
205
207
"""
206
208
:return: All :class:`Track`\\ s of type ``Text``.
207
209
:rtype: list of :class:`Track`\\ s
208
210
"""
209
211
return self ._tracks ("Text" )
210
212
211
213
@property
212
- def other_tracks (self ) -> List [Track ]:
214
+ def other_tracks (self ) -> list [Track ]:
213
215
"""
214
216
:return: All :class:`Track`\\ s of type ``Other``.
215
217
:rtype: list of :class:`Track`\\ s
216
218
"""
217
219
return self ._tracks ("Other" )
218
220
219
221
@property
220
- def image_tracks (self ) -> List [Track ]:
222
+ def image_tracks (self ) -> list [Track ]:
221
223
"""
222
224
:return: All :class:`Track`\\ s of type ``Image``.
223
225
:rtype: list of :class:`Track`\\ s
224
226
"""
225
227
return self ._tracks ("Image" )
226
228
227
229
@property
228
- def menu_tracks (self ) -> List [Track ]:
230
+ def menu_tracks (self ) -> list [Track ]:
229
231
"""
230
232
:return: All :class:`Track`\\ s of type ``Menu``.
231
233
:rtype: list of :class:`Track`\\ s
@@ -277,8 +279,8 @@ def _define_library_prototypes(cls, lib: Any) -> Any:
277
279
lib .MediaInfo_Close .restype = None
278
280
279
281
@staticmethod
280
- def _get_library_paths (os_is_nt : bool ) -> Tuple [str , ...]:
281
- library_paths : Tuple [str , ...]
282
+ def _get_library_paths (os_is_nt : bool ) -> tuple [str , ...]:
283
+ library_paths : tuple [str , ...]
282
284
if os_is_nt :
283
285
library_paths = ("MediaInfo.dll" ,)
284
286
elif sys .platform == "darwin" :
@@ -298,13 +300,10 @@ def _get_library_paths(os_is_nt: bool) -> Tuple[str, ...]:
298
300
@classmethod
299
301
def _get_library (
300
302
cls ,
301
- library_file : Optional [ str ] = None ,
302
- ) -> Tuple [Any , Any , str , Tuple [int , ...]]:
303
+ library_file : str | None = None ,
304
+ ) -> tuple [Any , Any , str , tuple [int , ...]]:
303
305
os_is_nt = os .name in ("nt" , "dos" , "os2" , "ce" )
304
- if os_is_nt :
305
- lib_type = ctypes .WinDLL # type: ignore
306
- else :
307
- lib_type = ctypes .CDLL
306
+ lib_type = ctypes .WinDLL if os_is_nt else ctypes .CDLL # type: ignore[attr-defined]
308
307
if library_file is None :
309
308
library_paths = cls ._get_library_paths (os_is_nt )
310
309
else :
@@ -334,7 +333,7 @@ def _get_library(
334
333
)
335
334
336
335
@classmethod
337
- def can_parse (cls , library_file : Optional [ str ] = None ) -> bool :
336
+ def can_parse (cls , library_file : str | None = None ) -> bool :
338
337
"""
339
338
Checks whether media files can be analyzed using libmediainfo.
340
339
@@ -350,22 +349,63 @@ def can_parse(cls, library_file: Optional[str] = None) -> bool:
350
349
except Exception : # pylint: disable=broad-except
351
350
return False
352
351
352
+ # The method may be called with output=<str>, in which case it returns a str
353
+ @overload
354
+ @classmethod
355
+ def parse (
356
+ # pylint: disable=too-many-arguments, too-many-locals
357
+ # pylint: disable=too-many-branches, too-many-statements
358
+ cls ,
359
+ filename : Any ,
360
+ * ,
361
+ library_file : str | None = None ,
362
+ cover_data : bool = False ,
363
+ encoding_errors : str = "strict" ,
364
+ parse_speed : float = 0.5 ,
365
+ full : bool = True ,
366
+ legacy_stream_display : bool = False ,
367
+ mediainfo_options : dict [str , str ] | None = None ,
368
+ output : str ,
369
+ buffer_size : int | None = 64 * 1024 ,
370
+ ) -> str : ...
371
+
372
+ # Or it may be called with output=None, in which case it returns a MediaInfo object
373
+ @overload
374
+ @classmethod
375
+ def parse (
376
+ # pylint: disable=too-many-arguments, too-many-locals
377
+ # pylint: disable=too-many-branches, too-many-statements
378
+ cls ,
379
+ filename : Any ,
380
+ * ,
381
+ library_file : str | None = None ,
382
+ cover_data : bool = False ,
383
+ encoding_errors : str = "strict" ,
384
+ parse_speed : float = 0.5 ,
385
+ full : bool = True ,
386
+ legacy_stream_display : bool = False ,
387
+ mediainfo_options : dict [str , str ] | None = None ,
388
+ output : None = None ,
389
+ buffer_size : int | None = 64 * 1024 ,
390
+ ) -> MediaInfo : ...
391
+
353
392
@classmethod
354
393
def parse (
355
- # pylint: disable=too-many-statements
356
- # pylint: disable=too-many-branches, too-many-locals, too-many-arguments
394
+ # pylint: disable=too-many-arguments, too-many-locals
395
+ # pylint: disable=too-many-branches, too-many-statements
357
396
cls ,
358
397
filename : Any ,
359
- library_file : Optional [str ] = None ,
398
+ * ,
399
+ library_file : str | None = None ,
360
400
cover_data : bool = False ,
361
401
encoding_errors : str = "strict" ,
362
402
parse_speed : float = 0.5 ,
363
403
full : bool = True ,
364
404
legacy_stream_display : bool = False ,
365
- mediainfo_options : Optional [ Dict [ str , str ]] = None ,
366
- output : Optional [ str ] = None ,
367
- buffer_size : Optional [ int ] = 64 * 1024 ,
368
- ) -> Union [ str , " MediaInfo" ] :
405
+ mediainfo_options : dict [ str , str ] | None = None ,
406
+ output : str | None = None ,
407
+ buffer_size : int | None = 64 * 1024 ,
408
+ ) -> MediaInfo | str :
369
409
"""
370
410
Analyze a media file using libmediainfo.
371
411
@@ -515,7 +555,7 @@ def parse(
515
555
return cls (info , encoding_errors )
516
556
return info
517
557
518
- def to_data (self ) -> Dict [str , Any ]:
558
+ def to_data (self ) -> dict [str , Any ]:
519
559
"""
520
560
Returns a dict representation of the object's :py:class:`Tracks <Track>`.
521
561
0 commit comments