TonieToolbox 0.5.1__py3-none-any.whl → 0.6.0a2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -18,14 +18,14 @@ from .logger import get_logger
18
18
  logger = get_logger('tonie_file')
19
19
 
20
20
 
21
- def toniefile_comment_add(buffer, length, comment_str):
21
+ def toniefile_comment_add(buffer: bytearray, length: int, comment_str: str) -> int:
22
22
  """
23
23
  Add a comment string to an Opus comment packet buffer.
24
24
 
25
25
  Args:
26
- buffer: Bytearray buffer to add comment to
27
- length: Current position in the buffer
28
- comment_str: Comment string to add
26
+ buffer (bytearray): Bytearray buffer to add comment to
27
+ length (int): Current position in the buffer
28
+ comment_str (str): Comment string to add
29
29
 
30
30
  Returns:
31
31
  int: New position in the buffer after adding comment
@@ -44,7 +44,7 @@ def toniefile_comment_add(buffer, length, comment_str):
44
44
  return length
45
45
 
46
46
 
47
- def check_identification_header(page):
47
+ def check_identification_header(page) -> None:
48
48
  """
49
49
  Check if a page contains a valid Opus identification header.
50
50
 
@@ -77,16 +77,16 @@ def check_identification_header(page):
77
77
  logger.debug("Opus identification header is valid")
78
78
 
79
79
 
80
- def prepare_opus_tags(page, custom_tags=False, bitrate=64, vbr=True, opus_binary=None):
80
+ def prepare_opus_tags(page, custom_tags: bool = False, bitrate: int = 64, vbr: bool = True, opus_binary: str = None) -> OggPage:
81
81
  """
82
82
  Prepare standard Opus tags for a Tonie file.
83
83
 
84
84
  Args:
85
85
  page: OggPage to modify
86
- custom_tags: Whether to use custom TonieToolbox tags instead of default ones
87
- bitrate: Actual bitrate used for encoding
88
- vbr: Whether variable bitrate was used
89
- opus_binary: Path to opusenc binary for version detection
86
+ custom_tags (bool): Whether to use custom TonieToolbox tags instead of default ones
87
+ bitrate (int): Actual bitrate used for encoding
88
+ vbr (bool): Whether variable bitrate was used
89
+ opus_binary (str | None): Path to opusenc binary for version detection
90
90
 
91
91
  Returns:
92
92
  OggPage: Modified page with Tonie-compatible Opus tags
@@ -162,19 +162,28 @@ def prepare_opus_tags(page, custom_tags=False, bitrate=64, vbr=True, opus_binary
162
162
  return page
163
163
 
164
164
 
165
- def copy_first_and_second_page(in_file, out_file, timestamp, sha, use_custom_tags=True, bitrate=64, vbr=True, opus_binary=None):
165
+ def copy_first_and_second_page(
166
+ in_file,
167
+ out_file,
168
+ timestamp: int,
169
+ sha,
170
+ use_custom_tags: bool = True,
171
+ bitrate: int = 64,
172
+ vbr: bool = True,
173
+ opus_binary: str = None
174
+ ) -> None:
166
175
  """
167
176
  Copy and modify the first two pages of an Opus file for a Tonie file.
168
177
 
169
178
  Args:
170
179
  in_file: Input file handle
171
180
  out_file: Output file handle
172
- timestamp: Timestamp to use for the Tonie file
181
+ timestamp (int): Timestamp to use for the Tonie file
173
182
  sha: SHA1 hash object to update with written data
174
- use_custom_tags: Whether to use custom TonieToolbox tags
175
- bitrate: Actual bitrate used for encoding
176
- vbr: Whether VBR was used
177
- opus_binary: Path to opusenc binary
183
+ use_custom_tags (bool): Whether to use custom TonieToolbox tags
184
+ bitrate (int): Actual bitrate used for encoding
185
+ vbr (bool): Whether VBR was used
186
+ opus_binary (str | None): Path to opusenc binary
178
187
  """
179
188
  logger.debug("Copying first and second pages with timestamp %d", timestamp)
180
189
  found = OggPage.seek_to_page_header(in_file)
@@ -202,7 +211,7 @@ def copy_first_and_second_page(in_file, out_file, timestamp, sha, use_custom_tag
202
211
  logger.debug("Second page written successfully")
203
212
 
204
213
 
205
- def skip_first_two_pages(in_file):
214
+ def skip_first_two_pages(in_file) -> None:
206
215
  """
207
216
  Skip the first two pages of an Opus file.
208
217
 
@@ -235,7 +244,7 @@ def skip_first_two_pages(in_file):
235
244
  logger.debug("First two pages skipped successfully")
236
245
 
237
246
 
238
- def read_all_remaining_pages(in_file):
247
+ def read_all_remaining_pages(in_file) -> list:
239
248
  """
240
249
  Read all remaining OGG pages from an input file.
241
250
 
@@ -260,19 +269,26 @@ def read_all_remaining_pages(in_file):
260
269
  return remaining_pages
261
270
 
262
271
 
263
- def resize_pages(old_pages, max_page_size, first_page_size, template_page, last_granule=0, start_no=2,
264
- set_last_page_flag=False):
272
+ def resize_pages(
273
+ old_pages: list,
274
+ max_page_size: int,
275
+ first_page_size: int,
276
+ template_page,
277
+ last_granule: int = 0,
278
+ start_no: int = 2,
279
+ set_last_page_flag: bool = False
280
+ ) -> list:
265
281
  """
266
282
  Resize OGG pages to fit Tonie requirements.
267
283
 
268
284
  Args:
269
- old_pages: List of original OggPage objects
270
- max_page_size: Maximum size for pages
271
- first_page_size: Size for the first page
285
+ old_pages (list): List of original OggPage objects
286
+ max_page_size (int): Maximum size for pages
287
+ first_page_size (int): Size for the first page
272
288
  template_page: Template OggPage to use for creating new pages
273
- last_granule: Last granule position
274
- start_no: Starting page number
275
- set_last_page_flag: Whether to set the last page flag
289
+ last_granule (int): Last granule position
290
+ start_no (int): Starting page number
291
+ set_last_page_flag (bool): Whether to set the last page flag
276
292
 
277
293
  Returns:
278
294
  list: List of resized OggPage objects
@@ -326,14 +342,14 @@ def resize_pages(old_pages, max_page_size, first_page_size, template_page, last_
326
342
  return new_pages
327
343
 
328
344
 
329
- def fix_tonie_header(out_file, chapters, timestamp, sha):
345
+ def fix_tonie_header(out_file, chapters: list, timestamp: int, sha) -> None:
330
346
  """
331
347
  Fix the Tonie header in a file.
332
348
 
333
349
  Args:
334
350
  out_file: Output file handle
335
- chapters: List of chapter page numbers
336
- timestamp: Timestamp for the Tonie file
351
+ chapters (list): List of chapter page numbers
352
+ timestamp (int): Timestamp for the Tonie file
337
353
  sha: SHA1 hash object with file content
338
354
  """
339
355
  logger.info("Writing Tonie header with %d chapters and timestamp %d", len(chapters), timestamp)
@@ -362,25 +378,36 @@ def fix_tonie_header(out_file, chapters, timestamp, sha):
362
378
  logger.debug("Tonie header written successfully (size: %d bytes)", len(header))
363
379
 
364
380
 
365
- def create_tonie_file(output_file, input_files, no_tonie_header=False, user_timestamp=None,
366
- bitrate=96, vbr=True, ffmpeg_binary=None, opus_binary=None, keep_temp=False, auto_download=False,
367
- use_custom_tags=True, no_mono_conversion=False):
381
+ def create_tonie_file(
382
+ output_file: str,
383
+ input_files: list[str],
384
+ no_tonie_header: bool = False,
385
+ user_timestamp: str = None,
386
+ bitrate: int = 96,
387
+ vbr: bool = True,
388
+ ffmpeg_binary: str = None,
389
+ opus_binary: str = None,
390
+ keep_temp: bool = False,
391
+ auto_download: bool = False,
392
+ use_custom_tags: bool = True,
393
+ no_mono_conversion: bool = False
394
+ ) -> None:
368
395
  """
369
396
  Create a Tonie file from input files.
370
397
 
371
398
  Args:
372
- output_file: Output file path
373
- input_files: List of input file paths
374
- no_tonie_header: Whether to omit the Tonie header
375
- user_timestamp: Custom timestamp to use
376
- bitrate: Bitrate for encoding in kbps
377
- vbr: Whether to use variable bitrate encoding (True) or constant (False)
378
- ffmpeg_binary: Path to ffmpeg binary
379
- opus_binary: Path to opusenc binary
380
- keep_temp: Whether to keep temporary opus files for testing
381
- auto_download: Whether to automatically download dependencies if not found
382
- use_custom_tags: Whether to use dynamic comment tags generated with toniefile_comment_add
383
- no_mono_conversion: Whether to skip mono conversion during audio processing
399
+ output_file (str): Output file path
400
+ input_files (list[str]): List of input file paths
401
+ no_tonie_header (bool): Whether to omit the Tonie header
402
+ user_timestamp (str | None): Custom timestamp to use
403
+ bitrate (int): Bitrate for encoding in kbps
404
+ vbr (bool): Whether to use variable bitrate encoding (True) or constant (False)
405
+ ffmpeg_binary (str | None): Path to ffmpeg binary
406
+ opus_binary (str | None): Path to opusenc binary
407
+ keep_temp (bool): Whether to keep temporary opus files for testing
408
+ auto_download (bool): Whether to automatically download dependencies if not found
409
+ use_custom_tags (bool): Whether to use dynamic comment tags generated with toniefile_comment_add
410
+ no_mono_conversion (bool): Whether to skip mono conversion during audio processing
384
411
  """
385
412
  from .audio_conversion import get_opus_tempfile
386
413
 
@@ -29,7 +29,7 @@ class ToniesJsonHandlerv1:
29
29
  Initialize the handler.
30
30
 
31
31
  Args:
32
- client: TeddyCloudClient instance to use for API communication
32
+ client (TeddyCloudClient | None): TeddyCloudClient instance to use for API communication
33
33
  """
34
34
  self.client = client
35
35
  self.custom_json = []
@@ -40,7 +40,7 @@ class ToniesJsonHandlerv1:
40
40
  Load tonies.custom.json from the TeddyCloud server.
41
41
 
42
42
  Returns:
43
- True if successful, False otherwise
43
+ bool: True if successful, False otherwise
44
44
  """
45
45
  if self.client is None:
46
46
  logger.error("Cannot load from server: no client provided")
@@ -71,10 +71,10 @@ class ToniesJsonHandlerv1:
71
71
  Load tonies.custom.json from a local file.
72
72
 
73
73
  Args:
74
- file_path: Path to the tonies.custom.json file
74
+ file_path (str): Path to the tonies.custom.json file
75
75
 
76
76
  Returns:
77
- True if successful, False otherwise
77
+ bool: True if successful, False otherwise
78
78
  """
79
79
  try:
80
80
  if os.path.exists(file_path):
@@ -109,10 +109,10 @@ class ToniesJsonHandlerv1:
109
109
  Save tonies.custom.json to a local file.
110
110
 
111
111
  Args:
112
- file_path: Path where to save the tonies.custom.json file
112
+ file_path (str): Path where to save the tonies.custom.json file
113
113
 
114
114
  Returns:
115
- True if successful, False otherwise
115
+ bool: True if successful, False otherwise
116
116
  """
117
117
  if not self.is_loaded:
118
118
  logger.error("Cannot save tonies.custom.json: data not loaded")
@@ -131,10 +131,13 @@ class ToniesJsonHandlerv1:
131
131
  logger.error("Error saving tonies.custom.json to file: %s", e)
132
132
  return False
133
133
 
134
- def renumber_series_entries(self, series: str):
134
+ def renumber_series_entries(self, series: str) -> None:
135
135
  """
136
136
  Re-sort and re-number all entries for a series by year (chronological),
137
137
  with entries without a year coming last.
138
+
139
+ Args:
140
+ series (str): Series name to renumber
138
141
  """
139
142
  # Collect all entries for the series
140
143
  series_entries = [entry for entry in self.custom_json if entry.get('series') == series]
@@ -167,12 +170,12 @@ class ToniesJsonHandlerv1:
167
170
  If an entry with the same series+episodes exists, the new hash will be added to it.
168
171
 
169
172
  Args:
170
- taf_file: Path to the TAF file
171
- input_files: List of input audio files used to create the TAF
172
- artwork_url: URL of the uploaded artwork (if any)
173
+ taf_file (str): Path to the TAF file
174
+ input_files (list[str]): List of input audio files used to create the TAF
175
+ artwork_url (str | None): URL of the uploaded artwork (if any)
173
176
 
174
177
  Returns:
175
- True if successful, False otherwise
178
+ bool: True if successful, False otherwise
176
179
  """
177
180
  logger.trace("Entering add_entry_from_taf() with taf_file=%s, input_files=%s, artwork_url=%s",
178
181
  taf_file, input_files, artwork_url)
@@ -329,12 +332,12 @@ class ToniesJsonHandlerv1:
329
332
  2. For entries without years: assign the next available number after those with years
330
333
 
331
334
  Args:
332
- series: Series name
333
- episodes: Episodes name
334
- year: Release year from metadata, if available
335
+ series (str): Series name
336
+ episodes (str): Episodes name
337
+ year (int | None): Release year from metadata, if available
335
338
 
336
339
  Returns:
337
- Generated entry number as string
340
+ str: Generated entry number as string
338
341
  """
339
342
  logger.trace("Entering _generate_entry_no() with series='%s', episodes='%s', year=%s",
340
343
  series, episodes, year)
@@ -443,10 +446,10 @@ class ToniesJsonHandlerv1:
443
446
  Extract a year (1900-2099) from text.
444
447
 
445
448
  Args:
446
- text: The text to extract the year from
449
+ text (str): The text to extract the year from
447
450
 
448
451
  Returns:
449
- The extracted year as int, or None if no valid year found
452
+ int | None: The extracted year as int, or None if no valid year found
450
453
  """
451
454
  import re
452
455
  year_pattern = re.compile(r'(19\d{2}|20\d{2})')
@@ -467,11 +470,11 @@ class ToniesJsonHandlerv1:
467
470
  Format a number to match the existing entry number format (e.g., with leading zeros).
468
471
 
469
472
  Args:
470
- number: The number to format
471
- existing_entries: List of existing entries with their numbers
473
+ number (int): The number to format
474
+ existing_entries (list[dict]): List of existing entries with their numbers
472
475
 
473
476
  Returns:
474
- Formatted number as string
477
+ str: Formatted number as string
475
478
  """
476
479
  max_digits = 1
477
480
  for entry in existing_entries:
@@ -492,7 +495,7 @@ class ToniesJsonHandlerv1:
492
495
  Generate a unique model number for a new entry.
493
496
 
494
497
  Returns:
495
- Unique model number in the format "model-" followed by sequential number with zero padding
498
+ str: Unique model number in the format "model-" followed by sequential number with zero padding
496
499
  """
497
500
  logger.trace("Entering _generate_model_number()")
498
501
  highest_num = -1
@@ -525,10 +528,10 @@ class ToniesJsonHandlerv1:
525
528
  Determine the category in v1 format.
526
529
 
527
530
  Args:
528
- metadata: Dictionary containing file metadata
531
+ metadata (dict): Dictionary containing file metadata
529
532
 
530
533
  Returns:
531
- Category string in v1 format
534
+ str: Category string in v1 format
532
535
  """
533
536
  if 'genre' in metadata:
534
537
  genre_value = metadata['genre'].lower().strip()
@@ -551,10 +554,10 @@ class ToniesJsonHandlerv1:
551
554
  Find an entry in the custom JSON by TAF hash.
552
555
 
553
556
  Args:
554
- taf_hash: SHA1 hash of the TAF file to find
557
+ taf_hash (str): SHA1 hash of the TAF file to find
555
558
 
556
559
  Returns:
557
- Tuple of (entry, entry_index) if found, or (None, None) if not found
560
+ tuple[dict | None, int | None]: Tuple of (entry, entry_index) if found, or (None, None) if not found
558
561
  """
559
562
  logger.trace("Searching for entry with hash %s", taf_hash)
560
563
 
@@ -575,11 +578,11 @@ class ToniesJsonHandlerv1:
575
578
  Find an entry in the custom JSON by series and episodes.
576
579
 
577
580
  Args:
578
- series: Series name to find
579
- episodes: Episodes name to find
581
+ series (str): Series name to find
582
+ episodes (str): Episodes name to find
580
583
 
581
584
  Returns:
582
- Tuple of (entry, entry_index) if found, or (None, None) if not found
585
+ tuple[dict | None, int | None]: Tuple of (entry, entry_index) if found, or (None, None) if not found
583
586
  """
584
587
  logger.trace("Searching for entry with series='%s', episodes='%s'", series, episodes)
585
588
 
@@ -596,10 +599,10 @@ class ToniesJsonHandlerv1:
596
599
  Extract metadata from audio files to use in the custom JSON entry.
597
600
 
598
601
  Args:
599
- input_files: List of paths to audio files
602
+ input_files (list[str]): List of paths to audio files
600
603
 
601
604
  Returns:
602
- Dictionary containing metadata extracted from files
605
+ dict: Dictionary containing metadata extracted from files
603
606
  """
604
607
  metadata = {}
605
608
  track_descriptions = []
@@ -638,10 +641,10 @@ class ToniesJsonHandlerv1:
638
641
  Convert data from v2 format to v1 format.
639
642
 
640
643
  Args:
641
- v2_data: Data in v2 format
644
+ v2_data (list[dict]): Data in v2 format
642
645
 
643
646
  Returns:
644
- Converted data in v1 format
647
+ list[dict]: Converted data in v1 format
645
648
  """
646
649
  v1_data = []
647
650
 
@@ -687,10 +690,10 @@ class ToniesJsonHandlerv1:
687
690
  Convert category from v2 format to v1 format.
688
691
 
689
692
  Args:
690
- v2_category: Category in v2 format
693
+ v2_category (str): Category in v2 format
691
694
 
692
695
  Returns:
693
- Category in v1 format
696
+ str: Category in v1 format
694
697
  """
695
698
  v2_to_v1_mapping = {
696
699
  "music": "music",
@@ -710,7 +713,7 @@ class ToniesJsonHandlerv2:
710
713
  Initialize the handler.
711
714
 
712
715
  Args:
713
- client: TeddyCloudClient instance to use for API communication
716
+ client (TeddyCloudClient | None): TeddyCloudClient instance to use for API communication
714
717
  """
715
718
  self.client = client
716
719
  self.custom_json = []
@@ -721,7 +724,7 @@ class ToniesJsonHandlerv2:
721
724
  Load tonies.custom.json from the TeddyCloud server.
722
725
 
723
726
  Returns:
724
- True if successful, False otherwise
727
+ bool: True if successful, False otherwise
725
728
  """
726
729
  if self.client is None:
727
730
  logger.error("Cannot load from server: no client provided")
@@ -747,10 +750,10 @@ class ToniesJsonHandlerv2:
747
750
  Load tonies.custom.json from a local file.
748
751
 
749
752
  Args:
750
- file_path: Path to the tonies.custom.json file
753
+ file_path (str): Path to the tonies.custom.json file
751
754
 
752
755
  Returns:
753
- True if successful, False otherwise
756
+ bool: True if successful, False otherwise
754
757
  """
755
758
  try:
756
759
  if os.path.exists(file_path):
@@ -780,10 +783,10 @@ class ToniesJsonHandlerv2:
780
783
  Save tonies.custom.json to a local file.
781
784
 
782
785
  Args:
783
- file_path: Path where to save the tonies.custom.json file
786
+ file_path (str): Path where to save the tonies.custom.json file
784
787
 
785
788
  Returns:
786
- True if successful, False otherwise
789
+ bool: True if successful, False otherwise
787
790
  """
788
791
  if not self.is_loaded:
789
792
  logger.error("Cannot save tonies.custom.json: data not loaded")
@@ -809,12 +812,12 @@ class ToniesJsonHandlerv2:
809
812
  If an entry with the same series+episode exists, the new hash will be added to it.
810
813
 
811
814
  Args:
812
- taf_file: Path to the TAF file
813
- input_files: List of input audio files used to create the TAF
814
- artwork_url: URL of the uploaded artwork (if any)
815
+ taf_file (str): Path to the TAF file
816
+ input_files (list[str]): List of input audio files used to create the TAF
817
+ artwork_url (str | None): URL of the uploaded artwork (if any)
815
818
 
816
819
  Returns:
817
- True if successful, False otherwise
820
+ bool: True if successful, False otherwise
818
821
  """
819
822
  logger.trace("Entering add_entry_from_taf() with taf_file=%s, input_files=%s, artwork_url=%s",
820
823
  taf_file, input_files, artwork_url)
@@ -915,7 +918,7 @@ class ToniesJsonHandlerv2:
915
918
  Generate a unique article ID for a new entry.
916
919
 
917
920
  Returns:
918
- Unique article ID in the format "tt-42" followed by sequential number starting from 0
921
+ str: Unique article ID in the format "tt-42" followed by sequential number starting from 0
919
922
  """
920
923
  logger.trace("Entering _generate_article_id()")
921
924
  highest_num = -1
@@ -948,10 +951,10 @@ class ToniesJsonHandlerv2:
948
951
  Extract metadata from audio files to use in the custom JSON entry.
949
952
 
950
953
  Args:
951
- input_files: List of paths to audio files
954
+ input_files (list[str]): List of paths to audio files
952
955
 
953
956
  Returns:
954
- Dictionary containing metadata extracted from files
957
+ dict: Dictionary containing metadata extracted from files
955
958
  """
956
959
  metadata = {}
957
960
  track_descriptions = []
@@ -1043,10 +1046,10 @@ class ToniesJsonHandlerv2:
1043
1046
  Find an entry in the custom JSON by TAF hash.
1044
1047
 
1045
1048
  Args:
1046
- taf_hash: SHA1 hash of the TAF file to find
1049
+ taf_hash (str): SHA1 hash of the TAF file to find
1047
1050
 
1048
1051
  Returns:
1049
- Tuple of (entry, entry_index, data_index) if found, or (None, None, None) if not found
1052
+ tuple[dict | None, int | None, int | None]: Tuple of (entry, entry_index, data_index) if found, or (None, None, None) if not found
1050
1053
  """
1051
1054
  logger.trace("Searching for entry with hash %s", taf_hash)
1052
1055
 
@@ -1071,11 +1074,11 @@ class ToniesJsonHandlerv2:
1071
1074
  Find an entry in the custom JSON by series and episode.
1072
1075
 
1073
1076
  Args:
1074
- series: Series name to find
1075
- episode: Episode name to find
1077
+ series (str): Series name to find
1078
+ episode (str): Episode name to find
1076
1079
 
1077
1080
  Returns:
1078
- Tuple of (entry, entry_index, data_index) if found, or (None, None, None) if not found
1081
+ tuple[dict | None, int | None, int | None]: Tuple of (entry, entry_index, data_index) if found, or (None, None, None) if not found
1079
1082
  """
1080
1083
  logger.trace("Searching for entry with series='%s', episode='%s'", series, episode)
1081
1084
 
@@ -1096,10 +1099,10 @@ class ToniesJsonHandlerv2:
1096
1099
  Calculate the total runtime in minutes from a list of audio files.
1097
1100
 
1098
1101
  Args:
1099
- input_files: List of paths to audio files
1102
+ input_files (list[str]): List of paths to audio files
1100
1103
 
1101
1104
  Returns:
1102
- Total runtime in minutes (rounded to the nearest minute)
1105
+ int: Total runtime in minutes (rounded to the nearest minute)
1103
1106
  """
1104
1107
  logger.trace("Entering _calculate_runtime() with %d input files", len(input_files))
1105
1108
  total_runtime_seconds = 0
@@ -1166,14 +1169,14 @@ def fetch_and_update_tonies_json_v1(client: TeddyCloudClient, taf_file: Optional
1166
1169
  Fetch tonies.custom.json from server and merge with local file if it exists, then update with new entry in v1 format.
1167
1170
 
1168
1171
  Args:
1169
- client: TeddyCloudClient instance to use for API communication
1170
- taf_file: Path to the TAF file to add
1171
- input_files: List of input audio files used to create the TAF
1172
- artwork_url: URL of the uploaded artwork (if any)
1173
- output_dir: Directory where to save the tonies.custom.json file (defaults to './output')
1172
+ client (TeddyCloudClient): TeddyCloudClient instance to use for API communication
1173
+ taf_file (str | None): Path to the TAF file to add
1174
+ input_files (list[str] | None): List of input audio files used to create the TAF
1175
+ artwork_url (str | None): URL of the uploaded artwork (if any)
1176
+ output_dir (str | None): Directory where to save the tonies.custom.json file (defaults to './output')
1174
1177
 
1175
1178
  Returns:
1176
- True if successful, False otherwise
1179
+ bool: True if successful, False otherwise
1177
1180
  """
1178
1181
  logger.trace("Entering fetch_and_update_tonies_json_v1 with client=%s, taf_file=%s, input_files=%s, artwork_url=%s, output_dir=%s",
1179
1182
  client, taf_file, input_files, artwork_url, output_dir)
@@ -1275,14 +1278,14 @@ def fetch_and_update_tonies_json_v2(client: TeddyCloudClient, taf_file: Optional
1275
1278
  Fetch tonies.custom.json from server and merge with local file if it exists, then update with new entry.
1276
1279
 
1277
1280
  Args:
1278
- client: TeddyCloudClient instance to use for API communication
1279
- taf_file: Path to the TAF file to add
1280
- input_files: List of input audio files used to create the TAF
1281
- artwork_url: URL of the uploaded artwork (if any)
1282
- output_dir: Directory where to save the tonies.custom.json file (defaults to './output')
1281
+ client (TeddyCloudClient): TeddyCloudClient instance to use for API communication
1282
+ taf_file (str | None): Path to the TAF file to add
1283
+ input_files (list[str] | None): List of input audio files used to create the TAF
1284
+ artwork_url (str | None): URL of the uploaded artwork (if any)
1285
+ output_dir (str | None): Directory where to save the tonies.custom.json file (defaults to './output')
1283
1286
 
1284
1287
  Returns:
1285
- True if successful, False otherwise
1288
+ bool: True if successful, False otherwise
1286
1289
  """
1287
1290
  logger.trace("Entering fetch_and_update_tonies_json with client=%s, taf_file=%s, input_files=%s, artwork_url=%s, output_dir=%s",
1288
1291
  client, taf_file, input_files, artwork_url, output_dir)
@@ -18,15 +18,14 @@ CACHE_FILE = os.path.join(CACHE_DIR, "version_cache.json")
18
18
  CACHE_EXPIRY = 86400 # 24 hours in seconds
19
19
 
20
20
 
21
- def get_pypi_version(force_refresh=False):
21
+ def get_pypi_version(force_refresh: bool = False) -> tuple[str, str | None]:
22
22
  """
23
23
  Get the latest version of TonieToolbox from PyPI.
24
24
 
25
25
  Args:
26
- force_refresh: If True, ignore the cache and fetch directly from PyPI
27
-
26
+ force_refresh (bool): If True, ignore the cache and fetch directly from PyPI
28
27
  Returns:
29
- tuple: (latest_version, None) on success, (current_version, error_message) on failure
28
+ tuple[str, str | None]: (latest_version, None) on success, (current_version, error_message) on failure
30
29
  """
31
30
  logger = get_logger("version_handler")
32
31
  logger.debug("Checking for latest version (force_refresh=%s)", force_refresh)
@@ -88,14 +87,13 @@ def get_pypi_version(force_refresh=False):
88
87
  return __version__, f"Unexpected error checking for updates: {str(e)}"
89
88
 
90
89
 
91
- def compare_versions(v1, v2):
90
+ def compare_versions(v1: str, v2: str) -> int:
92
91
  """
93
92
  Compare two version strings according to PEP 440.
94
93
 
95
94
  Args:
96
- v1: First version string
97
- v2: Second version string
98
-
95
+ v1 (str): First version string
96
+ v2 (str): Second version string
99
97
  Returns:
100
98
  int: -1 if v1 < v2, 0 if v1 == v2, 1 if v1 > v2
101
99
  """
@@ -133,16 +131,15 @@ def compare_versions(v1, v2):
133
131
  return 1
134
132
 
135
133
 
136
- def check_for_updates(quiet=False, force_refresh=False):
134
+ def check_for_updates(quiet: bool = False, force_refresh: bool = False) -> tuple[bool, str, str, bool]:
137
135
  """
138
136
  Check if the current version of TonieToolbox is the latest.
139
137
 
140
138
  Args:
141
- quiet: If True, will not log any information messages and skip user confirmation
142
- force_refresh: If True, bypass cache and check PyPI directly
143
-
139
+ quiet (bool): If True, will not log any information messages and skip user confirmation
140
+ force_refresh (bool): If True, bypass cache and check PyPI directly
144
141
  Returns:
145
- tuple: (is_latest, latest_version, message, update_confirmed)
142
+ tuple[bool, str, str, bool]: (is_latest, latest_version, message, update_confirmed)
146
143
  is_latest: boolean indicating if the current version is the latest
147
144
  latest_version: string with the latest version
148
145
  message: string message about the update status or error
@@ -200,7 +197,7 @@ def check_for_updates(quiet=False, force_refresh=False):
200
197
  return is_latest, latest_version, message, update_confirmed
201
198
 
202
199
 
203
- def install_update():
200
+ def install_update() -> bool:
204
201
  """
205
202
  Try to install the update using pip, pip3, or pipx.
206
203
 
@@ -238,7 +235,7 @@ def install_update():
238
235
  return False
239
236
 
240
237
 
241
- def clear_version_cache():
238
+ def clear_version_cache() -> bool:
242
239
  """
243
240
  Clear the version cache file to force a refresh on next check.
244
241
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: TonieToolbox
3
- Version: 0.5.1
3
+ Version: 0.6.0a2
4
4
  Summary: Create files for the Tonie box and interact with TeddyCloud servers
5
5
  Home-page: https://github.com/Quentendo64/TonieToolbox
6
6
  Author: Quentendo64
@@ -33,7 +33,7 @@ Dynamic: requires-python
33
33
 
34
34
  # TonieToolbox 🎵📦
35
35
 
36
- [![Publish to DockerHub](https://github.com/Quentendo64/TonieToolbox/actions/workflows/docker-publish.yml/badge.svg)](https://github.com/Quentendo64/TonieToolbox/actions)
36
+ [![Publish to DockerHub](https://github.com/Quentendo64/TonieToolbox/actions/workflows/publish-to-docker.yml/badge.svg)](https://github.com/Quentendo64/TonieToolbox/actions)
37
37
  [![Publish to PyPI](https://github.com/Quentendo64/TonieToolbox/actions/workflows/publish-to-pypi.yml/badge.svg)](https://github.com/Quentendo64/TonieToolbox/actions)
38
38
 
39
39
  [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
@@ -225,7 +225,7 @@ docker run --rm -v "$(pwd)/input:/tonietoolbox/input" -v "$(pwd)/output:/tonieto
225
225
  docker run --rm -v "%cd%\input:/tonietoolbox/input" -v "%cd%\output:/tonietoolbox/output" quentendo64/tonietoolbox input/my-audio-file.mp3
226
226
  ```
227
227
 
228
- **Or using docker-compose**
228
+ **Or using docker-compose:**
229
229
 
230
230
  ```shell
231
231
  docker-compose run --rm tonietoolbox input/my-audio-file.mp3