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.
Files changed (367) hide show
  1. {audiometa_python-0.6.1/audiometa_python.egg-info → audiometa_python-0.7.1}/PKG-INFO +1 -1
  2. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/__init__.py +20 -7
  3. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/_audio_file.py +37 -13
  4. {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
  5. {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
  6. {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
  7. {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
  8. 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
  9. audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_state_precedence.py +39 -0
  10. 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
  11. 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
  12. 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
  13. 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
  14. audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_metadata_combinations/test_md5_with_metadata_combinations.py +94 -0
  15. {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
  16. audiometa_python-0.7.1/audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +33 -0
  17. audiometa_python-0.7.1/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
  18. audiometa_python-0.7.1/audiometa/utils/flac_md5_state.py +22 -0
  19. {audiometa_python-0.6.1 → audiometa_python-0.7.1/audiometa_python.egg-info}/PKG-INFO +1 -1
  20. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/SOURCES.txt +10 -1
  21. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/pyproject.toml +1 -1
  22. audiometa_python-0.6.1/audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +0 -21
  23. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/LICENSE +0 -0
  24. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/README.md +0 -0
  25. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/__main__.py +0 -0
  26. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/cli.py +0 -0
  27. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/exceptions.py +0 -0
  28. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_MetadataManager.py +0 -0
  29. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/__init__.py +0 -0
  30. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/_RatingSupportingMetadataManager.py +0 -0
  31. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/__init__.py +0 -0
  32. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/id3v2/_Id3v2Manager.py +0 -0
  33. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/id3v2/__init__.py +0 -0
  34. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/id3v2/_id3v2_constants.py +0 -0
  35. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/riff/_RiffManager.py +0 -0
  36. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/riff/__init__.py +0 -0
  37. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/riff/_riff_constants.py +0 -0
  38. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +0 -0
  39. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/vorbis/__init__.py +0 -0
  40. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/_rating_supporting/vorbis/_vorbis_constants.py +0 -0
  41. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/_Id3v1Manager.py +0 -0
  42. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/__init__.py +0 -0
  43. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/_constants.py +0 -0
  44. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/id3v1_raw_metadata.py +0 -0
  45. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/manager/id3v1/id3v1_raw_metadata_key.py +0 -0
  46. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/__init__.py +0 -0
  47. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/assets/create_test_files.py +0 -0
  48. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/__init__.py +0 -0
  49. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/common/__init__.py +0 -0
  50. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/common/audio_file_creator.py +0 -0
  51. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/common/external_tool_runner.py +0 -0
  52. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/__init__.py +0 -0
  53. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_header_verifier.py +0 -0
  54. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_metadata_deleter.py +0 -0
  55. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_metadata_getter.py +0 -0
  56. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v1/id3v1_metadata_setter.py +0 -0
  57. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/__init__.py +0 -0
  58. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_frame_manual_creator.py +0 -0
  59. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_header_verifier.py +0 -0
  60. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_metadata_deleter.py +0 -0
  61. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_metadata_getter.py +0 -0
  62. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +0 -0
  63. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/__init__.py +0 -0
  64. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_header_verifier.py +0 -0
  65. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_manual_metadata_creator.py +0 -0
  66. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_metadata_deleter.py +0 -0
  67. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_metadata_getter.py +0 -0
  68. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/riff/riff_metadata_setter.py +0 -0
  69. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/scripts/__init__.py +0 -0
  70. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/technical_info_inspector.py +0 -0
  71. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/temp_file_with_metadata.py +0 -0
  72. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/__init__.py +0 -0
  73. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_header_verifier.py +0 -0
  74. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_metadata_deleter.py +0 -0
  75. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_metadata_getter.py +0 -0
  76. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/helpers/vorbis/vorbis_metadata_setter.py +0 -0
  77. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/__init__.py +0 -0
  78. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/conftest.py +0 -0
  79. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/__init__.py +0 -0
  80. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/__init__.py +0 -0
  81. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/__init__.py +0 -0
  82. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_command_structure_errors.py +0 -0
  83. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_file_access_errors.py +0 -0
  84. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_format_output_errors.py +0 -0
  85. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_input_validation_errors.py +0 -0
  86. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_missing_fields_validation.py +0 -0
  87. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_multiple_files_errors.py +0 -0
  88. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_rating_validation.py +0 -0
  89. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/error_handling/test_year_validation.py +0 -0
  90. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/__init__.py +0 -0
  91. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_basic.py +0 -0
  92. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_comprehensive.py +0 -0
  93. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_formats.py +0 -0
  94. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_metadata_content.py +0 -0
  95. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_multiple_files.py +0 -0
  96. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_options.py +0 -0
  97. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/read/test_unified.py +0 -0
  98. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/test_delete.py +0 -0
  99. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/test_formatting.py +0 -0
  100. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/test_help.py +0 -0
  101. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/__init__.py +0 -0
  102. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_basic.py +0 -0
  103. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_comprehensive.py +0 -0
  104. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_force_format.py +0 -0
  105. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_integer_fields.py +0 -0
  106. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_list_fields.py +0 -0
  107. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_rating.py +0 -0
  108. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_string_fields.py +0 -0
  109. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/cli/write/test_validation.py +0 -0
  110. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
  111. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +0 -0
  112. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/__init__.py +0 -0
  113. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_core_workflows.py +0 -0
  114. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +0 -0
  115. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +0 -0
  116. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +0 -0
  117. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/e2e/workflows/test_rating_workflows.py +0 -0
  118. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/__init__.py +0 -0
  119. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/__init__.py +0 -0
  120. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
  121. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +0 -0
  122. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +0 -0
  123. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +0 -0
  124. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +0 -0
  125. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
  126. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +0 -0
  127. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +0 -0
  128. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +0 -0
  129. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +0 -0
  130. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
  131. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +0 -0
  132. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +0 -0
  133. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +0 -0
  134. {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
  135. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +0 -0
  136. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/conftest.py +0 -0
  137. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/__init__.py +0 -0
  138. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +0 -0
  139. {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
  140. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +0 -0
  141. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +0 -0
  142. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/encoding/__init__.py +0 -0
  143. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/encoding/test_encoding.py +0 -0
  144. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +0 -0
  145. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
  146. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_audio_formats.py +0 -0
  147. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +0 -0
  148. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_consistency.py +0 -0
  149. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_edge_cases.py +0 -0
  150. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_error_handling.py +0 -0
  151. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +0 -0
  152. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_options.py +0 -0
  153. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_performance.py +0 -0
  154. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_riff_bext.py +0 -0
  155. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/get_full_metadata/test_structure.py +0 -0
  156. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
  157. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
  158. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/test_deleting.py +0 -0
  159. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/test_reading.py +0 -0
  160. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album/test_writing.py +0 -0
  161. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
  162. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +0 -0
  163. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +0 -0
  164. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +0 -0
  165. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
  166. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +0 -0
  167. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/test_reading.py +0 -0
  168. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/artists/test_writing.py +0 -0
  169. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
  170. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +0 -0
  171. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +0 -0
  172. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +0 -0
  173. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
  174. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +0 -0
  175. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/test_reading.py +0 -0
  176. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/comment/test_writing.py +0 -0
  177. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
  178. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +0 -0
  179. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/test_reading.py +0 -0
  180. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/composer/test_writing.py +0 -0
  181. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
  182. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +0 -0
  183. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +0 -0
  184. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +0 -0
  185. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/__init__.py +0 -0
  186. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_deleting.py +0 -0
  187. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_reading.py +0 -0
  188. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_writing.py +0 -0
  189. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/__init__.py +0 -0
  190. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +0 -0
  191. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +0 -0
  192. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +0 -0
  193. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/__init__.py +0 -0
  194. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/__init__.py +0 -0
  195. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/__init__.py +0 -0
  196. {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
  197. {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
  198. {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
  199. {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
  200. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +0 -0
  201. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +0 -0
  202. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/genre/test_writing.py +0 -0
  203. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/__init__.py +0 -0
  204. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/test_deleting.py +0 -0
  205. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/test_reading.py +0 -0
  206. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/isrc/test_writing.py +0 -0
  207. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/__init__.py +0 -0
  208. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/test_deleting.py +0 -0
  209. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/test_reading.py +0 -0
  210. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/language/test_writing.py +0 -0
  211. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/__init__.py +0 -0
  212. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +0 -0
  213. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +0 -0
  214. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +0 -0
  215. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/__init__.py +0 -0
  216. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +0 -0
  217. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +0 -0
  218. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +0 -0
  219. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/__init__.py +0 -0
  220. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/reading/__init__.py +0 -0
  221. {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
  222. {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
  223. {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
  224. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +0 -0
  225. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +0 -0
  226. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/__init__.py +0 -0
  227. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/__init__.py +0 -0
  228. {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
  229. {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
  230. {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
  231. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +0 -0
  232. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/__init__.py +0 -0
  233. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +0 -0
  234. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +0 -0
  235. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +0 -0
  236. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +0 -0
  237. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +0 -0
  238. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/__init__.py +0 -0
  239. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_deleting.py +0 -0
  240. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +0 -0
  241. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_reading.py +0 -0
  242. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/title/test_writing.py +0 -0
  243. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/__init__.py +0 -0
  244. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/reading/__init__.py +0 -0
  245. {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
  246. {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
  247. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +0 -0
  248. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +0 -0
  249. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/__init__.py +0 -0
  250. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/__init__.py +0 -0
  251. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +0 -0
  252. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +0 -0
  253. {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
  254. {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
  255. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +0 -0
  256. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +0 -0
  257. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +0 -0
  258. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +0 -0
  259. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +0 -0
  260. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/__init__.py +0 -0
  261. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +0 -0
  262. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +0 -0
  263. {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
  264. {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
  265. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +0 -0
  266. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +0 -0
  267. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +0 -0
  268. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +0 -0
  269. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/reading/__init__.py +0 -0
  270. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +0 -0
  271. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/reading/test_reading_error_handling.py +0 -0
  272. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/real_audio_files/__init__.py +0 -0
  273. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/real_audio_files/test_reading.py +0 -0
  274. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/real_audio_files/test_writing.py +0 -0
  275. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/__init__.py +0 -0
  276. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/__init__.py +0 -0
  277. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +0 -0
  278. {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
  279. {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
  280. {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
  281. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_bitrate.py +0 -0
  282. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_channels.py +0 -0
  283. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +0 -0
  284. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/technical_info/test_sample_rate.py +0 -0
  285. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/test_audio_file.py +0 -0
  286. {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
  287. {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
  288. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_error_handling.py +0 -0
  289. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_forced_format.py +0 -0
  290. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +0 -0
  291. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/test_partial_update.py +0 -0
  292. {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
  293. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +0 -0
  294. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +0 -0
  295. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/integration/writing/writing_strategies/test_sync_strategy.py +0 -0
  296. {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
  297. {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
  298. {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
  299. {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
  300. {audiometa_python-0.6.1/audiometa/test/tests/unit/audio_file → audiometa_python-0.7.1/audiometa/test/tests/unit}/__init__.py +0 -0
  301. {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
  302. {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
  303. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +0 -0
  304. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +0 -0
  305. {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
  306. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +0 -0
  307. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +0 -0
  308. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +0 -0
  309. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +0 -0
  310. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_context_manager.py +0 -0
  311. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_file_validation.py +0 -0
  312. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_is_audio_file.py +0 -0
  313. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_operations.py +0 -0
  314. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/audio_file/test_path_handling.py +0 -0
  315. {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
  316. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/cli/test_expand_file_patterns.py +0 -0
  317. {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
  318. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/conftest.py +0 -0
  319. {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
  320. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +0 -0
  321. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +0 -0
  322. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +0 -0
  323. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +0 -0
  324. {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
  325. {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
  326. {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
  327. {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
  328. {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
  329. {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
  330. {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
  331. {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
  332. {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
  333. {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
  334. {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
  335. {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
  336. {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
  337. {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
  338. {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
  339. {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
  340. {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
  341. {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
  342. {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
  343. {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
  344. {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
  345. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +0 -0
  346. {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
  347. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/test/tests/unit/metadata_managers/test_riff_configuration_error.py +0 -0
  348. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/__init__.py +0 -0
  349. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/id3v1_genre_code_map.py +0 -0
  350. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/metadata_format.py +0 -0
  351. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/metadata_writing_strategy.py +0 -0
  352. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/mutagen_exception_handler.py +0 -0
  353. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/__init__.py +0 -0
  354. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/base.py +0 -0
  355. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/config.py +0 -0
  356. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/macos.py +0 -0
  357. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/ubuntu.py +0 -0
  358. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/os_dependencies_checker/windows.py +0 -0
  359. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/rating_profiles.py +0 -0
  360. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/tool_path_resolver.py +0 -0
  361. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/types.py +0 -0
  362. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa/utils/unified_metadata_key.py +0 -0
  363. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/dependency_links.txt +0 -0
  364. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/entry_points.txt +0 -0
  365. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/requires.txt +0 -0
  366. {audiometa_python-0.6.1 → audiometa_python-0.7.1}/audiometa_python.egg-info/top_level.txt +0 -0
  367. {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.6.1
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) -> bool:
1110
- """Check if a FLAC file's MD5 signature is valid.
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
- True if MD5 signature is valid, False otherwise
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
- is_valid = is_flac_md5_valid("song.flac")
1128
- if is_valid:
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 False
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() if audio_file.file_extension == ".flac" else None
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 is_flac_file_md5_valid(self) -> bool:
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 False
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
- # flac -t returns 0 on success, non-zero on error
299
- # If return code is non-zero, the file is invalid
300
- if result.returncode != 0:
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 explicit error messages (shouldn't happen with return code 0, but defensive)
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 False
306
- if "FLAC__STREAM_DECODER_ERROR_STATUS_LOST_SYNC" in combined_output:
307
- return False
327
+ return FlacMd5State.INVALID
308
328
 
309
- # Check for explicit success message
310
- if "ok" in combined_output.lower():
311
- return True
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, bool)
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 not is_flac_md5_valid(test_file), "Flipped MD5 should be detected as invalid"
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 not is_flac_md5_valid(test_file), "Test file should have invalid MD5 for fix_md5_checking test"
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 not is_flac_md5_valid(test_file), "Partially corrupted MD5 should be detected as invalid"
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 not is_flac_md5_valid(test_file), "Partially corrupted MD5 should be invalid"
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 not is_flac_md5_valid(test_file), "Random MD5 corruption should be detected as invalid"
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 not is_flac_md5_valid(test_file), "Random MD5 corruption should be invalid"
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."