audiometa-python 0.6.1__tar.gz → 0.7.1__tar.gz
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_python-0.6.1/audiometa_python.egg-info → audiometa_python-0.7.1}/PKG-INFO +1 -1
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/__init__.py +20 -7
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/_audio_file.py +37 -13
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_audio_data_corruption.py +3 -2
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_flipped_md5.py +6 -4
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_partial_md5.py +6 -4
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_random_md5.py +6 -4
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_invalid_with_metadata_combinations.py +101 -0
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_state_precedence.py +39 -0
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_unset_with_metadata_combinations.py +101 -0
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_validation_fails_with_id3v1.py +61 -0
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_validation_with_id3v2_only.py +42 -0
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_validation_works_without_id3v1.py +60 -0
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_with_metadata_combinations.py +94 -0
- {audiometa_python-0.6.1/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5 → audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5}/test_unset_md5.py +9 -9
- audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +33 -0
- audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
- audiometa_python-0.7.1/audiometa/utils/flac_md5_state.py +22 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1/audiometa_python.egg-info}/PKG-INFO +1 -1
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/SOURCES.txt +10 -1
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/pyproject.toml +1 -1
- audiometa_python-0.6.1/audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +0 -21
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/LICENSE +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/README.md +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/__main__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/cli.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/exceptions.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_MetadataManager.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/_RatingSupportingMetadataManager.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/id3v2/_Id3v2Manager.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/id3v2/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/id3v2/_id3v2_constants.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/riff/_RiffManager.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/riff/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/riff/_riff_constants.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/vorbis/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/vorbis/_vorbis_constants.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/_Id3v1Manager.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/_constants.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/id3v1_raw_metadata.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/id3v1_raw_metadata_key.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/assets/create_test_files.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/common/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/common/audio_file_creator.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/common/external_tool_runner.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_header_verifier.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_metadata_deleter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_metadata_getter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_metadata_setter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_frame_manual_creator.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_header_verifier.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_metadata_deleter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_metadata_getter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_header_verifier.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_manual_metadata_creator.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_metadata_deleter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_metadata_getter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_metadata_setter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/scripts/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/technical_info_inspector.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/temp_file_with_metadata.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_header_verifier.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_metadata_deleter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_metadata_getter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_metadata_setter.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/conftest.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_command_structure_errors.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_file_access_errors.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_format_output_errors.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_input_validation_errors.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_missing_fields_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_multiple_files_errors.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_rating_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_year_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_basic.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_comprehensive.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_formats.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_metadata_content.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_multiple_files.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_options.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_unified.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/test_delete.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/test_formatting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/test_help.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_basic.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_comprehensive.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_force_format.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_integer_fields.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_list_fields.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_rating.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_string_fields.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_core_workflows.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_rating_workflows.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_with_id3v2_tags.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/conftest.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_header_deletion.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/encoding/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/encoding/test_encoding.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_audio_formats.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_consistency.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_edge_cases.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_options.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_performance.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_riff_bext.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_structure.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v1_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v2_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_riff_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_vorbis_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/reading/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_100_proportional.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_non_proportional.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_proportional.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_id3v2.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_riff.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_vorbis.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/reading/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_edge_cases.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_metadata_format.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_3.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_4.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_3.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_4.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/reading/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/reading/test_reading_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/real_audio_files/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/real_audio_files/test_reading.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/real_audio_files/test_writing.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_non_flac_error.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/integration/writing → audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_bitrate.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_channels.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_sample_rate.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/test_audio_file.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/test_audio_format_readable_after_update_all_metadata_formats.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/integration/writing/writing_strategies → audiometa_python-0.7.1/audiometa/test/tests/integration/writing}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_forced_format.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_partial_update.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields → audiometa_python-0.7.1/audiometa/test/tests/integration/writing/writing_strategies}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/test_sync_strategy.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit → audiometa_python-0.7.1/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_fail_behavior.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_no_writing_on_failure.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_strategy_specific.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/audio_file → audiometa_python-0.7.1/audiometa/test/tests/unit}/__init__.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/audio_file/technical_info → audiometa_python-0.7.1/audiometa/test/tests/unit/audio_file}/__init__.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/cli → audiometa_python-0.7.1/audiometa/test/tests/unit/audio_file/technical_info}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_duration_in_sec.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_context_manager.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_file_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_is_audio_file.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_operations.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_path_handling.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers → audiometa_python-0.7.1/audiometa/test/tests/unit/cli}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/cli/test_expand_file_patterns.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/header_info → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/conftest.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/metadata_field → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/header_info}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field}/__init__.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values}/__init__.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/test_smart_parsing.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/metadata_field/rating → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_separator_selection.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_value_filtering.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field/rating}/__init__.py +0 -0
- {audiometa_python-0.6.1/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing → audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading}/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_normalization.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_profiles_values.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/test_rating_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_configuration_error.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_writing_profiles.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_date_format_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_disc_number_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_isrc_format_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_isrc_type_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_track_number_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_type_validation_exception.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/test_metadata_format_managers_write_and_read.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/test_riff_configuration_error.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/id3v1_genre_code_map.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/metadata_format.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/metadata_writing_strategy.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/mutagen_exception_handler.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/__init__.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/base.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/config.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/macos.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/ubuntu.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/windows.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/rating_profiles.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/tool_path_resolver.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/types.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/unified_metadata_key.py +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/dependency_links.txt +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/entry_points.txt +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/requires.txt +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/top_level.txt +0 -0
- {audiometa_python-0.6.1 → audiometa_python-0.7.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: audiometa-python
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.7.1
|
|
4
4
|
Summary: A comprehensive Python library for reading and writing audio metadata across multiple formats
|
|
5
5
|
Author: AudioMeta Python Contributors
|
|
6
6
|
Author-email: Andreas Garcia <garcia.andreas.1991@gmail.com>
|
|
@@ -30,6 +30,7 @@ from .manager._rating_supporting.id3v2._Id3v2Manager import _Id3v2Manager
|
|
|
30
30
|
from .manager._rating_supporting.riff._RiffManager import _RiffManager
|
|
31
31
|
from .manager._rating_supporting.vorbis._VorbisManager import _VorbisManager
|
|
32
32
|
from .manager.id3v1._Id3v1Manager import _Id3v1Manager
|
|
33
|
+
from .utils.flac_md5_state import FlacMd5State
|
|
33
34
|
from .utils.metadata_format import MetadataFormat
|
|
34
35
|
from .utils.metadata_writing_strategy import MetadataWritingStrategy
|
|
35
36
|
from .utils.types import UnifiedMetadata, UnifiedMetadataValue
|
|
@@ -1106,8 +1107,8 @@ def get_duration_in_sec(file: PublicFileType) -> float:
|
|
|
1106
1107
|
return audio_file.get_duration_in_sec()
|
|
1107
1108
|
|
|
1108
1109
|
|
|
1109
|
-
def is_flac_md5_valid(file: PublicFileType) ->
|
|
1110
|
-
"""Check
|
|
1110
|
+
def is_flac_md5_valid(file: PublicFileType) -> FlacMd5State:
|
|
1111
|
+
"""Check the MD5 checksum validation state of a FLAC file.
|
|
1111
1112
|
|
|
1112
1113
|
This function verifies the integrity of a FLAC file by checking its MD5 signature.
|
|
1113
1114
|
Only works with FLAC files.
|
|
@@ -1116,17 +1117,27 @@ def is_flac_md5_valid(file: PublicFileType) -> bool:
|
|
|
1116
1117
|
file: Audio file path (str or Path; must be FLAC)
|
|
1117
1118
|
|
|
1118
1119
|
Returns:
|
|
1119
|
-
|
|
1120
|
+
FlacMd5State indicating the validation state:
|
|
1121
|
+
- FlacMd5State.VALID: MD5 is set and matches the audio data
|
|
1122
|
+
- FlacMd5State.UNSET: MD5 is all zeros (not set)
|
|
1123
|
+
- FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1: MD5 is set but cannot be validated due to ID3v1 tags
|
|
1124
|
+
- FlacMd5State.INVALID: MD5 is set but doesn't match the audio data (corrupted)
|
|
1120
1125
|
|
|
1121
1126
|
Raises:
|
|
1122
1127
|
FileTypeNotSupportedError: If the file is not a FLAC file
|
|
1123
1128
|
FileNotFoundError: If the file does not exist
|
|
1124
1129
|
|
|
1125
1130
|
Examples:
|
|
1131
|
+
from audiometa import is_flac_md5_valid, FlacMd5State
|
|
1132
|
+
|
|
1126
1133
|
# Check FLAC file integrity
|
|
1127
|
-
|
|
1128
|
-
if
|
|
1134
|
+
state = is_flac_md5_valid("song.flac")
|
|
1135
|
+
if state == FlacMd5State.VALID:
|
|
1129
1136
|
print("FLAC file is intact")
|
|
1137
|
+
elif state == FlacMd5State.UNSET:
|
|
1138
|
+
print("MD5 checksum is not set")
|
|
1139
|
+
elif state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1:
|
|
1140
|
+
print("MD5 cannot be validated due to ID3v1 tags")
|
|
1130
1141
|
else:
|
|
1131
1142
|
print("FLAC file may be corrupted")
|
|
1132
1143
|
"""
|
|
@@ -1134,7 +1145,7 @@ def is_flac_md5_valid(file: PublicFileType) -> bool:
|
|
|
1134
1145
|
try:
|
|
1135
1146
|
return audio_file.is_flac_file_md5_valid()
|
|
1136
1147
|
except FileCorruptedError:
|
|
1137
|
-
return
|
|
1148
|
+
return FlacMd5State.INVALID
|
|
1138
1149
|
|
|
1139
1150
|
|
|
1140
1151
|
def fix_md5_checking(file: PublicFileType) -> str:
|
|
@@ -1237,7 +1248,9 @@ def get_full_metadata(
|
|
|
1237
1248
|
"file_extension": audio_file.file_extension,
|
|
1238
1249
|
"audio_format_name": audio_file.get_audio_format_name(),
|
|
1239
1250
|
"is_flac_md5_valid": (
|
|
1240
|
-
audio_file.is_flac_file_md5_valid()
|
|
1251
|
+
audio_file.is_flac_file_md5_valid() == FlacMd5State.VALID
|
|
1252
|
+
if audio_file.file_extension == ".flac"
|
|
1253
|
+
else None
|
|
1241
1254
|
),
|
|
1242
1255
|
}
|
|
1243
1256
|
except Exception:
|
|
@@ -23,6 +23,7 @@ from .exceptions import (
|
|
|
23
23
|
)
|
|
24
24
|
from .manager._rating_supporting.id3v2._id3v2_constants import ID3V2_HEADER_SIZE
|
|
25
25
|
from .manager._rating_supporting.riff._riff_constants import RIFF_HEADER_SIZE
|
|
26
|
+
from .utils.flac_md5_state import FlacMd5State
|
|
26
27
|
from .utils.metadata_format import MetadataFormat
|
|
27
28
|
from .utils.mutagen_exception_handler import handle_mutagen_exception
|
|
28
29
|
from .utils.tool_path_resolver import get_tool_path
|
|
@@ -280,14 +281,31 @@ class _AudioFile:
|
|
|
280
281
|
except Exception:
|
|
281
282
|
return False
|
|
282
283
|
|
|
283
|
-
def
|
|
284
|
+
def _has_id3v1_tags(self) -> bool:
|
|
285
|
+
"""Check if FLAC file has ID3v1 tags.
|
|
286
|
+
|
|
287
|
+
Only ID3v1 tags cause validation failures, so we only need to check for ID3v1.
|
|
288
|
+
ID3v2 tags do not interfere with flac -t validation.
|
|
289
|
+
"""
|
|
290
|
+
try:
|
|
291
|
+
with Path(self.file_path).open("rb") as f:
|
|
292
|
+
# Check for ID3v1 at the end (last 128 bytes)
|
|
293
|
+
f.seek(-128, 2)
|
|
294
|
+
id3v1_header = f.read(3)
|
|
295
|
+
return id3v1_header == b"TAG"
|
|
296
|
+
except Exception:
|
|
297
|
+
return False
|
|
298
|
+
|
|
299
|
+
def is_flac_file_md5_valid(self) -> FlacMd5State:
|
|
284
300
|
if self.file_extension != ".flac":
|
|
285
301
|
msg = "The file is not a FLAC file"
|
|
286
302
|
raise FileTypeNotSupportedError(msg)
|
|
287
303
|
|
|
304
|
+
# Check if MD5 is unset (all zeros)
|
|
288
305
|
if self._is_md5_unset():
|
|
289
|
-
return
|
|
306
|
+
return FlacMd5State.UNSET
|
|
290
307
|
|
|
308
|
+
# Run flac -t to validate MD5
|
|
291
309
|
result = subprocess.run([get_tool_path("flac"), "-t", self.file_path], capture_output=True, check=False)
|
|
292
310
|
|
|
293
311
|
# Combine stdout and stderr as flac may output to either
|
|
@@ -295,20 +313,26 @@ class _AudioFile:
|
|
|
295
313
|
stderr_output = result.stderr.decode()
|
|
296
314
|
combined_output = stdout_output + stderr_output
|
|
297
315
|
|
|
298
|
-
#
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
return False
|
|
316
|
+
# Check for explicit success message
|
|
317
|
+
if result.returncode == 0 and "ok" in combined_output.lower():
|
|
318
|
+
return FlacMd5State.VALID
|
|
302
319
|
|
|
303
|
-
# Check for
|
|
320
|
+
# Check for ID3v1-related errors when ID3v1 tags are present
|
|
321
|
+
has_id3v1 = self._has_id3v1_tags()
|
|
322
|
+
if has_id3v1 and "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC" in combined_output:
|
|
323
|
+
return FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
324
|
+
|
|
325
|
+
# Check for explicit MD5 mismatch (corruption)
|
|
304
326
|
if "MD5 signature mismatch" in combined_output:
|
|
305
|
-
return
|
|
306
|
-
if "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC" in combined_output:
|
|
307
|
-
return False
|
|
327
|
+
return FlacMd5State.INVALID
|
|
308
328
|
|
|
309
|
-
#
|
|
310
|
-
if
|
|
311
|
-
return
|
|
329
|
+
# If flac -t failed and we have ID3v1 tags, it's likely due to ID3v1 interference
|
|
330
|
+
if has_id3v1 and result.returncode != 0:
|
|
331
|
+
return FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
332
|
+
|
|
333
|
+
# If return code is non-zero and no specific error message, assume invalid
|
|
334
|
+
if result.returncode != 0:
|
|
335
|
+
return FlacMd5State.INVALID
|
|
312
336
|
|
|
313
337
|
# If return code was 0 but no "ok" found, something unexpected happened
|
|
314
338
|
msg = "The Flac file md5 check failed"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import pytest
|
|
2
2
|
|
|
3
|
-
from audiometa import is_flac_md5_valid
|
|
3
|
+
from audiometa import FlacMd5State, is_flac_md5_valid
|
|
4
4
|
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
5
5
|
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import corrupt_audio_data, ensure_flac_has_md5
|
|
6
6
|
|
|
@@ -18,4 +18,5 @@ class TestAudioDataCorruption:
|
|
|
18
18
|
# If the decoded PCM is unchanged, the MD5 will still match (correct behavior).
|
|
19
19
|
# Manual MD5 verification works correctly - it will detect when MD5 doesn't match PCM.
|
|
20
20
|
# This test verifies the function handles this scenario gracefully.
|
|
21
|
-
assert isinstance(result,
|
|
21
|
+
assert isinstance(result, FlacMd5State)
|
|
22
|
+
assert result in [FlacMd5State.VALID, FlacMd5State.INVALID]
|
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
from audiometa import fix_md5_checking, is_flac_md5_valid
|
|
5
|
+
from audiometa import FlacMd5State, fix_md5_checking, is_flac_md5_valid
|
|
6
6
|
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
7
7
|
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import corrupt_md5, ensure_flac_has_md5
|
|
8
8
|
|
|
@@ -14,16 +14,18 @@ class TestFlippedMd5:
|
|
|
14
14
|
ensure_flac_has_md5(test_file)
|
|
15
15
|
corrupt_md5(test_file, "flip_all")
|
|
16
16
|
|
|
17
|
-
assert
|
|
17
|
+
assert is_flac_md5_valid(test_file) == FlacMd5State.INVALID, "Flipped MD5 should be detected as INVALID"
|
|
18
18
|
|
|
19
19
|
def test_fix_md5_checking_flac(self):
|
|
20
20
|
with temp_file_with_metadata({}, "flac") as test_file:
|
|
21
21
|
ensure_flac_has_md5(test_file)
|
|
22
22
|
corrupt_md5(test_file, "flip_all")
|
|
23
23
|
|
|
24
|
-
assert
|
|
24
|
+
assert (
|
|
25
|
+
is_flac_md5_valid(test_file) == FlacMd5State.INVALID
|
|
26
|
+
), "Test file should have invalid MD5 for fix_md5_checking test"
|
|
25
27
|
|
|
26
28
|
fixed_file_path = fix_md5_checking(test_file)
|
|
27
|
-
assert is_flac_md5_valid(fixed_file_path), "Fixed file should have valid MD5"
|
|
29
|
+
assert is_flac_md5_valid(fixed_file_path) == FlacMd5State.VALID, "Fixed file should have valid MD5"
|
|
28
30
|
|
|
29
31
|
Path(fixed_file_path).unlink()
|
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
from audiometa import fix_md5_checking, is_flac_md5_valid
|
|
5
|
+
from audiometa import FlacMd5State, fix_md5_checking, is_flac_md5_valid
|
|
6
6
|
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
7
7
|
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import corrupt_md5, ensure_flac_has_md5
|
|
8
8
|
|
|
@@ -14,16 +14,18 @@ class TestPartialMd5:
|
|
|
14
14
|
ensure_flac_has_md5(test_file)
|
|
15
15
|
corrupt_md5(test_file, "partial")
|
|
16
16
|
|
|
17
|
-
assert
|
|
17
|
+
assert (
|
|
18
|
+
is_flac_md5_valid(test_file) == FlacMd5State.INVALID
|
|
19
|
+
), "Partially corrupted MD5 should be detected as INVALID"
|
|
18
20
|
|
|
19
21
|
def test_fix_md5_checking_with_partial_corruption(self):
|
|
20
22
|
with temp_file_with_metadata({}, "flac") as test_file:
|
|
21
23
|
ensure_flac_has_md5(test_file)
|
|
22
24
|
corrupt_md5(test_file, "partial")
|
|
23
25
|
|
|
24
|
-
assert
|
|
26
|
+
assert is_flac_md5_valid(test_file) == FlacMd5State.INVALID, "Partially corrupted MD5 should be INVALID"
|
|
25
27
|
|
|
26
28
|
fixed_file_path = fix_md5_checking(test_file)
|
|
27
|
-
assert is_flac_md5_valid(fixed_file_path), "Fixed file should have valid MD5"
|
|
29
|
+
assert is_flac_md5_valid(fixed_file_path) == FlacMd5State.VALID, "Fixed file should have valid MD5"
|
|
28
30
|
|
|
29
31
|
Path(fixed_file_path).unlink()
|
|
@@ -2,7 +2,7 @@ from pathlib import Path
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
from audiometa import fix_md5_checking, is_flac_md5_valid
|
|
5
|
+
from audiometa import FlacMd5State, fix_md5_checking, is_flac_md5_valid
|
|
6
6
|
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
7
7
|
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import corrupt_md5, ensure_flac_has_md5
|
|
8
8
|
|
|
@@ -14,16 +14,18 @@ class TestRandomMd5:
|
|
|
14
14
|
ensure_flac_has_md5(test_file)
|
|
15
15
|
corrupt_md5(test_file, "random")
|
|
16
16
|
|
|
17
|
-
assert
|
|
17
|
+
assert (
|
|
18
|
+
is_flac_md5_valid(test_file) == FlacMd5State.INVALID
|
|
19
|
+
), "Random MD5 corruption should be detected as INVALID"
|
|
18
20
|
|
|
19
21
|
def test_fix_md5_checking_with_random_corruption(self):
|
|
20
22
|
with temp_file_with_metadata({}, "flac") as test_file:
|
|
21
23
|
ensure_flac_has_md5(test_file)
|
|
22
24
|
corrupt_md5(test_file, "random")
|
|
23
25
|
|
|
24
|
-
assert
|
|
26
|
+
assert is_flac_md5_valid(test_file) == FlacMd5State.INVALID, "Random MD5 corruption should be INVALID"
|
|
25
27
|
|
|
26
28
|
fixed_file_path = fix_md5_checking(test_file)
|
|
27
|
-
assert is_flac_md5_valid(fixed_file_path), "Fixed file should have valid MD5"
|
|
29
|
+
assert is_flac_md5_valid(fixed_file_path) == FlacMd5State.VALID, "Fixed file should have valid MD5"
|
|
28
30
|
|
|
29
31
|
Path(fixed_file_path).unlink()
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Test INVALID MD5 state with metadata format combinations that support validation."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from audiometa import FlacMd5State, is_flac_md5_valid
|
|
6
|
+
from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
|
|
7
|
+
from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
|
|
8
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
9
|
+
from audiometa.test.helpers.vorbis import VorbisMetadataSetter
|
|
10
|
+
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import corrupt_md5, ensure_flac_has_md5
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.integration
|
|
14
|
+
class TestMd5InvalidWithMetadataCombinations:
|
|
15
|
+
"""Test INVALID MD5 state with metadata format combinations that support validation."""
|
|
16
|
+
|
|
17
|
+
def test_invalid_md5_no_metadata(self):
|
|
18
|
+
"""Test INVALID state with no metadata."""
|
|
19
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
20
|
+
ensure_flac_has_md5(test_file)
|
|
21
|
+
corrupt_md5(test_file, "random")
|
|
22
|
+
state = is_flac_md5_valid(test_file)
|
|
23
|
+
assert state == FlacMd5State.INVALID, "Clean FLAC with invalid MD5 should return INVALID"
|
|
24
|
+
|
|
25
|
+
def test_invalid_md5_vorbis_only(self):
|
|
26
|
+
"""Test INVALID state with Vorbis metadata only."""
|
|
27
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
28
|
+
ensure_flac_has_md5(test_file)
|
|
29
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
30
|
+
corrupt_md5(test_file, "random")
|
|
31
|
+
state = is_flac_md5_valid(test_file)
|
|
32
|
+
assert state == FlacMd5State.INVALID, "FLAC with Vorbis metadata and invalid MD5 should return INVALID"
|
|
33
|
+
|
|
34
|
+
def test_invalid_md5_id3v2_only(self):
|
|
35
|
+
"""Test INVALID state with ID3v2 metadata only."""
|
|
36
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
37
|
+
ensure_flac_has_md5(test_file)
|
|
38
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
39
|
+
corrupt_md5(test_file, "random")
|
|
40
|
+
state = is_flac_md5_valid(test_file)
|
|
41
|
+
assert state == FlacMd5State.INVALID, "FLAC with ID3v2 metadata and invalid MD5 should return INVALID"
|
|
42
|
+
|
|
43
|
+
def test_invalid_md5_vorbis_and_id3v2(self):
|
|
44
|
+
"""Test INVALID state with Vorbis and ID3v2 metadata."""
|
|
45
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
46
|
+
ensure_flac_has_md5(test_file)
|
|
47
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
48
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
49
|
+
corrupt_md5(test_file, "random")
|
|
50
|
+
state = is_flac_md5_valid(test_file)
|
|
51
|
+
assert (
|
|
52
|
+
state == FlacMd5State.INVALID
|
|
53
|
+
), "FLAC with Vorbis and ID3v2 metadata and invalid MD5 should return INVALID"
|
|
54
|
+
|
|
55
|
+
def test_invalid_md5_with_id3v1_returns_uncheckable(self):
|
|
56
|
+
"""Test that invalid MD5 with ID3v1 returns UNCHECKABLE_DUE_TO_ID3, not INVALID."""
|
|
57
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
58
|
+
ensure_flac_has_md5(test_file)
|
|
59
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
60
|
+
corrupt_md5(test_file, "random")
|
|
61
|
+
state = is_flac_md5_valid(test_file)
|
|
62
|
+
assert (
|
|
63
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
64
|
+
), "FLAC with ID3v1 should return UNCHECKABLE_DUE_TO_ID3 even if MD5 corrupted (ID3v1 takes precedence)"
|
|
65
|
+
|
|
66
|
+
def test_invalid_md5_vorbis_and_id3v1_returns_uncheckable(self):
|
|
67
|
+
"""Test that invalid MD5 with Vorbis and ID3v1 returns UNCHECKABLE_DUE_TO_ID3."""
|
|
68
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
69
|
+
ensure_flac_has_md5(test_file)
|
|
70
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
71
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
72
|
+
corrupt_md5(test_file, "random")
|
|
73
|
+
state = is_flac_md5_valid(test_file)
|
|
74
|
+
assert (
|
|
75
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
76
|
+
), "FLAC with Vorbis and ID3v1 metadata should return UNCHECKABLE_DUE_TO_ID3 (ID3v1 takes precedence)"
|
|
77
|
+
|
|
78
|
+
def test_invalid_md5_id3v1_and_id3v2_returns_uncheckable(self):
|
|
79
|
+
"""Test that invalid MD5 with ID3v1 and ID3v2 returns UNCHECKABLE_DUE_TO_ID3."""
|
|
80
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
81
|
+
ensure_flac_has_md5(test_file)
|
|
82
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
83
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
84
|
+
corrupt_md5(test_file, "random")
|
|
85
|
+
state = is_flac_md5_valid(test_file)
|
|
86
|
+
assert (
|
|
87
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
88
|
+
), "FLAC with ID3v1 and ID3v2 metadata should return UNCHECKABLE_DUE_TO_ID3 (ID3v1 takes precedence)"
|
|
89
|
+
|
|
90
|
+
def test_invalid_md5_all_formats_returns_uncheckable(self):
|
|
91
|
+
"""Test that invalid MD5 with all metadata formats returns UNCHECKABLE_DUE_TO_ID3."""
|
|
92
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
93
|
+
ensure_flac_has_md5(test_file)
|
|
94
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
95
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
96
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
97
|
+
corrupt_md5(test_file, "random")
|
|
98
|
+
state = is_flac_md5_valid(test_file)
|
|
99
|
+
assert (
|
|
100
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
101
|
+
), "FLAC with all metadata formats should return UNCHECKABLE_DUE_TO_ID3 (ID3v1 takes precedence)"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""Test that state detection follows correct precedence rules for MD5 validation."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from audiometa import FlacMd5State, is_flac_md5_valid
|
|
6
|
+
from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
|
|
7
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
8
|
+
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import (
|
|
9
|
+
corrupt_md5,
|
|
10
|
+
create_flac_without_md5,
|
|
11
|
+
ensure_flac_has_md5,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.mark.integration
|
|
16
|
+
class TestMd5StatePrecedence:
|
|
17
|
+
"""Test that state detection follows correct precedence rules."""
|
|
18
|
+
|
|
19
|
+
def test_unset_takes_precedence_over_uncheckable(self):
|
|
20
|
+
"""Test that UNSET state takes precedence over UNCHECKABLE_DUE_TO_ID3."""
|
|
21
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
22
|
+
ensure_flac_has_md5(test_file)
|
|
23
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
24
|
+
create_flac_without_md5(test_file)
|
|
25
|
+
state = is_flac_md5_valid(test_file)
|
|
26
|
+
assert (
|
|
27
|
+
state == FlacMd5State.UNSET
|
|
28
|
+
), "UNSET should take precedence over UNCHECKABLE_DUE_TO_ID3 when MD5 is unset"
|
|
29
|
+
|
|
30
|
+
def test_uncheckable_takes_precedence_over_invalid_when_id3v1_present(self):
|
|
31
|
+
"""Test that UNCHECKABLE_DUE_TO_ID3 takes precedence over INVALID when ID3v1 is present."""
|
|
32
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
33
|
+
ensure_flac_has_md5(test_file)
|
|
34
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
35
|
+
corrupt_md5(test_file, "random")
|
|
36
|
+
state = is_flac_md5_valid(test_file)
|
|
37
|
+
assert (
|
|
38
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
39
|
+
), "UNCHECKABLE_DUE_TO_ID3 should take precedence over INVALID when ID3v1 is present"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
"""Test UNSET MD5 state with all metadata format combinations."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from audiometa import FlacMd5State, is_flac_md5_valid
|
|
6
|
+
from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
|
|
7
|
+
from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
|
|
8
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
9
|
+
from audiometa.test.helpers.vorbis import VorbisMetadataSetter
|
|
10
|
+
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import (
|
|
11
|
+
create_flac_without_md5,
|
|
12
|
+
ensure_flac_has_md5,
|
|
13
|
+
)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@pytest.mark.integration
|
|
17
|
+
class TestMd5UnsetWithMetadataCombinations:
|
|
18
|
+
"""Test UNSET MD5 state with all metadata format combinations."""
|
|
19
|
+
|
|
20
|
+
def test_unset_md5_no_metadata(self):
|
|
21
|
+
"""Test UNSET state with no metadata."""
|
|
22
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
23
|
+
create_flac_without_md5(test_file)
|
|
24
|
+
state = is_flac_md5_valid(test_file)
|
|
25
|
+
assert state == FlacMd5State.UNSET, "Clean FLAC with unset MD5 should return UNSET"
|
|
26
|
+
|
|
27
|
+
def test_unset_md5_vorbis_only(self):
|
|
28
|
+
"""Test UNSET state with Vorbis metadata only."""
|
|
29
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
30
|
+
ensure_flac_has_md5(test_file)
|
|
31
|
+
create_flac_without_md5(test_file)
|
|
32
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
33
|
+
state = is_flac_md5_valid(test_file)
|
|
34
|
+
assert state == FlacMd5State.UNSET, "FLAC with Vorbis metadata and unset MD5 should return UNSET"
|
|
35
|
+
|
|
36
|
+
def test_unset_md5_id3v2_only(self):
|
|
37
|
+
"""Test UNSET state with ID3v2 metadata only."""
|
|
38
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
39
|
+
ensure_flac_has_md5(test_file)
|
|
40
|
+
create_flac_without_md5(test_file)
|
|
41
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
42
|
+
state = is_flac_md5_valid(test_file)
|
|
43
|
+
assert state == FlacMd5State.UNSET, "FLAC with ID3v2 metadata and unset MD5 should return UNSET"
|
|
44
|
+
|
|
45
|
+
def test_unset_md5_id3v1_only(self):
|
|
46
|
+
"""Test UNSET state with ID3v1 metadata only (should still be UNSET, not UNCHECKABLE)."""
|
|
47
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
48
|
+
ensure_flac_has_md5(test_file)
|
|
49
|
+
create_flac_without_md5(test_file)
|
|
50
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
51
|
+
state = is_flac_md5_valid(test_file)
|
|
52
|
+
assert (
|
|
53
|
+
state == FlacMd5State.UNSET
|
|
54
|
+
), "FLAC with ID3v1 metadata and unset MD5 should return UNSET (unset takes precedence)"
|
|
55
|
+
|
|
56
|
+
def test_unset_md5_vorbis_and_id3v2(self):
|
|
57
|
+
"""Test UNSET state with Vorbis and ID3v2 metadata."""
|
|
58
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
59
|
+
ensure_flac_has_md5(test_file)
|
|
60
|
+
create_flac_without_md5(test_file)
|
|
61
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
62
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
63
|
+
state = is_flac_md5_valid(test_file)
|
|
64
|
+
assert state == FlacMd5State.UNSET, "FLAC with Vorbis and ID3v2 metadata and unset MD5 should return UNSET"
|
|
65
|
+
|
|
66
|
+
def test_unset_md5_vorbis_and_id3v1(self):
|
|
67
|
+
"""Test UNSET state with Vorbis and ID3v1 metadata (unset takes precedence)."""
|
|
68
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
69
|
+
ensure_flac_has_md5(test_file)
|
|
70
|
+
create_flac_without_md5(test_file)
|
|
71
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
72
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
73
|
+
state = is_flac_md5_valid(test_file)
|
|
74
|
+
assert (
|
|
75
|
+
state == FlacMd5State.UNSET
|
|
76
|
+
), "FLAC with Vorbis and ID3v1 metadata and unset MD5 should return UNSET (unset takes precedence)"
|
|
77
|
+
|
|
78
|
+
def test_unset_md5_id3v1_and_id3v2(self):
|
|
79
|
+
"""Test UNSET state with ID3v1 and ID3v2 metadata (unset takes precedence)."""
|
|
80
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
81
|
+
ensure_flac_has_md5(test_file)
|
|
82
|
+
create_flac_without_md5(test_file)
|
|
83
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
84
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
85
|
+
state = is_flac_md5_valid(test_file)
|
|
86
|
+
assert (
|
|
87
|
+
state == FlacMd5State.UNSET
|
|
88
|
+
), "FLAC with ID3v1 and ID3v2 metadata and unset MD5 should return UNSET (unset takes precedence)"
|
|
89
|
+
|
|
90
|
+
def test_unset_md5_all_formats(self):
|
|
91
|
+
"""Test UNSET state with all metadata formats (unset takes precedence)."""
|
|
92
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
93
|
+
ensure_flac_has_md5(test_file)
|
|
94
|
+
create_flac_without_md5(test_file)
|
|
95
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
96
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
97
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
98
|
+
state = is_flac_md5_valid(test_file)
|
|
99
|
+
assert (
|
|
100
|
+
state == FlacMd5State.UNSET
|
|
101
|
+
), "FLAC with all metadata formats and unset MD5 should return UNSET (unset takes precedence)"
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"""Test that MD5 validation returns UNCHECKABLE_DUE_TO_ID3 when ID3v1 tags are present."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from audiometa import FlacMd5State, is_flac_md5_valid
|
|
6
|
+
from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
|
|
7
|
+
from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
|
|
8
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
9
|
+
from audiometa.test.helpers.vorbis import VorbisMetadataSetter
|
|
10
|
+
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import ensure_flac_has_md5
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest.mark.integration
|
|
14
|
+
class TestMd5ValidationFailsWithId3v1:
|
|
15
|
+
"""Test that MD5 validation returns UNCHECKABLE_DUE_TO_ID3 when ID3v1 tags are present.
|
|
16
|
+
|
|
17
|
+
These tests confirm that validation fails (returns UNCHECKABLE_DUE_TO_ID3) for all
|
|
18
|
+
metadata combinations that include ID3v1 tags, regardless of other metadata formats.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def test_validation_fails_id3v1_only(self):
|
|
22
|
+
"""Test that validation fails with ID3v1 metadata only."""
|
|
23
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
24
|
+
ensure_flac_has_md5(test_file)
|
|
25
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
26
|
+
state = is_flac_md5_valid(test_file)
|
|
27
|
+
assert state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1, "Validation should fail with ID3v1 metadata only"
|
|
28
|
+
|
|
29
|
+
def test_validation_fails_vorbis_and_id3v1(self):
|
|
30
|
+
"""Test that validation fails with Vorbis and ID3v1 metadata."""
|
|
31
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
32
|
+
ensure_flac_has_md5(test_file)
|
|
33
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
34
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
35
|
+
state = is_flac_md5_valid(test_file)
|
|
36
|
+
assert (
|
|
37
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
38
|
+
), "Validation should fail with Vorbis and ID3v1 metadata"
|
|
39
|
+
|
|
40
|
+
def test_validation_fails_id3v1_and_id3v2(self):
|
|
41
|
+
"""Test that validation fails with ID3v1 and ID3v2 metadata."""
|
|
42
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
43
|
+
ensure_flac_has_md5(test_file)
|
|
44
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
45
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
46
|
+
state = is_flac_md5_valid(test_file)
|
|
47
|
+
assert (
|
|
48
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
49
|
+
), "Validation should fail with ID3v1 and ID3v2 metadata"
|
|
50
|
+
|
|
51
|
+
def test_validation_fails_all_formats(self):
|
|
52
|
+
"""Test that validation fails with all metadata formats (ID3v1 present)."""
|
|
53
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
54
|
+
ensure_flac_has_md5(test_file)
|
|
55
|
+
VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
|
|
56
|
+
ID3v1MetadataSetter.set_title(test_file, "ID3v1 Title")
|
|
57
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
58
|
+
state = is_flac_md5_valid(test_file)
|
|
59
|
+
assert (
|
|
60
|
+
state == FlacMd5State.UNCHECKABLE_DUE_TO_ID3V1
|
|
61
|
+
), "Validation should fail with all metadata formats when ID3v1 is present"
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""Test that ID3v2 tags alone do NOT cause validation failures."""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
|
|
5
|
+
from audiometa import FlacMd5State, is_flac_md5_valid
|
|
6
|
+
from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
|
|
7
|
+
from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
|
|
8
|
+
from audiometa.test.tests.integration.technical_info.flac_md5.conftest import corrupt_md5, ensure_flac_has_md5
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@pytest.mark.integration
|
|
12
|
+
class TestMd5ValidationWithId3v2Only:
|
|
13
|
+
"""Test that ID3v2 tags alone do NOT cause validation failures.
|
|
14
|
+
|
|
15
|
+
These tests verify that ID3v2 tags (without ID3v1) do not interfere with validation
|
|
16
|
+
and return appropriate states (VALID or INVALID) based on actual MD5 state.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
def test_id3v2_alone_with_valid_md5_returns_valid(self):
|
|
20
|
+
"""Test that ID3v2 tags alone with valid MD5 return VALID (not UNCHECKABLE)."""
|
|
21
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
22
|
+
ensure_flac_has_md5(test_file)
|
|
23
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
24
|
+
state = is_flac_md5_valid(test_file)
|
|
25
|
+
assert (
|
|
26
|
+
state == FlacMd5State.VALID
|
|
27
|
+
), "ID3v2 tags alone with valid MD5 should return VALID, not UNCHECKABLE_DUE_TO_ID3"
|
|
28
|
+
|
|
29
|
+
def test_id3v2_alone_with_invalid_md5_returns_invalid(self):
|
|
30
|
+
"""Test that ID3v2 tags alone with invalid MD5 return INVALID (not UNCHECKABLE).
|
|
31
|
+
|
|
32
|
+
This confirms that ID3v2 tags do NOT cause validation failures - even with
|
|
33
|
+
corrupted MD5, we get INVALID (actual corruption) rather than UNCHECKABLE_DUE_TO_ID3.
|
|
34
|
+
"""
|
|
35
|
+
with temp_file_with_metadata({}, "flac") as test_file:
|
|
36
|
+
ensure_flac_has_md5(test_file)
|
|
37
|
+
ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title"})
|
|
38
|
+
corrupt_md5(test_file, "random")
|
|
39
|
+
state = is_flac_md5_valid(test_file)
|
|
40
|
+
assert (
|
|
41
|
+
state == FlacMd5State.INVALID
|
|
42
|
+
), "ID3v2 alone with invalid MD5 returns INVALID, not UNCHECKABLE. Proves ID3v2 doesn't cause failures."
|