TonieToolbox 0.2.2__py3-none-any.whl → 0.3.0__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.
- TonieToolbox/__init__.py +1 -1
- TonieToolbox/__main__.py +407 -7
- TonieToolbox/dependency_manager.py +95 -5
- TonieToolbox/media_tags.py +637 -0
- TonieToolbox/recursive_processor.py +96 -11
- TonieToolbox/teddycloud.py +580 -0
- {tonietoolbox-0.2.2.dist-info → tonietoolbox-0.3.0.dist-info}/METADATA +158 -5
- {tonietoolbox-0.2.2.dist-info → tonietoolbox-0.3.0.dist-info}/RECORD +12 -10
- {tonietoolbox-0.2.2.dist-info → tonietoolbox-0.3.0.dist-info}/WHEEL +1 -1
- {tonietoolbox-0.2.2.dist-info → tonietoolbox-0.3.0.dist-info}/entry_points.txt +0 -0
- {tonietoolbox-0.2.2.dist-info → tonietoolbox-0.3.0.dist-info}/licenses/LICENSE.md +0 -0
- {tonietoolbox-0.2.2.dist-info → tonietoolbox-0.3.0.dist-info}/top_level.txt +0 -0
@@ -204,12 +204,101 @@ def extract_folder_meta(folder_path: str) -> Dict[str, str]:
|
|
204
204
|
return meta
|
205
205
|
|
206
206
|
|
207
|
-
def
|
207
|
+
def get_folder_name_from_metadata(folder_path: str, use_media_tags: bool = False, template: str = None) -> str:
|
208
|
+
"""
|
209
|
+
Generate a suitable output filename for a folder based on folder name
|
210
|
+
and optionally audio file metadata.
|
211
|
+
|
212
|
+
Args:
|
213
|
+
folder_path: Path to folder
|
214
|
+
use_media_tags: Whether to use media tags from audio files if available
|
215
|
+
template: Optional template for formatting output name using media tags
|
216
|
+
|
217
|
+
Returns:
|
218
|
+
String with cleaned output name
|
219
|
+
"""
|
220
|
+
# Start with folder name metadata
|
221
|
+
folder_meta = extract_folder_meta(folder_path)
|
222
|
+
output_name = None
|
223
|
+
|
224
|
+
# Try to get metadata from audio files if requested
|
225
|
+
if use_media_tags:
|
226
|
+
try:
|
227
|
+
# Import here to avoid circular imports
|
228
|
+
from .media_tags import extract_album_info, format_metadata_filename, is_available, normalize_tag_value
|
229
|
+
|
230
|
+
if is_available():
|
231
|
+
logger.debug("Using media tags to generate folder name for: %s", folder_path)
|
232
|
+
|
233
|
+
# Get album metadata from the files
|
234
|
+
album_info = extract_album_info(folder_path)
|
235
|
+
|
236
|
+
if album_info:
|
237
|
+
# Normalize all tag values to handle special characters
|
238
|
+
for key, value in album_info.items():
|
239
|
+
album_info[key] = normalize_tag_value(value)
|
240
|
+
|
241
|
+
# Add folder metadata as fallback values
|
242
|
+
if 'number' in folder_meta and folder_meta['number']:
|
243
|
+
if 'tracknumber' not in album_info or not album_info['tracknumber']:
|
244
|
+
album_info['tracknumber'] = folder_meta['number']
|
245
|
+
|
246
|
+
if 'title' in folder_meta and folder_meta['title']:
|
247
|
+
if 'album' not in album_info or not album_info['album']:
|
248
|
+
album_info['album'] = normalize_tag_value(folder_meta['title'])
|
249
|
+
|
250
|
+
# Use template or default format
|
251
|
+
format_template = template or "{album}"
|
252
|
+
if 'artist' in album_info and album_info['artist']:
|
253
|
+
format_template = format_template + " - {artist}"
|
254
|
+
if 'number' in folder_meta and folder_meta['number']:
|
255
|
+
format_template = "{tracknumber} - " + format_template
|
256
|
+
|
257
|
+
formatted_name = format_metadata_filename(album_info, format_template)
|
258
|
+
|
259
|
+
if formatted_name:
|
260
|
+
logger.debug("Generated name from media tags: %s", formatted_name)
|
261
|
+
output_name = formatted_name
|
262
|
+
except Exception as e:
|
263
|
+
logger.warning("Error using media tags for folder naming: %s", str(e))
|
264
|
+
|
265
|
+
# Fall back to folder name parsing if no media tags or if media tag extraction failed
|
266
|
+
if not output_name:
|
267
|
+
if folder_meta['number'] and folder_meta['title']:
|
268
|
+
# Apply normalization to the title from the folder name
|
269
|
+
try:
|
270
|
+
from .media_tags import normalize_tag_value
|
271
|
+
normalized_title = normalize_tag_value(folder_meta['title'])
|
272
|
+
output_name = f"{folder_meta['number']} - {normalized_title}"
|
273
|
+
except:
|
274
|
+
output_name = f"{folder_meta['number']} - {folder_meta['title']}"
|
275
|
+
else:
|
276
|
+
# Try to normalize the folder name itself
|
277
|
+
folder_name = os.path.basename(folder_path)
|
278
|
+
try:
|
279
|
+
from .media_tags import normalize_tag_value
|
280
|
+
output_name = normalize_tag_value(folder_name)
|
281
|
+
except:
|
282
|
+
output_name = folder_name
|
283
|
+
|
284
|
+
# Clean up the output name (remove invalid filename characters)
|
285
|
+
output_name = re.sub(r'[<>:"/\\|?*]', '_', output_name)
|
286
|
+
output_name = output_name.replace("???", "Fragezeichen")
|
287
|
+
output_name = output_name.replace("!!!", "Ausrufezeichen")
|
288
|
+
|
289
|
+
logger.debug("Final generated output name: %s", output_name)
|
290
|
+
return output_name
|
291
|
+
|
292
|
+
|
293
|
+
def process_recursive_folders(root_path: str, use_media_tags: bool = False,
|
294
|
+
name_template: str = None) -> List[Tuple[str, str, List[str]]]:
|
208
295
|
"""
|
209
296
|
Process folders recursively and prepare data for conversion.
|
210
297
|
|
211
298
|
Args:
|
212
299
|
root_path: Root directory to start processing from
|
300
|
+
use_media_tags: Whether to use media tags from audio files for naming
|
301
|
+
name_template: Optional template for formatting output names using media tags
|
213
302
|
|
214
303
|
Returns:
|
215
304
|
List of tuples: (output_filename, folder_path, list_of_audio_files)
|
@@ -230,17 +319,13 @@ def process_recursive_folders(root_path: str) -> List[Tuple[str, str, List[str]]
|
|
230
319
|
# Use natural sort order to ensure consistent results
|
231
320
|
audio_files = natural_sort(audio_files)
|
232
321
|
|
233
|
-
meta = extract_folder_meta(folder_path)
|
234
|
-
|
235
322
|
if audio_files:
|
236
|
-
#
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
# Clean up the output name (remove invalid filename characters)
|
243
|
-
output_name = re.sub(r'[<>:"/\\|?*]', '_', output_name)
|
323
|
+
# Generate output filename using metadata
|
324
|
+
output_name = get_folder_name_from_metadata(
|
325
|
+
folder_path,
|
326
|
+
use_media_tags=use_media_tags,
|
327
|
+
template=name_template
|
328
|
+
)
|
244
329
|
|
245
330
|
results.append((output_name, folder_path, audio_files))
|
246
331
|
logger.debug("Created processing task: %s -> %s (%d files)",
|