audiometa-python 0.6.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.
- audiometa/__init__.py +1297 -0
- audiometa/__main__.py +6 -0
- audiometa/_audio_file.py +607 -0
- audiometa/cli.py +476 -0
- audiometa/exceptions.py +167 -0
- audiometa/manager/_MetadataManager.py +768 -0
- audiometa/manager/__init__.py +1 -0
- audiometa/manager/_rating_supporting/_RatingSupportingMetadataManager.py +250 -0
- audiometa/manager/_rating_supporting/__init__.py +1 -0
- audiometa/manager/_rating_supporting/id3v2/_Id3v2Manager.py +1032 -0
- audiometa/manager/_rating_supporting/id3v2/__init__.py +25 -0
- audiometa/manager/_rating_supporting/id3v2/_id3v2_constants.py +11 -0
- audiometa/manager/_rating_supporting/riff/_RiffManager.py +1002 -0
- audiometa/manager/_rating_supporting/riff/__init__.py +25 -0
- audiometa/manager/_rating_supporting/riff/_riff_constants.py +17 -0
- audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +542 -0
- audiometa/manager/_rating_supporting/vorbis/__init__.py +17 -0
- audiometa/manager/_rating_supporting/vorbis/_vorbis_constants.py +6 -0
- audiometa/manager/id3v1/_Id3v1Manager.py +512 -0
- audiometa/manager/id3v1/__init__.py +1 -0
- audiometa/manager/id3v1/_constants.py +8 -0
- audiometa/manager/id3v1/id3v1_raw_metadata.py +242 -0
- audiometa/manager/id3v1/id3v1_raw_metadata_key.py +13 -0
- audiometa/test/__init__.py +1 -0
- audiometa/test/assets/create_test_files.py +72 -0
- audiometa/test/helpers/__init__.py +51 -0
- audiometa/test/helpers/common/__init__.py +6 -0
- audiometa/test/helpers/common/audio_file_creator.py +68 -0
- audiometa/test/helpers/common/external_tool_runner.py +74 -0
- audiometa/test/helpers/id3v1/__init__.py +8 -0
- audiometa/test/helpers/id3v1/id3v1_header_verifier.py +18 -0
- audiometa/test/helpers/id3v1/id3v1_metadata_deleter.py +37 -0
- audiometa/test/helpers/id3v1/id3v1_metadata_getter.py +61 -0
- audiometa/test/helpers/id3v1/id3v1_metadata_setter.py +82 -0
- audiometa/test/helpers/id3v2/__init__.py +28 -0
- audiometa/test/helpers/id3v2/id3v2_frame_manual_creator.py +349 -0
- audiometa/test/helpers/id3v2/id3v2_header_verifier.py +38 -0
- audiometa/test/helpers/id3v2/id3v2_metadata_deleter.py +56 -0
- audiometa/test/helpers/id3v2/id3v2_metadata_getter.py +189 -0
- audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +506 -0
- audiometa/test/helpers/riff/__init__.py +8 -0
- audiometa/test/helpers/riff/riff_header_verifier.py +85 -0
- audiometa/test/helpers/riff/riff_manual_metadata_creator.py +298 -0
- audiometa/test/helpers/riff/riff_metadata_deleter.py +56 -0
- audiometa/test/helpers/riff/riff_metadata_getter.py +219 -0
- audiometa/test/helpers/riff/riff_metadata_setter.py +374 -0
- audiometa/test/helpers/scripts/__init__.py +0 -0
- audiometa/test/helpers/technical_info_inspector.py +115 -0
- audiometa/test/helpers/temp_file_with_metadata.py +82 -0
- audiometa/test/helpers/vorbis/__init__.py +8 -0
- audiometa/test/helpers/vorbis/vorbis_header_verifier.py +31 -0
- audiometa/test/helpers/vorbis/vorbis_metadata_deleter.py +49 -0
- audiometa/test/helpers/vorbis/vorbis_metadata_getter.py +67 -0
- audiometa/test/helpers/vorbis/vorbis_metadata_setter.py +221 -0
- audiometa/test/tests/__init__.py +0 -0
- audiometa/test/tests/conftest.py +276 -0
- audiometa/test/tests/e2e/__init__.py +0 -0
- audiometa/test/tests/e2e/cli/__init__.py +0 -0
- audiometa/test/tests/e2e/cli/error_handling/__init__.py +1 -0
- audiometa/test/tests/e2e/cli/error_handling/test_command_structure_errors.py +77 -0
- audiometa/test/tests/e2e/cli/error_handling/test_file_access_errors.py +130 -0
- audiometa/test/tests/e2e/cli/error_handling/test_format_output_errors.py +118 -0
- audiometa/test/tests/e2e/cli/error_handling/test_input_validation_errors.py +172 -0
- audiometa/test/tests/e2e/cli/error_handling/test_missing_fields_validation.py +49 -0
- audiometa/test/tests/e2e/cli/error_handling/test_multiple_files_errors.py +160 -0
- audiometa/test/tests/e2e/cli/error_handling/test_rating_validation.py +90 -0
- audiometa/test/tests/e2e/cli/error_handling/test_year_validation.py +51 -0
- audiometa/test/tests/e2e/cli/read/__init__.py +0 -0
- audiometa/test/tests/e2e/cli/read/test_basic.py +58 -0
- audiometa/test/tests/e2e/cli/read/test_comprehensive.py +240 -0
- audiometa/test/tests/e2e/cli/read/test_formats.py +55 -0
- audiometa/test/tests/e2e/cli/read/test_metadata_content.py +164 -0
- audiometa/test/tests/e2e/cli/read/test_multiple_files.py +149 -0
- audiometa/test/tests/e2e/cli/read/test_options.py +88 -0
- audiometa/test/tests/e2e/cli/read/test_unified.py +84 -0
- audiometa/test/tests/e2e/cli/test_delete.py +20 -0
- audiometa/test/tests/e2e/cli/test_formatting.py +31 -0
- audiometa/test/tests/e2e/cli/test_help.py +41 -0
- audiometa/test/tests/e2e/cli/write/__init__.py +0 -0
- audiometa/test/tests/e2e/cli/write/test_basic.py +51 -0
- audiometa/test/tests/e2e/cli/write/test_comprehensive.py +210 -0
- audiometa/test/tests/e2e/cli/write/test_force_format.py +336 -0
- audiometa/test/tests/e2e/cli/write/test_integer_fields.py +145 -0
- audiometa/test/tests/e2e/cli/write/test_list_fields.py +107 -0
- audiometa/test/tests/e2e/cli/write/test_rating.py +74 -0
- audiometa/test/tests/e2e/cli/write/test_string_fields.py +54 -0
- audiometa/test/tests/e2e/cli/write/test_validation.py +85 -0
- audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
- audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +166 -0
- audiometa/test/tests/e2e/workflows/__init__.py +0 -0
- audiometa/test/tests/e2e/workflows/test_core_workflows.py +166 -0
- audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +318 -0
- audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +165 -0
- audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +129 -0
- audiometa/test/tests/e2e/workflows/test_rating_workflows.py +124 -0
- audiometa/test/tests/integration/__init__.py +0 -0
- audiometa/test/tests/integration/audio_format/__init__.py +0 -0
- audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
- audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +108 -0
- audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +61 -0
- audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +65 -0
- audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +69 -0
- audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
- audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +79 -0
- audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +61 -0
- audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +67 -0
- audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +60 -0
- audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
- audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +87 -0
- audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +62 -0
- audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +57 -0
- audiometa/test/tests/integration/audio_format/wav/test_wav_with_id3v2_tags.py +83 -0
- audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +62 -0
- audiometa/test/tests/integration/conftest.py +29 -0
- audiometa/test/tests/integration/delete_all_metadata/__init__.py +1 -0
- audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +102 -0
- audiometa/test/tests/integration/delete_all_metadata/test_audio_format_header_deletion.py +77 -0
- audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +47 -0
- audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +24 -0
- audiometa/test/tests/integration/encoding/__init__.py +1 -0
- audiometa/test/tests/integration/encoding/test_encoding.py +88 -0
- audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +223 -0
- audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
- audiometa/test/tests/integration/get_full_metadata/test_audio_formats.py +122 -0
- audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +250 -0
- audiometa/test/tests/integration/get_full_metadata/test_consistency.py +67 -0
- audiometa/test/tests/integration/get_full_metadata/test_edge_cases.py +123 -0
- audiometa/test/tests/integration/get_full_metadata/test_error_handling.py +40 -0
- audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +43 -0
- audiometa/test/tests/integration/get_full_metadata/test_options.py +207 -0
- audiometa/test/tests/integration/get_full_metadata/test_performance.py +95 -0
- audiometa/test/tests/integration/get_full_metadata/test_riff_bext.py +128 -0
- audiometa/test/tests/integration/get_full_metadata/test_structure.py +161 -0
- audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/album/test_deleting.py +73 -0
- audiometa/test/tests/integration/metadata_field/album/test_reading.py +36 -0
- audiometa/test/tests/integration/metadata_field/album/test_writing.py +50 -0
- audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +83 -0
- audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +38 -0
- audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +52 -0
- audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +68 -0
- audiometa/test/tests/integration/metadata_field/artists/test_reading.py +36 -0
- audiometa/test/tests/integration/metadata_field/artists/test_writing.py +46 -0
- audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +75 -0
- audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +32 -0
- audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +56 -0
- audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +68 -0
- audiometa/test/tests/integration/metadata_field/comment/test_reading.py +36 -0
- audiometa/test/tests/integration/metadata_field/comment/test_writing.py +49 -0
- audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +75 -0
- audiometa/test/tests/integration/metadata_field/composer/test_reading.py +34 -0
- audiometa/test/tests/integration/metadata_field/composer/test_writing.py +41 -0
- audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +81 -0
- audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +35 -0
- audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +41 -0
- audiometa/test/tests/integration/metadata_field/disc_number/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/disc_number/test_deleting.py +97 -0
- audiometa/test/tests/integration/metadata_field/disc_number/test_reading.py +92 -0
- audiometa/test/tests/integration/metadata_field/disc_number/test_writing.py +153 -0
- audiometa/test/tests/integration/metadata_field/field_not_supported/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +56 -0
- audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +54 -0
- audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +61 -0
- audiometa/test/tests/integration/metadata_field/genre/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/genre/reading/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v1_reading.py +65 -0
- audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v2_reading.py +25 -0
- audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_riff_reading.py +58 -0
- audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_vorbis_reading.py +61 -0
- audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +191 -0
- audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +62 -0
- audiometa/test/tests/integration/metadata_field/genre/test_writing.py +64 -0
- audiometa/test/tests/integration/metadata_field/isrc/__init__.py +1 -0
- audiometa/test/tests/integration/metadata_field/isrc/test_deleting.py +31 -0
- audiometa/test/tests/integration/metadata_field/isrc/test_reading.py +35 -0
- audiometa/test/tests/integration/metadata_field/isrc/test_writing.py +165 -0
- audiometa/test/tests/integration/metadata_field/language/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/language/test_deleting.py +75 -0
- audiometa/test/tests/integration/metadata_field/language/test_reading.py +39 -0
- audiometa/test/tests/integration/metadata_field/language/test_writing.py +43 -0
- audiometa/test/tests/integration/metadata_field/lyrics/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +129 -0
- audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +57 -0
- audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +59 -0
- audiometa/test/tests/integration/metadata_field/publisher/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +88 -0
- audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +32 -0
- audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +47 -0
- audiometa/test/tests/integration/metadata_field/rating/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/rating/reading/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/rating/reading/test_base_100_proportional.py +81 -0
- audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_non_proportional.py +33 -0
- audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_proportional.py +58 -0
- audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +117 -0
- audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +137 -0
- audiometa/test/tests/integration/metadata_field/rating/writing/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_id3v2.py +77 -0
- audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_riff.py +55 -0
- audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_vorbis.py +57 -0
- audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +192 -0
- audiometa/test/tests/integration/metadata_field/release_date/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +74 -0
- audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +82 -0
- audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +59 -0
- audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +49 -0
- audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +135 -0
- audiometa/test/tests/integration/metadata_field/title/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/title/test_deleting.py +73 -0
- audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +47 -0
- audiometa/test/tests/integration/metadata_field/title/test_reading.py +36 -0
- audiometa/test/tests/integration/metadata_field/title/test_writing.py +64 -0
- audiometa/test/tests/integration/metadata_field/track_number/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/track_number/reading/__init__.py +0 -0
- audiometa/test/tests/integration/metadata_field/track_number/reading/test_edge_cases.py +43 -0
- audiometa/test/tests/integration/metadata_field/track_number/reading/test_metadata_format.py +32 -0
- audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +59 -0
- audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +73 -0
- audiometa/test/tests/integration/multiple_values/__init__.py +1 -0
- audiometa/test/tests/integration/multiple_values/reading/__init__.py +1 -0
- audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +1 -0
- audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +23 -0
- audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_3.py +92 -0
- audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_4.py +216 -0
- audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +84 -0
- audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +169 -0
- audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +209 -0
- audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +198 -0
- audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +24 -0
- audiometa/test/tests/integration/multiple_values/writing/__init__.py +1 -0
- audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +1 -0
- audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +62 -0
- audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_3.py +36 -0
- audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_4.py +34 -0
- audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +32 -0
- audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +54 -0
- audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +42 -0
- audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +98 -0
- audiometa/test/tests/integration/reading/__init__.py +1 -0
- audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +80 -0
- audiometa/test/tests/integration/reading/test_reading_error_handling.py +36 -0
- audiometa/test/tests/integration/real_audio_files/__init__.py +0 -0
- audiometa/test/tests/integration/real_audio_files/test_reading.py +146 -0
- audiometa/test/tests/integration/real_audio_files/test_writing.py +198 -0
- audiometa/test/tests/integration/technical_info/__init__.py +0 -0
- audiometa/test/tests/integration/technical_info/flac_md5/__init__.py +0 -0
- audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +103 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/__init__.py +0 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_audio_data_corruption.py +21 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_flipped_md5.py +29 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_non_flac_error.py +13 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_partial_md5.py +29 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_random_md5.py +29 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_unset_md5.py +56 -0
- audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +21 -0
- audiometa/test/tests/integration/technical_info/test_bitrate.py +79 -0
- audiometa/test/tests/integration/technical_info/test_channels.py +38 -0
- audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +38 -0
- audiometa/test/tests/integration/technical_info/test_sample_rate.py +40 -0
- audiometa/test/tests/integration/test_audio_file.py +35 -0
- audiometa/test/tests/integration/test_audio_format_readable_after_update_all_metadata_formats.py +95 -0
- audiometa/test/tests/integration/writing/__init__.py +0 -0
- audiometa/test/tests/integration/writing/test_error_handling.py +44 -0
- audiometa/test/tests/integration/writing/test_forced_format.py +224 -0
- audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +223 -0
- audiometa/test/tests/integration/writing/test_partial_update.py +36 -0
- audiometa/test/tests/integration/writing/writing_strategies/__init__.py +0 -0
- audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +79 -0
- audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +76 -0
- audiometa/test/tests/integration/writing/writing_strategies/test_sync_strategy.py +215 -0
- audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/__init__.py +0 -0
- audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_fail_behavior.py +42 -0
- audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_no_writing_on_failure.py +93 -0
- audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_strategy_specific.py +99 -0
- audiometa/test/tests/unit/__init__.py +0 -0
- audiometa/test/tests/unit/audio_file/__init__.py +0 -0
- audiometa/test/tests/unit/audio_file/technical_info/__init__.py +0 -0
- audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +26 -0
- audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +31 -0
- audiometa/test/tests/unit/audio_file/technical_info/test_duration_in_sec.py +38 -0
- audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +190 -0
- audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +51 -0
- audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +28 -0
- audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +31 -0
- audiometa/test/tests/unit/audio_file/test_context_manager.py +30 -0
- audiometa/test/tests/unit/audio_file/test_file_validation.py +40 -0
- audiometa/test/tests/unit/audio_file/test_is_audio_file.py +49 -0
- audiometa/test/tests/unit/audio_file/test_operations.py +20 -0
- audiometa/test/tests/unit/audio_file/test_path_handling.py +23 -0
- audiometa/test/tests/unit/cli/__init__.py +0 -0
- audiometa/test/tests/unit/cli/test_expand_file_patterns.py +234 -0
- audiometa/test/tests/unit/metadata_managers/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/conftest.py +142 -0
- audiometa/test/tests/unit/metadata_managers/header_info/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +49 -0
- audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +66 -0
- audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +343 -0
- audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +53 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/test_smart_parsing.py +186 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_separator_selection.py +142 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_value_filtering.py +76 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_normalization.py +152 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_profiles_values.py +23 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/test_rating_validation.py +77 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_configuration_error.py +43 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_validation.py +151 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_writing_profiles.py +61 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/test_date_format_validation.py +135 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/test_disc_number_validation.py +75 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/test_isrc_format_validation.py +121 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/test_isrc_type_validation.py +30 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/test_track_number_validation.py +46 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/test_type_validation_exception.py +22 -0
- audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +83 -0
- audiometa/test/tests/unit/metadata_managers/test_metadata_format_managers_write_and_read.py +74 -0
- audiometa/test/tests/unit/metadata_managers/test_riff_configuration_error.py +26 -0
- audiometa/utils/__init__.py +1 -0
- audiometa/utils/id3v1_genre_code_map.py +205 -0
- audiometa/utils/metadata_format.py +31 -0
- audiometa/utils/metadata_writing_strategy.py +16 -0
- audiometa/utils/mutagen_exception_handler.py +24 -0
- audiometa/utils/os_dependencies_checker/__init__.py +24 -0
- audiometa/utils/os_dependencies_checker/base.py +62 -0
- audiometa/utils/os_dependencies_checker/config.py +77 -0
- audiometa/utils/os_dependencies_checker/macos.py +236 -0
- audiometa/utils/os_dependencies_checker/ubuntu.py +95 -0
- audiometa/utils/os_dependencies_checker/windows.py +227 -0
- audiometa/utils/rating_profiles.py +110 -0
- audiometa/utils/tool_path_resolver.py +135 -0
- audiometa/utils/types.py +82 -0
- audiometa/utils/unified_metadata_key.py +87 -0
- audiometa_python-0.6.0.dist-info/METADATA +1593 -0
- audiometa_python-0.6.0.dist-info/RECORD +352 -0
- audiometa_python-0.6.0.dist-info/WHEEL +5 -0
- audiometa_python-0.6.0.dist-info/entry_points.txt +2 -0
- audiometa_python-0.6.0.dist-info/licenses/LICENSE +202 -0
- audiometa_python-0.6.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,336 @@
|
|
|
1
|
+
import platform
|
|
2
|
+
import subprocess
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from audiometa import get_unified_metadata
|
|
8
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
9
|
+
from audiometa.utils.metadata_format import MetadataFormat
|
|
10
|
+
from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.e2e
|
|
14
|
+
class TestCLIWriteForceFormat:
|
|
15
|
+
def test_cli_write_force_format_id3v2_mp3(self):
|
|
16
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
17
|
+
result = subprocess.run(
|
|
18
|
+
[
|
|
19
|
+
sys.executable,
|
|
20
|
+
"-m",
|
|
21
|
+
"audiometa",
|
|
22
|
+
"write",
|
|
23
|
+
str(test_file),
|
|
24
|
+
"--title",
|
|
25
|
+
"CLI Force ID3v2 Title",
|
|
26
|
+
"--force-format",
|
|
27
|
+
"id3v2",
|
|
28
|
+
],
|
|
29
|
+
capture_output=True,
|
|
30
|
+
text=True,
|
|
31
|
+
check=False,
|
|
32
|
+
)
|
|
33
|
+
assert result.returncode == 0
|
|
34
|
+
assert "Updated metadata" in result.stdout
|
|
35
|
+
|
|
36
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
|
|
37
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "CLI Force ID3v2 Title"
|
|
38
|
+
|
|
39
|
+
def test_cli_write_force_format_id3v1_mp3(self):
|
|
40
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
41
|
+
result = subprocess.run(
|
|
42
|
+
[
|
|
43
|
+
sys.executable,
|
|
44
|
+
"-m",
|
|
45
|
+
"audiometa",
|
|
46
|
+
"write",
|
|
47
|
+
str(test_file),
|
|
48
|
+
"--title",
|
|
49
|
+
"CLI Force ID3v1 Title",
|
|
50
|
+
"--force-format",
|
|
51
|
+
"id3v1",
|
|
52
|
+
],
|
|
53
|
+
capture_output=True,
|
|
54
|
+
text=True,
|
|
55
|
+
check=False,
|
|
56
|
+
)
|
|
57
|
+
assert result.returncode == 0
|
|
58
|
+
assert "Updated metadata" in result.stdout
|
|
59
|
+
|
|
60
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
|
|
61
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "CLI Force ID3v1 Title"
|
|
62
|
+
|
|
63
|
+
def test_cli_write_force_format_vorbis_flac(self):
|
|
64
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
65
|
+
result = subprocess.run(
|
|
66
|
+
[
|
|
67
|
+
sys.executable,
|
|
68
|
+
"-m",
|
|
69
|
+
"audiometa",
|
|
70
|
+
"write",
|
|
71
|
+
str(test_file),
|
|
72
|
+
"--title",
|
|
73
|
+
"CLI Force Vorbis Title",
|
|
74
|
+
"--force-format",
|
|
75
|
+
"vorbis",
|
|
76
|
+
],
|
|
77
|
+
capture_output=True,
|
|
78
|
+
text=True,
|
|
79
|
+
check=False,
|
|
80
|
+
)
|
|
81
|
+
assert result.returncode == 0
|
|
82
|
+
assert "Updated metadata" in result.stdout
|
|
83
|
+
|
|
84
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
|
|
85
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "CLI Force Vorbis Title"
|
|
86
|
+
|
|
87
|
+
def test_cli_write_force_format_riff_wav(self):
|
|
88
|
+
with temp_file_with_metadata({}, "wav") as test_file:
|
|
89
|
+
result = subprocess.run(
|
|
90
|
+
[
|
|
91
|
+
sys.executable,
|
|
92
|
+
"-m",
|
|
93
|
+
"audiometa",
|
|
94
|
+
"write",
|
|
95
|
+
str(test_file),
|
|
96
|
+
"--title",
|
|
97
|
+
"CLI Force RIFF Title",
|
|
98
|
+
"--force-format",
|
|
99
|
+
"riff",
|
|
100
|
+
],
|
|
101
|
+
capture_output=True,
|
|
102
|
+
text=True,
|
|
103
|
+
check=False,
|
|
104
|
+
)
|
|
105
|
+
assert result.returncode == 0
|
|
106
|
+
assert "Updated metadata" in result.stdout
|
|
107
|
+
|
|
108
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.RIFF)
|
|
109
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "CLI Force RIFF Title"
|
|
110
|
+
|
|
111
|
+
def test_cli_write_force_format_unsupported_format_mp3(self):
|
|
112
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
113
|
+
result = subprocess.run(
|
|
114
|
+
[
|
|
115
|
+
sys.executable,
|
|
116
|
+
"-m",
|
|
117
|
+
"audiometa",
|
|
118
|
+
"write",
|
|
119
|
+
str(test_file),
|
|
120
|
+
"--title",
|
|
121
|
+
"Test Title",
|
|
122
|
+
"--force-format",
|
|
123
|
+
"vorbis",
|
|
124
|
+
],
|
|
125
|
+
capture_output=True,
|
|
126
|
+
text=True,
|
|
127
|
+
check=False,
|
|
128
|
+
)
|
|
129
|
+
assert result.returncode != 0
|
|
130
|
+
stderr_output = result.stderr.lower()
|
|
131
|
+
assert "not supported" in stderr_output or "error" in stderr_output
|
|
132
|
+
|
|
133
|
+
def test_cli_write_force_format_writes_only_to_specified_format(self):
|
|
134
|
+
with temp_file_with_metadata({"title": "Original RIFF Title"}, "wav") as test_file:
|
|
135
|
+
result = subprocess.run(
|
|
136
|
+
[
|
|
137
|
+
sys.executable,
|
|
138
|
+
"-m",
|
|
139
|
+
"audiometa",
|
|
140
|
+
"write",
|
|
141
|
+
str(test_file),
|
|
142
|
+
"--title",
|
|
143
|
+
"New ID3v2 Title",
|
|
144
|
+
"--force-format",
|
|
145
|
+
"id3v2",
|
|
146
|
+
],
|
|
147
|
+
capture_output=True,
|
|
148
|
+
text=True,
|
|
149
|
+
check=False,
|
|
150
|
+
)
|
|
151
|
+
assert result.returncode == 0
|
|
152
|
+
|
|
153
|
+
riff_metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.RIFF)
|
|
154
|
+
id3v2_metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
|
|
155
|
+
|
|
156
|
+
assert riff_metadata.get(UnifiedMetadataKey.TITLE) == "Original RIFF Title"
|
|
157
|
+
assert id3v2_metadata.get(UnifiedMetadataKey.TITLE) == "New ID3v2 Title"
|
|
158
|
+
|
|
159
|
+
@pytest.mark.skipif(platform.system() == "Windows", reason="id3v2 tool requires WSL on Windows")
|
|
160
|
+
def test_cli_write_force_format_id3v2_flac(self):
|
|
161
|
+
"""Test forcing ID3v2 format on FLAC files.
|
|
162
|
+
|
|
163
|
+
Note: This test is skipped on Windows because writing ID3v2 tags to FLAC files
|
|
164
|
+
requires the external 'id3v2' tool (mutagen corrupts FLAC structure). On Windows,
|
|
165
|
+
the 'id3v2' tool is not available as a native binary and requires WSL (Windows
|
|
166
|
+
Subsystem for Linux), which is not set up in Windows CI environments.
|
|
167
|
+
"""
|
|
168
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
169
|
+
result = subprocess.run(
|
|
170
|
+
[
|
|
171
|
+
sys.executable,
|
|
172
|
+
"-m",
|
|
173
|
+
"audiometa",
|
|
174
|
+
"write",
|
|
175
|
+
str(test_file),
|
|
176
|
+
"--title",
|
|
177
|
+
"CLI Force ID3v2 FLAC Title",
|
|
178
|
+
"--force-format",
|
|
179
|
+
"id3v2",
|
|
180
|
+
],
|
|
181
|
+
capture_output=True,
|
|
182
|
+
text=True,
|
|
183
|
+
check=False,
|
|
184
|
+
)
|
|
185
|
+
assert result.returncode == 0
|
|
186
|
+
assert "Updated metadata" in result.stdout
|
|
187
|
+
|
|
188
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
|
|
189
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "CLI Force ID3v2 FLAC Title"
|
|
190
|
+
|
|
191
|
+
def test_cli_write_force_format_id3v1_flac(self):
|
|
192
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
193
|
+
result = subprocess.run(
|
|
194
|
+
[
|
|
195
|
+
sys.executable,
|
|
196
|
+
"-m",
|
|
197
|
+
"audiometa",
|
|
198
|
+
"write",
|
|
199
|
+
str(test_file),
|
|
200
|
+
"--title",
|
|
201
|
+
"CLI Force ID3v1 FLAC Title",
|
|
202
|
+
"--force-format",
|
|
203
|
+
"id3v1",
|
|
204
|
+
],
|
|
205
|
+
capture_output=True,
|
|
206
|
+
text=True,
|
|
207
|
+
check=False,
|
|
208
|
+
)
|
|
209
|
+
assert result.returncode == 0
|
|
210
|
+
assert "Updated metadata" in result.stdout
|
|
211
|
+
|
|
212
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
|
|
213
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "CLI Force ID3v1 FLAC Title"
|
|
214
|
+
|
|
215
|
+
def test_cli_write_force_format_id3v1_wav(self):
|
|
216
|
+
with temp_file_with_metadata({}, "wav") as test_file:
|
|
217
|
+
result = subprocess.run(
|
|
218
|
+
[
|
|
219
|
+
sys.executable,
|
|
220
|
+
"-m",
|
|
221
|
+
"audiometa",
|
|
222
|
+
"write",
|
|
223
|
+
str(test_file),
|
|
224
|
+
"--title",
|
|
225
|
+
"CLI Force ID3v1 WAV Title",
|
|
226
|
+
"--force-format",
|
|
227
|
+
"id3v1",
|
|
228
|
+
],
|
|
229
|
+
capture_output=True,
|
|
230
|
+
text=True,
|
|
231
|
+
check=False,
|
|
232
|
+
)
|
|
233
|
+
assert result.returncode == 0
|
|
234
|
+
assert "Updated metadata" in result.stdout
|
|
235
|
+
|
|
236
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
|
|
237
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "CLI Force ID3v1 WAV Title"
|
|
238
|
+
|
|
239
|
+
def test_cli_write_force_format_with_multiple_fields(self):
|
|
240
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
241
|
+
result = subprocess.run(
|
|
242
|
+
[
|
|
243
|
+
sys.executable,
|
|
244
|
+
"-m",
|
|
245
|
+
"audiometa",
|
|
246
|
+
"write",
|
|
247
|
+
str(test_file),
|
|
248
|
+
"--title",
|
|
249
|
+
"Multi Field Title",
|
|
250
|
+
"--artist",
|
|
251
|
+
"Multi Field Artist",
|
|
252
|
+
"--album",
|
|
253
|
+
"Multi Field Album",
|
|
254
|
+
"--force-format",
|
|
255
|
+
"id3v2",
|
|
256
|
+
],
|
|
257
|
+
capture_output=True,
|
|
258
|
+
text=True,
|
|
259
|
+
check=False,
|
|
260
|
+
)
|
|
261
|
+
assert result.returncode == 0
|
|
262
|
+
|
|
263
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
|
|
264
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "Multi Field Title"
|
|
265
|
+
assert metadata.get(UnifiedMetadataKey.ARTISTS) == ["Multi Field Artist"]
|
|
266
|
+
assert metadata.get(UnifiedMetadataKey.ALBUM) == "Multi Field Album"
|
|
267
|
+
|
|
268
|
+
def test_cli_write_force_format_with_rating(self):
|
|
269
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
270
|
+
result = subprocess.run(
|
|
271
|
+
[
|
|
272
|
+
sys.executable,
|
|
273
|
+
"-m",
|
|
274
|
+
"audiometa",
|
|
275
|
+
"write",
|
|
276
|
+
str(test_file),
|
|
277
|
+
"--title",
|
|
278
|
+
"Rating Test Title",
|
|
279
|
+
"--rating",
|
|
280
|
+
"85",
|
|
281
|
+
"--force-format",
|
|
282
|
+
"id3v2",
|
|
283
|
+
],
|
|
284
|
+
capture_output=True,
|
|
285
|
+
text=True,
|
|
286
|
+
check=False,
|
|
287
|
+
)
|
|
288
|
+
assert result.returncode == 0
|
|
289
|
+
|
|
290
|
+
metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
|
|
291
|
+
assert metadata.get(UnifiedMetadataKey.TITLE) == "Rating Test Title"
|
|
292
|
+
assert metadata.get(UnifiedMetadataKey.RATING) is not None
|
|
293
|
+
|
|
294
|
+
def test_cli_write_force_format_unsupported_flac_riff(self):
|
|
295
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
296
|
+
result = subprocess.run(
|
|
297
|
+
[
|
|
298
|
+
sys.executable,
|
|
299
|
+
"-m",
|
|
300
|
+
"audiometa",
|
|
301
|
+
"write",
|
|
302
|
+
str(test_file),
|
|
303
|
+
"--title",
|
|
304
|
+
"Test Title",
|
|
305
|
+
"--force-format",
|
|
306
|
+
"riff",
|
|
307
|
+
],
|
|
308
|
+
capture_output=True,
|
|
309
|
+
text=True,
|
|
310
|
+
check=False,
|
|
311
|
+
)
|
|
312
|
+
assert result.returncode != 0
|
|
313
|
+
stderr_output = result.stderr.lower()
|
|
314
|
+
assert "not supported" in stderr_output or "error" in stderr_output
|
|
315
|
+
|
|
316
|
+
def test_cli_write_force_format_unsupported_wav_vorbis(self):
|
|
317
|
+
with temp_file_with_metadata({}, "wav") as test_file:
|
|
318
|
+
result = subprocess.run(
|
|
319
|
+
[
|
|
320
|
+
sys.executable,
|
|
321
|
+
"-m",
|
|
322
|
+
"audiometa",
|
|
323
|
+
"write",
|
|
324
|
+
str(test_file),
|
|
325
|
+
"--title",
|
|
326
|
+
"Test Title",
|
|
327
|
+
"--force-format",
|
|
328
|
+
"vorbis",
|
|
329
|
+
],
|
|
330
|
+
capture_output=True,
|
|
331
|
+
text=True,
|
|
332
|
+
check=False,
|
|
333
|
+
)
|
|
334
|
+
assert result.returncode != 0
|
|
335
|
+
stderr_output = result.stderr.lower()
|
|
336
|
+
assert "not supported" in stderr_output or "error" in stderr_output
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from audiometa import get_unified_metadata
|
|
7
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
8
|
+
from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.e2e
|
|
12
|
+
class TestCLIWriteIntegerFields:
|
|
13
|
+
def test_cli_write_integer_fields(self):
|
|
14
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
15
|
+
result = subprocess.run(
|
|
16
|
+
[
|
|
17
|
+
sys.executable,
|
|
18
|
+
"-m",
|
|
19
|
+
"audiometa",
|
|
20
|
+
"write",
|
|
21
|
+
str(test_file),
|
|
22
|
+
"--disc-number",
|
|
23
|
+
"2",
|
|
24
|
+
"--disc-total",
|
|
25
|
+
"3",
|
|
26
|
+
"--bpm",
|
|
27
|
+
"120",
|
|
28
|
+
],
|
|
29
|
+
capture_output=True,
|
|
30
|
+
text=True,
|
|
31
|
+
check=False,
|
|
32
|
+
)
|
|
33
|
+
assert result.returncode == 0
|
|
34
|
+
|
|
35
|
+
metadata = get_unified_metadata(test_file)
|
|
36
|
+
assert metadata.get(UnifiedMetadataKey.DISC_NUMBER) == 2
|
|
37
|
+
assert metadata.get(UnifiedMetadataKey.DISC_TOTAL) == 3
|
|
38
|
+
assert metadata.get(UnifiedMetadataKey.BPM) == 120
|
|
39
|
+
|
|
40
|
+
def test_cli_write_track_number_simple(self):
|
|
41
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
42
|
+
result = subprocess.run(
|
|
43
|
+
[
|
|
44
|
+
sys.executable,
|
|
45
|
+
"-m",
|
|
46
|
+
"audiometa",
|
|
47
|
+
"write",
|
|
48
|
+
str(test_file),
|
|
49
|
+
"--track-number",
|
|
50
|
+
"5",
|
|
51
|
+
],
|
|
52
|
+
capture_output=True,
|
|
53
|
+
text=True,
|
|
54
|
+
check=False,
|
|
55
|
+
)
|
|
56
|
+
assert result.returncode == 0
|
|
57
|
+
|
|
58
|
+
metadata = get_unified_metadata(test_file)
|
|
59
|
+
assert metadata.get(UnifiedMetadataKey.TRACK_NUMBER) == "5"
|
|
60
|
+
|
|
61
|
+
def test_cli_write_track_number_with_total(self):
|
|
62
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
63
|
+
result = subprocess.run(
|
|
64
|
+
[
|
|
65
|
+
sys.executable,
|
|
66
|
+
"-m",
|
|
67
|
+
"audiometa",
|
|
68
|
+
"write",
|
|
69
|
+
str(test_file),
|
|
70
|
+
"--track-number",
|
|
71
|
+
"5/12",
|
|
72
|
+
],
|
|
73
|
+
capture_output=True,
|
|
74
|
+
text=True,
|
|
75
|
+
check=False,
|
|
76
|
+
)
|
|
77
|
+
assert result.returncode == 0
|
|
78
|
+
|
|
79
|
+
metadata = get_unified_metadata(test_file)
|
|
80
|
+
assert metadata.get(UnifiedMetadataKey.TRACK_NUMBER) == "5/12"
|
|
81
|
+
|
|
82
|
+
def test_cli_write_release_date_year(self):
|
|
83
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
84
|
+
result = subprocess.run(
|
|
85
|
+
[
|
|
86
|
+
sys.executable,
|
|
87
|
+
"-m",
|
|
88
|
+
"audiometa",
|
|
89
|
+
"write",
|
|
90
|
+
str(test_file),
|
|
91
|
+
"--year",
|
|
92
|
+
"2024",
|
|
93
|
+
],
|
|
94
|
+
capture_output=True,
|
|
95
|
+
text=True,
|
|
96
|
+
check=False,
|
|
97
|
+
)
|
|
98
|
+
assert result.returncode == 0
|
|
99
|
+
|
|
100
|
+
metadata = get_unified_metadata(test_file)
|
|
101
|
+
assert metadata.get(UnifiedMetadataKey.RELEASE_DATE) == "2024"
|
|
102
|
+
|
|
103
|
+
def test_cli_write_release_date_full(self):
|
|
104
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
105
|
+
result = subprocess.run(
|
|
106
|
+
[
|
|
107
|
+
sys.executable,
|
|
108
|
+
"-m",
|
|
109
|
+
"audiometa",
|
|
110
|
+
"write",
|
|
111
|
+
str(test_file),
|
|
112
|
+
"--release-date",
|
|
113
|
+
"2024-01-15",
|
|
114
|
+
],
|
|
115
|
+
capture_output=True,
|
|
116
|
+
text=True,
|
|
117
|
+
check=False,
|
|
118
|
+
)
|
|
119
|
+
assert result.returncode == 0
|
|
120
|
+
|
|
121
|
+
metadata = get_unified_metadata(test_file)
|
|
122
|
+
assert metadata.get(UnifiedMetadataKey.RELEASE_DATE) == "2024-01-15"
|
|
123
|
+
|
|
124
|
+
def test_cli_write_year_takes_precedence_over_release_date(self):
|
|
125
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
126
|
+
result = subprocess.run(
|
|
127
|
+
[
|
|
128
|
+
sys.executable,
|
|
129
|
+
"-m",
|
|
130
|
+
"audiometa",
|
|
131
|
+
"write",
|
|
132
|
+
str(test_file),
|
|
133
|
+
"--year",
|
|
134
|
+
"2023",
|
|
135
|
+
"--release-date",
|
|
136
|
+
"2024-01-15",
|
|
137
|
+
],
|
|
138
|
+
capture_output=True,
|
|
139
|
+
text=True,
|
|
140
|
+
check=False,
|
|
141
|
+
)
|
|
142
|
+
assert result.returncode == 0
|
|
143
|
+
|
|
144
|
+
metadata = get_unified_metadata(test_file)
|
|
145
|
+
assert metadata.get(UnifiedMetadataKey.RELEASE_DATE) == "2023"
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from audiometa import get_unified_metadata
|
|
7
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
8
|
+
from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.e2e
|
|
12
|
+
class TestCLIWriteListFields:
|
|
13
|
+
def test_cli_write_multiple_artists(self):
|
|
14
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
15
|
+
result = subprocess.run(
|
|
16
|
+
[
|
|
17
|
+
sys.executable,
|
|
18
|
+
"-m",
|
|
19
|
+
"audiometa",
|
|
20
|
+
"write",
|
|
21
|
+
str(test_file),
|
|
22
|
+
"--artist",
|
|
23
|
+
"Artist One",
|
|
24
|
+
"--artist",
|
|
25
|
+
"Artist Two",
|
|
26
|
+
"--artist",
|
|
27
|
+
"Artist Three",
|
|
28
|
+
],
|
|
29
|
+
capture_output=True,
|
|
30
|
+
text=True,
|
|
31
|
+
check=False,
|
|
32
|
+
)
|
|
33
|
+
assert result.returncode == 0
|
|
34
|
+
|
|
35
|
+
metadata = get_unified_metadata(test_file)
|
|
36
|
+
assert metadata.get(UnifiedMetadataKey.ARTISTS) == ["Artist One", "Artist Two", "Artist Three"]
|
|
37
|
+
|
|
38
|
+
def test_cli_write_multiple_album_artists(self):
|
|
39
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
40
|
+
result = subprocess.run(
|
|
41
|
+
[
|
|
42
|
+
sys.executable,
|
|
43
|
+
"-m",
|
|
44
|
+
"audiometa",
|
|
45
|
+
"write",
|
|
46
|
+
str(test_file),
|
|
47
|
+
"--album-artist",
|
|
48
|
+
"Album Artist One",
|
|
49
|
+
"--album-artist",
|
|
50
|
+
"Album Artist Two",
|
|
51
|
+
],
|
|
52
|
+
capture_output=True,
|
|
53
|
+
text=True,
|
|
54
|
+
check=False,
|
|
55
|
+
)
|
|
56
|
+
assert result.returncode == 0
|
|
57
|
+
|
|
58
|
+
metadata = get_unified_metadata(test_file)
|
|
59
|
+
assert metadata.get(UnifiedMetadataKey.ALBUM_ARTISTS) == ["Album Artist One", "Album Artist Two"]
|
|
60
|
+
|
|
61
|
+
def test_cli_write_multiple_genres(self):
|
|
62
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
63
|
+
result = subprocess.run(
|
|
64
|
+
[
|
|
65
|
+
sys.executable,
|
|
66
|
+
"-m",
|
|
67
|
+
"audiometa",
|
|
68
|
+
"write",
|
|
69
|
+
str(test_file),
|
|
70
|
+
"--genre",
|
|
71
|
+
"Rock",
|
|
72
|
+
"--genre",
|
|
73
|
+
"Blues",
|
|
74
|
+
"--genre",
|
|
75
|
+
"Jazz",
|
|
76
|
+
],
|
|
77
|
+
capture_output=True,
|
|
78
|
+
text=True,
|
|
79
|
+
check=False,
|
|
80
|
+
)
|
|
81
|
+
assert result.returncode == 0
|
|
82
|
+
|
|
83
|
+
metadata = get_unified_metadata(test_file)
|
|
84
|
+
assert metadata.get(UnifiedMetadataKey.GENRES_NAMES) == ["Rock", "Blues", "Jazz"]
|
|
85
|
+
|
|
86
|
+
def test_cli_write_multiple_composers(self):
|
|
87
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
88
|
+
result = subprocess.run(
|
|
89
|
+
[
|
|
90
|
+
sys.executable,
|
|
91
|
+
"-m",
|
|
92
|
+
"audiometa",
|
|
93
|
+
"write",
|
|
94
|
+
str(test_file),
|
|
95
|
+
"--composer",
|
|
96
|
+
"Composer One",
|
|
97
|
+
"--composer",
|
|
98
|
+
"Composer Two",
|
|
99
|
+
],
|
|
100
|
+
capture_output=True,
|
|
101
|
+
text=True,
|
|
102
|
+
check=False,
|
|
103
|
+
)
|
|
104
|
+
assert result.returncode == 0
|
|
105
|
+
|
|
106
|
+
metadata = get_unified_metadata(test_file)
|
|
107
|
+
assert metadata.get(UnifiedMetadataKey.COMPOSERS) == ["Composer One", "Composer Two"]
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@pytest.mark.e2e
|
|
10
|
+
class TestCLIWriteRating:
|
|
11
|
+
def test_cli_write_rating_integer(self):
|
|
12
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
13
|
+
result = subprocess.run(
|
|
14
|
+
[
|
|
15
|
+
sys.executable,
|
|
16
|
+
"-m",
|
|
17
|
+
"audiometa",
|
|
18
|
+
"write",
|
|
19
|
+
str(test_file),
|
|
20
|
+
"--rating",
|
|
21
|
+
"50",
|
|
22
|
+
],
|
|
23
|
+
capture_output=True,
|
|
24
|
+
text=True,
|
|
25
|
+
check=False,
|
|
26
|
+
)
|
|
27
|
+
assert result.returncode == 0
|
|
28
|
+
assert "Updated metadata" in result.stdout
|
|
29
|
+
|
|
30
|
+
def test_cli_invalid_rating_value_fractional_float(self):
|
|
31
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
32
|
+
result = subprocess.run(
|
|
33
|
+
[
|
|
34
|
+
sys.executable,
|
|
35
|
+
"-m",
|
|
36
|
+
"audiometa",
|
|
37
|
+
"write",
|
|
38
|
+
str(test_file),
|
|
39
|
+
"--rating",
|
|
40
|
+
"1.5",
|
|
41
|
+
],
|
|
42
|
+
capture_output=True,
|
|
43
|
+
text=True,
|
|
44
|
+
check=False,
|
|
45
|
+
)
|
|
46
|
+
assert result.returncode != 0
|
|
47
|
+
stderr_output = result.stderr.lower()
|
|
48
|
+
assert "invalid" in stderr_output or "error" in stderr_output
|
|
49
|
+
assert "raw mode" in stderr_output or "normalization" in stderr_output
|
|
50
|
+
|
|
51
|
+
def test_cli_invalid_rating_value_fractional_float_with_other_metadata(self):
|
|
52
|
+
with temp_file_with_metadata({}, "mp3") as test_file:
|
|
53
|
+
result = subprocess.run(
|
|
54
|
+
[
|
|
55
|
+
sys.executable,
|
|
56
|
+
"-m",
|
|
57
|
+
"audiometa",
|
|
58
|
+
"write",
|
|
59
|
+
str(test_file),
|
|
60
|
+
"--title",
|
|
61
|
+
"Test Song",
|
|
62
|
+
"--artist",
|
|
63
|
+
"Test Artist",
|
|
64
|
+
"--rating",
|
|
65
|
+
"7.5",
|
|
66
|
+
],
|
|
67
|
+
capture_output=True,
|
|
68
|
+
text=True,
|
|
69
|
+
check=False,
|
|
70
|
+
)
|
|
71
|
+
assert result.returncode != 0
|
|
72
|
+
stderr_output = result.stderr.lower()
|
|
73
|
+
assert "invalid" in stderr_output or "error" in stderr_output
|
|
74
|
+
assert "raw mode" in stderr_output or "normalization" in stderr_output
|