audiometa-python 1.4.2__tar.gz → 1.4.3__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 (422) hide show
  1. {audiometa_python-1.4.2/audiometa_python.egg-info → audiometa_python-1.4.3}/PKG-INFO +2 -2
  2. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/__init__.py +22 -17
  3. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/_audio_file.py +3 -3
  4. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_MetadataManager.py +6 -4
  5. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/_RatingSupportingMetadataManager.py +3 -1
  6. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/id3v2/_Id3v2Manager.py +2 -2
  7. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/id3v2/_id3v2_reader.py +1 -1
  8. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/id3v2/_id3v2_writer.py +3 -10
  9. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/riff/_RiffManager.py +2 -2
  10. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +29 -3
  11. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/id3v1/_Id3v1Manager.py +4 -5
  12. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v1/__init__.py +1 -1
  13. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v2/__init__.py +2 -6
  14. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/riff/__init__.py +1 -1
  15. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/vorbis/__init__.py +1 -1
  16. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_multiple_files_errors.py +6 -6
  17. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +18 -18
  18. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_structure.py +12 -12
  19. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/disc_number/test_writing.py +82 -0
  20. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_invalid_md5.py +6 -6
  21. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_invalid_with_metadata_combinations.py +15 -15
  22. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_state_precedence.py +6 -6
  23. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_unset_with_metadata_combinations.py +12 -12
  24. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_validation_fails_with_id3v1.py +9 -9
  25. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_validation_with_id3v2_only.py +6 -6
  26. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_with_metadata_combinations.py +12 -12
  27. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/test_flipped_md5.py +3 -3
  28. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_md5_repair_with_metadata.py +6 -6
  29. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/test_bitrate.py +3 -3
  30. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/header_info/test_riff_info_chunk_fourcc.py +9 -3
  31. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/flac_md5_state.py +2 -2
  32. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/metadata_format.py +5 -2
  33. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/metadata_writing_strategy.py +2 -2
  34. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/os_dependencies_checker/base.py +1 -1
  35. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/os_dependencies_checker/ubuntu.py +2 -2
  36. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/types.py +2 -2
  37. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/unified_metadata_key.py +5 -2
  38. {audiometa_python-1.4.2 → audiometa_python-1.4.3/audiometa_python.egg-info}/PKG-INFO +2 -2
  39. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa_python.egg-info/requires.txt +1 -1
  40. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/pyproject.toml +14 -3
  41. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/LICENSE +0 -0
  42. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/README.md +0 -0
  43. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/__main__.py +0 -0
  44. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/cli.py +0 -0
  45. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/exceptions.py +0 -0
  46. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/__init__.py +0 -0
  47. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/__init__.py +0 -0
  48. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/id3v2/__init__.py +1 -1
  49. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/id3v2/_id3v1_preserver.py +0 -0
  50. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/id3v2/_id3v2_constants.py +0 -0
  51. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/id3v2/_id3v2_flac_handler.py +0 -0
  52. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/riff/__init__.py +1 -1
  53. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/riff/_riff_bext_chunk.py +0 -0
  54. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/riff/_riff_constants.py +0 -0
  55. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/riff/_riff_file_structure.py +0 -0
  56. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/riff/_riff_info_chunk.py +0 -0
  57. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/vorbis/__init__.py +1 -1
  58. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/_rating_supporting/vorbis/_vorbis_constants.py +0 -0
  59. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/id3v1/__init__.py +0 -0
  60. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/id3v1/_constants.py +0 -0
  61. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/id3v1/id3v1_raw_metadata.py +0 -0
  62. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/manager/id3v1/id3v1_raw_metadata_key.py +0 -0
  63. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/__init__.py +0 -0
  64. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/assets/create_test_files.py +0 -0
  65. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/__init__.py +0 -0
  66. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/common/__init__.py +0 -0
  67. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/common/audio_file_creator.py +0 -0
  68. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/common/external_tool_runner.py +0 -0
  69. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v1/id3v1_header_verifier.py +0 -0
  70. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v1/id3v1_metadata_deleter.py +0 -0
  71. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v1/id3v1_metadata_getter.py +0 -0
  72. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v1/id3v1_metadata_setter.py +0 -0
  73. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v2/id3v2_frame_manual_creator.py +0 -0
  74. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v2/id3v2_header_verifier.py +0 -0
  75. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v2/id3v2_metadata_deleter.py +0 -0
  76. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v2/id3v2_metadata_getter.py +0 -0
  77. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +0 -0
  78. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/riff/riff_header_verifier.py +0 -0
  79. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/riff/riff_manual_metadata_creator.py +0 -0
  80. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/riff/riff_metadata_deleter.py +0 -0
  81. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/riff/riff_metadata_getter.py +0 -0
  82. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/riff/riff_metadata_setter.py +0 -0
  83. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/scripts/__init__.py +0 -0
  84. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/technical_info_inspector.py +0 -0
  85. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/temp_file_with_metadata.py +0 -0
  86. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/vorbis/vorbis_header_verifier.py +0 -0
  87. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/vorbis/vorbis_metadata_deleter.py +0 -0
  88. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/vorbis/vorbis_metadata_getter.py +0 -0
  89. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/helpers/vorbis/vorbis_metadata_setter.py +0 -0
  90. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/__init__.py +0 -0
  91. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/conftest.py +0 -0
  92. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/__init__.py +0 -0
  93. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/__init__.py +0 -0
  94. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/__init__.py +0 -0
  95. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_command_structure_errors.py +0 -0
  96. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_file_access_errors.py +0 -0
  97. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_format_output_errors.py +0 -0
  98. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_input_validation_errors.py +0 -0
  99. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_missing_fields_validation.py +0 -0
  100. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_rating_validation.py +0 -0
  101. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/error_handling/test_year_validation.py +0 -0
  102. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/__init__.py +0 -0
  103. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/test_basic.py +0 -0
  104. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/test_comprehensive.py +0 -0
  105. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/test_formats.py +0 -0
  106. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/test_metadata_content.py +0 -0
  107. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/test_multiple_files.py +0 -0
  108. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/test_options.py +0 -0
  109. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/read/test_unified.py +0 -0
  110. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/test_delete.py +0 -0
  111. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/test_formatting.py +0 -0
  112. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/test_help.py +0 -0
  113. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/__init__.py +0 -0
  114. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_basic.py +0 -0
  115. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_comprehensive.py +0 -0
  116. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_force_format.py +0 -0
  117. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_integer_fields.py +0 -0
  118. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_list_fields.py +0 -0
  119. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_rating.py +0 -0
  120. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_string_fields.py +0 -0
  121. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/cli/write/test_validation.py +0 -0
  122. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
  123. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +0 -0
  124. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/workflows/__init__.py +0 -0
  125. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/workflows/test_core_workflows.py +0 -0
  126. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +0 -0
  127. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +0 -0
  128. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +0 -0
  129. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/e2e/workflows/test_rating_workflows.py +0 -0
  130. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/__init__.py +0 -0
  131. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/__init__.py +0 -0
  132. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
  133. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +0 -0
  134. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +0 -0
  135. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +0 -0
  136. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +0 -0
  137. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
  138. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +0 -0
  139. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +0 -0
  140. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +0 -0
  141. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +0 -0
  142. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
  143. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +0 -0
  144. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +0 -0
  145. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +0 -0
  146. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +0 -0
  147. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/conftest.py +0 -0
  148. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/delete_all_metadata/__init__.py +0 -0
  149. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +0 -0
  150. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_header_deletion.py +0 -0
  151. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +0 -0
  152. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +0 -0
  153. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/encoding/__init__.py +0 -0
  154. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/encoding/test_encoding.py +0 -0
  155. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +0 -0
  156. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
  157. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/options/__init__.py +0 -0
  158. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/options/test_include_headers.py +0 -0
  159. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/options/test_include_technical.py +0 -0
  160. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_audio_formats.py +0 -0
  161. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_consistency.py +0 -0
  162. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_edge_cases.py +0 -0
  163. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_error_handling.py +0 -0
  164. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +0 -0
  165. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_performance.py +0 -0
  166. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_raw_metadata_includes_unsupported_tags.py +0 -0
  167. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/get_full_metadata/test_riff_bext.py +0 -0
  168. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
  169. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
  170. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album/test_deleting.py +0 -0
  171. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album/test_reading.py +0 -0
  172. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album/test_writing.py +0 -0
  173. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
  174. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +0 -0
  175. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +0 -0
  176. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +0 -0
  177. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
  178. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +0 -0
  179. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/artists/test_reading.py +0 -0
  180. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/artists/test_writing.py +0 -0
  181. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
  182. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +0 -0
  183. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +0 -0
  184. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +0 -0
  185. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
  186. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +0 -0
  187. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/comment/test_reading.py +0 -0
  188. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/comment/test_writing.py +0 -0
  189. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
  190. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +0 -0
  191. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/composer/test_reading.py +0 -0
  192. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/composer/test_writing.py +0 -0
  193. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
  194. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +0 -0
  195. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +0 -0
  196. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +0 -0
  197. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/description/__init__.py +0 -0
  198. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/description/test_deleting.py +0 -0
  199. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/description/test_reading.py +0 -0
  200. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/description/test_writing.py +0 -0
  201. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/disc_number/__init__.py +0 -0
  202. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/disc_number/test_deleting.py +0 -0
  203. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/disc_number/test_reading.py +0 -0
  204. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/field_not_supported/__init__.py +0 -0
  205. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +0 -0
  206. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +0 -0
  207. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +0 -0
  208. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/__init__.py +0 -0
  209. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/reading/__init__.py +0 -0
  210. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/__init__.py +0 -0
  211. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v1_reading.py +0 -0
  212. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v2_reading.py +0 -0
  213. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_riff_reading.py +0 -0
  214. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_vorbis_reading.py +0 -0
  215. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +0 -0
  216. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +0 -0
  217. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/genre/test_writing.py +0 -0
  218. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/isrc/__init__.py +0 -0
  219. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/isrc/test_deleting.py +0 -0
  220. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/isrc/test_reading.py +0 -0
  221. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/isrc/test_writing.py +0 -0
  222. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/language/__init__.py +0 -0
  223. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/language/test_deleting.py +0 -0
  224. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/language/test_reading.py +0 -0
  225. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/language/test_writing.py +0 -0
  226. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/lyrics/__init__.py +0 -0
  227. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +0 -0
  228. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +0 -0
  229. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +0 -0
  230. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/__init__.py +0 -0
  231. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/test_deleting.py +0 -0
  232. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/test_reading.py +0 -0
  233. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/test_writing.py +0 -0
  234. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/__init__.py +0 -0
  235. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/test_deleting.py +0 -0
  236. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/test_reading.py +0 -0
  237. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/test_writing.py +0 -0
  238. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/originator/__init__.py +0 -0
  239. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/originator/test_deleting.py +0 -0
  240. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/originator/test_reading.py +0 -0
  241. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/originator/test_writing.py +0 -0
  242. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/publisher/__init__.py +0 -0
  243. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +0 -0
  244. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +0 -0
  245. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +0 -0
  246. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/__init__.py +0 -0
  247. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/reading/__init__.py +0 -0
  248. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_100_proportional.py +0 -0
  249. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_non_proportional.py +0 -0
  250. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_proportional.py +0 -0
  251. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +0 -0
  252. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +0 -0
  253. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/writing/__init__.py +0 -0
  254. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/__init__.py +0 -0
  255. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_id3v2.py +0 -0
  256. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_riff.py +0 -0
  257. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_vorbis.py +0 -0
  258. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +0 -0
  259. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/release_date/__init__.py +0 -0
  260. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +0 -0
  261. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +0 -0
  262. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +0 -0
  263. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +0 -0
  264. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +0 -0
  265. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/title/__init__.py +0 -0
  266. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/title/test_deleting.py +0 -0
  267. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +0 -0
  268. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/title/test_reading.py +0 -0
  269. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/title/test_writing.py +0 -0
  270. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/track_number/__init__.py +0 -0
  271. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/track_number/reading/__init__.py +0 -0
  272. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_edge_cases.py +0 -0
  273. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_metadata_format.py +0 -0
  274. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +0 -0
  275. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +0 -0
  276. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/__init__.py +0 -0
  277. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/__init__.py +0 -0
  278. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +0 -0
  279. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +0 -0
  280. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_3.py +0 -0
  281. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_4.py +0 -0
  282. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +0 -0
  283. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +0 -0
  284. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +0 -0
  285. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +0 -0
  286. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +0 -0
  287. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/__init__.py +0 -0
  288. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +0 -0
  289. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +0 -0
  290. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_3.py +0 -0
  291. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_4.py +0 -0
  292. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +0 -0
  293. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +0 -0
  294. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +0 -0
  295. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +0 -0
  296. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/reading/__init__.py +0 -0
  297. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +0 -0
  298. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/reading/test_reading_error_handling.py +0 -0
  299. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/real_audio_files/__init__.py +0 -0
  300. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/real_audio_files/test_reading.py +0 -0
  301. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/real_audio_files/test_writing.py +0 -0
  302. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/__init__.py +0 -0
  303. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/__init__.py +0 -0
  304. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +0 -0
  305. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/__init__.py +0 -0
  306. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_audio_data_corruption.py +0 -0
  307. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_file.py +0 -0
  308. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/__init__.py +0 -0
  309. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_validation_works_without_id3v1.py +0 -0
  310. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_unset_md5.py +0 -0
  311. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/__init__.py +0 -0
  312. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_delete_original.py +0 -0
  313. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/__init__.py +0 -0
  314. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/test_partial_md5.py +0 -0
  315. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/test_random_md5.py +0 -0
  316. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_non_flac_error.py +0 -0
  317. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_unset_md5.py +0 -0
  318. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/test_channels.py +0 -0
  319. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +0 -0
  320. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/technical_info/test_sample_rate.py +0 -0
  321. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/test_audio_file.py +0 -0
  322. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/test_audio_format_readable_after_update_all_metadata_formats.py +0 -0
  323. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/__init__.py +0 -0
  324. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/test_error_handling.py +0 -0
  325. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/test_forced_format.py +0 -0
  326. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +0 -0
  327. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/test_partial_update.py +0 -0
  328. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/__init__.py +0 -0
  329. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/__init__.py +0 -0
  330. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/test_flac_sync.py +0 -0
  331. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/test_mp3_sync.py +0 -0
  332. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/test_wav_sync.py +0 -0
  333. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +0 -0
  334. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +0 -0
  335. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/__init__.py +0 -0
  336. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_fail_behavior.py +0 -0
  337. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_no_writing_on_failure.py +0 -0
  338. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_strategy_specific.py +0 -0
  339. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/__init__.py +0 -0
  340. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/__init__.py +0 -0
  341. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/__init__.py +0 -0
  342. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +0 -0
  343. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +0 -0
  344. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/test_duration_in_sec.py +0 -0
  345. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +0 -0
  346. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +0 -0
  347. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +0 -0
  348. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +0 -0
  349. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/test_context_manager.py +0 -0
  350. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/test_file_validation.py +0 -0
  351. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/test_is_audio_file.py +0 -0
  352. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/test_operations.py +0 -0
  353. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/audio_file/test_path_handling.py +0 -0
  354. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/cli/__init__.py +0 -0
  355. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/cli/test_cli_colorize.py +0 -0
  356. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/cli/test_expand_file_patterns.py +0 -0
  357. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/__init__.py +0 -0
  358. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/conftest.py +0 -0
  359. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/header_info/__init__.py +0 -0
  360. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +0 -0
  361. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +0 -0
  362. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +0 -0
  363. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +0 -0
  364. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/__init__.py +0 -0
  365. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/disc_number/__init__.py +0 -0
  366. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/disc_number/test_disc_number_validation.py +0 -0
  367. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/isrc/__init__.py +0 -0
  368. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/isrc/test_isrc_format_validation.py +0 -0
  369. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/isrc/test_isrc_type_validation.py +0 -0
  370. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/__init__.py +0 -0
  371. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/__init__.py +0 -0
  372. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/test_smart_parsing.py +0 -0
  373. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/__init__.py +0 -0
  374. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_separator_selection.py +0 -0
  375. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_value_filtering.py +0 -0
  376. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_artistid/__init__.py +0 -0
  377. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_artistid/test_musicbrainz_artistid_format_validation.py +0 -0
  378. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_artistid/test_musicbrainz_artistid_type_validation.py +0 -0
  379. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_trackid/__init__.py +0 -0
  380. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_trackid/test_musicbrainz_trackid_format_validation.py +0 -0
  381. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_trackid/test_musicbrainz_trackid_type_validation.py +0 -0
  382. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_uuid/__init__.py +0 -0
  383. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_uuid/test_uuid_format_validation.py +0 -0
  384. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/__init__.py +0 -0
  385. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/__init__.py +0 -0
  386. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_normalization.py +0 -0
  387. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_profiles_values.py +0 -0
  388. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/test_rating_validation.py +0 -0
  389. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
  390. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_configuration_error.py +0 -0
  391. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_validation.py +0 -0
  392. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_writing_profiles.py +0 -0
  393. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/release_date/__init__.py +0 -0
  394. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/release_date/test_date_format_validation.py +0 -0
  395. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_type_validation_exception.py +0 -0
  396. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +0 -0
  397. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/track_number/__init__.py +0 -0
  398. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/metadata_field/track_number/test_track_number_validation.py +0 -0
  399. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/test_metadata_format_managers_write_and_read.py +0 -0
  400. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/metadata_managers/test_riff_configuration_error.py +0 -0
  401. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/test_get_supported_unified_metadata_field_ids.py +0 -0
  402. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/utils/__init__.py +0 -0
  403. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/utils/test_disc_number_read.py +0 -0
  404. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/utils/test_raw_metadata_sanitizer.py +0 -0
  405. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/test/tests/unit/utils/test_unified_metadata_field_schema.py +0 -0
  406. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/__init__.py +0 -0
  407. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/disc_number_read.py +0 -0
  408. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/id3v1_genre_code_map.py +0 -0
  409. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/mutagen_exception_handler.py +0 -0
  410. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/os_dependencies_checker/__init__.py +0 -0
  411. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/os_dependencies_checker/config.py +0 -0
  412. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/os_dependencies_checker/macos.py +0 -0
  413. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/os_dependencies_checker/windows.py +0 -0
  414. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/rating_profiles.py +0 -0
  415. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/raw_metadata_sanitizer.py +0 -0
  416. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/tool_path_resolver.py +0 -0
  417. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa/utils/unified_metadata_field_schema.py +0 -0
  418. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa_python.egg-info/SOURCES.txt +0 -0
  419. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa_python.egg-info/dependency_links.txt +0 -0
  420. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa_python.egg-info/entry_points.txt +0 -0
  421. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/audiometa_python.egg-info/top_level.txt +0 -0
  422. {audiometa_python-1.4.2 → audiometa_python-1.4.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: audiometa-python
3
- Version: 1.4.2
3
+ Version: 1.4.3
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>
@@ -27,7 +27,7 @@ Provides-Extra: dev
27
27
  Requires-Dist: pytest==9.0.1; extra == "dev"
28
28
  Requires-Dist: pytest-cov==4.0.0; extra == "dev"
29
29
  Requires-Dist: pytest-mock==3.15.1; extra == "dev"
30
- Requires-Dist: ruff==0.6.9; extra == "dev"
30
+ Requires-Dist: ruff==0.15.9; extra == "dev"
31
31
  Requires-Dist: isort==5.13.2; extra == "dev"
32
32
  Requires-Dist: mypy==1.18.2; extra == "dev"
33
33
  Requires-Dist: pre-commit==3.0.0; extra == "dev"
@@ -38,35 +38,35 @@ from .utils.unified_metadata_field_schema import get_unified_metadata_field_sche
38
38
  from .utils.unified_metadata_key import UnifiedMetadataKey
39
39
 
40
40
  __all__ = [
41
- "UnifiedMetadataKey",
42
- "get_unified_metadata_field_schema",
43
- "get_supported_unified_metadata_field_ids",
44
- "FlacMd5State",
45
- "MetadataFormat",
46
- "MetadataWritingStrategy",
47
- "UnifiedMetadata",
48
- "UnifiedMetadataValue",
49
41
  "FileCorruptedError",
50
42
  "FileTypeNotSupportedError",
43
+ "FlacMd5State",
51
44
  "InvalidMetadataFieldTypeError",
52
45
  "MetadataFieldNotSupportedByLibError",
53
46
  "MetadataFieldNotSupportedByMetadataFormatError",
47
+ "MetadataFormat",
54
48
  "MetadataFormatNotSupportedByAudioFormatError",
55
49
  "MetadataWritingConflictParametersError",
56
- "get_unified_metadata",
57
- "get_unified_metadata_field",
58
- "validate_metadata_for_update",
59
- "update_metadata",
50
+ "MetadataWritingStrategy",
51
+ "UnifiedMetadata",
52
+ "UnifiedMetadataKey",
53
+ "UnifiedMetadataValue",
60
54
  "delete_all_metadata",
55
+ "fix_md5_checking",
61
56
  "get_bitrate",
62
57
  "get_channels",
58
+ "get_duration_in_sec",
63
59
  "get_file_size",
60
+ "get_full_metadata",
64
61
  "get_sample_rate",
62
+ "get_supported_unified_metadata_field_ids",
63
+ "get_unified_metadata",
64
+ "get_unified_metadata_field",
65
+ "get_unified_metadata_field_schema",
65
66
  "is_audio_file",
66
- "get_duration_in_sec",
67
67
  "is_flac_md5_valid",
68
- "fix_md5_checking",
69
- "get_full_metadata",
68
+ "update_metadata",
69
+ "validate_metadata_for_update",
70
70
  ]
71
71
 
72
72
  FILE_EXTENSION_NOT_HANDLED_MESSAGE = "The file's format is not handled by the service."
@@ -124,7 +124,10 @@ def _get_metadata_manager(
124
124
  if not metadata_format:
125
125
  metadata_format = audio_file_prioritized_tag_formats[0]
126
126
  elif metadata_format not in audio_file_prioritized_tag_formats:
127
- msg = f"Tag format {metadata_format} not supported for file extension {audio_file.file_extension}"
127
+ msg = (
128
+ f"Tag format {metadata_format.qualified_name()} not supported for file extension "
129
+ f"{audio_file.file_extension}"
130
+ )
128
131
  raise MetadataFormatNotSupportedByAudioFormatError(msg)
129
132
 
130
133
  manager_class: type[_MetadataManager] = cast(Any, METADATA_FORMAT_MANAGER_CLASS_MAP[metadata_format])
@@ -901,7 +904,9 @@ def _handle_metadata_strategy(
901
904
  except MetadataFieldNotSupportedByMetadataFormatError as e:
902
905
  # For SYNC strategy, log warning but continue with other formats
903
906
  if warn_on_unsupported_field:
904
- format_warn_msg = f"Format {target_format_actual} doesn't support some metadata fields: {e}"
907
+ format_warn_msg = (
908
+ f"Format {target_format_actual.qualified_name()} doesn't support some metadata fields: {e}"
909
+ )
905
910
  warnings.warn(format_warn_msg, stacklevel=2)
906
911
  except Exception as e:
907
912
  # Re-raise user errors (like InvalidRatingValueError) immediately
@@ -7,7 +7,7 @@ import tempfile
7
7
  import types
8
8
  import warnings
9
9
  from pathlib import Path
10
- from typing import cast
10
+ from typing import Self, cast
11
11
 
12
12
  from mutagen.flac import FLAC, StreamInfo
13
13
  from mutagen.mp3 import MP3
@@ -251,7 +251,7 @@ class _AudioFile:
251
251
  if hasattr(self.file, "close"):
252
252
  self.file.close()
253
253
 
254
- def __enter__(self) -> "_AudioFile":
254
+ def __enter__(self) -> Self:
255
255
  return self
256
256
 
257
257
  def __exit__(
@@ -368,7 +368,7 @@ class _AudioFile:
368
368
  )
369
369
 
370
370
  # Create a temporary file to store the corrected FLAC content
371
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".flac")
371
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=".flac") # noqa: SIM115
372
372
  temp_path = temp_file.name
373
373
  temp_file.close() # Close but don't delete yet
374
374
 
@@ -251,8 +251,7 @@ class _MetadataManager:
251
251
 
252
252
  raise InvalidMetadataFieldFormatError(
253
253
  UnifiedMetadataKey.ISRC.value,
254
- "12 alphanumeric characters (e.g., 'USRC17607839') or 15 characters with hyphens "
255
- "(e.g., 'US-RC1-76-07839')",
254
+ "12 alphanumeric characters (e.g., 'USRC17607839') or 15 characters with hyphens (e.g., 'US-RC1-76-07839')",
256
255
  isrc,
257
256
  )
258
257
 
@@ -660,7 +659,7 @@ class _MetadataManager:
660
659
  def get_unified_metadata_field(self, unified_metadata_key: UnifiedMetadataKey) -> UnifiedMetadataValue:
661
660
  if unified_metadata_key not in self.metadata_keys_direct_map_read:
662
661
  metadata_format_name = self._get_formatted_metadata_format_name()
663
- msg = f"{unified_metadata_key} metadata not supported by {metadata_format_name} format"
662
+ msg = f"{unified_metadata_key.qualified_name()} metadata not supported by {metadata_format_name} format"
664
663
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
665
664
 
666
665
  if self.raw_clean_metadata_uppercase_keys is None:
@@ -852,7 +851,10 @@ class _MetadataManager:
852
851
 
853
852
  if unified_metadata_key not in self.metadata_keys_direct_map_write:
854
853
  metadata_format_name = self._get_formatted_metadata_format_name()
855
- msg = f"{unified_metadata_key} metadata not supported by {metadata_format_name} format"
854
+ msg = (
855
+ f"{unified_metadata_key.qualified_name()} metadata not supported by "
856
+ f"{metadata_format_name} format"
857
+ )
856
858
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
857
859
  raw_metadata_key = self.metadata_keys_direct_map_write[unified_metadata_key]
858
860
  if raw_metadata_key:
@@ -212,7 +212,9 @@ class _RatingSupportingMetadataManager(_MetadataManager):
212
212
  or UnifiedMetadataKey.RATING not in self.metadata_keys_direct_map_write
213
213
  ):
214
214
  metadata_format_name = self._get_formatted_metadata_format_name()
215
- msg = f"{UnifiedMetadataKey.RATING} metadata not supported by {metadata_format_name} format"
215
+ msg = (
216
+ f"{UnifiedMetadataKey.RATING.qualified_name()} metadata not supported by {metadata_format_name} format"
217
+ )
216
218
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
217
219
 
218
220
  # Validate rating value before processing
@@ -426,7 +426,7 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
426
426
  return None
427
427
  tpos_str = str(tpos_value[0])
428
428
  return parse_disc_total_from_combined_str(tpos_str)
429
- msg = f"Metadata key not handled: {unified_metadata_key}"
429
+ msg = f"Metadata key not handled: {unified_metadata_key.qualified_name()}"
430
430
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
431
431
 
432
432
  def _update_formatted_value_in_raw_mutagen_metadata(
@@ -510,7 +510,7 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
510
510
  app_metadata_value = unified_metadata[unified_metadata_key]
511
511
  if unified_metadata_key not in self.metadata_keys_direct_map_write:
512
512
  metadata_format_name = self._get_formatted_metadata_format_name()
513
- msg = f"{unified_metadata_key} metadata not supported by {metadata_format_name} format"
513
+ msg = f"{unified_metadata_key.qualified_name()} metadata not supported by {metadata_format_name} format"
514
514
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
515
515
  raw_metadata_key = self.metadata_keys_direct_map_write[unified_metadata_key]
516
516
  if raw_metadata_key:
@@ -254,5 +254,5 @@ class _Id3v2Reader:
254
254
  """
255
255
  uuid_hex_length = 32
256
256
  if len(uuid_str) == uuid_hex_length and all(c in "0123456789abcdefABCDEF" for c in uuid_str):
257
- return f"{uuid_str[:8]}-{uuid_str[8:12]}-" f"{uuid_str[12:16]}-{uuid_str[16:20]}-{uuid_str[20:32]}"
257
+ return f"{uuid_str[:8]}-{uuid_str[8:12]}-{uuid_str[12:16]}-{uuid_str[16:20]}-{uuid_str[20:32]}"
258
258
  return uuid_str
@@ -6,6 +6,7 @@ from mutagen.id3 import ID3
6
6
  from mutagen.id3._frames import TPOS, TXXX, UFID
7
7
 
8
8
  from audiometa.manager._MetadataManager import _MetadataManager as MetadataManager
9
+ from audiometa.utils.disc_number_read import parse_disc_number_from_combined_str, parse_disc_total_from_combined_str
9
10
  from audiometa.utils.types import RawMetadataKey, UnifiedMetadataValue
10
11
  from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
11
12
 
@@ -285,11 +286,7 @@ class _Id3v2Writer:
285
286
  current_total = None
286
287
  if current_tpos and len(current_tpos.text) > 0:
287
288
  tpos_str = str(current_tpos.text[0])
288
- import re
289
-
290
- match = re.match(r"^(\d+)/(\d+)$", tpos_str)
291
- if match:
292
- current_total = int(match.group(2))
289
+ current_total = parse_disc_total_from_combined_str(tpos_str)
293
290
 
294
291
  raw_mutagen_metadata.delall(tpos_key)
295
292
  if app_metadata_value is not None:
@@ -304,11 +301,7 @@ class _Id3v2Writer:
304
301
  current_disc_number = None
305
302
  if current_tpos and len(current_tpos.text) > 0:
306
303
  tpos_str = str(current_tpos.text[0])
307
- import re
308
-
309
- match = re.match(r"^(\d+)(?:/(\d+))?$", tpos_str)
310
- if match:
311
- current_disc_number = int(match.group(1))
304
+ current_disc_number = parse_disc_number_from_combined_str(tpos_str)
312
305
 
313
306
  raw_mutagen_metadata.delall(tpos_key)
314
307
  if app_metadata_value is not None:
@@ -307,7 +307,7 @@ class _RiffManager(_RatingSupportingMetadataManager):
307
307
  except Exception:
308
308
  pass
309
309
  return None
310
- msg = f"Metadata key not handled: {unified_metadata_key}"
310
+ msg = f"Metadata key not handled: {unified_metadata_key.qualified_name()}"
311
311
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
312
312
 
313
313
  def _update_not_using_mutagen_metadata(self, unified_metadata: UnifiedMetadata) -> None:
@@ -344,7 +344,7 @@ class _RiffManager(_RatingSupportingMetadataManager):
344
344
 
345
345
  for unified_metadata_key in unified_metadata:
346
346
  if unified_metadata_key not in self.metadata_keys_direct_map_write:
347
- msg = f"{unified_metadata_key} metadata not supported by RIFF format"
347
+ msg = f"{unified_metadata_key.qualified_name()} metadata not supported by RIFF format"
348
348
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
349
349
 
350
350
  def _read_file_data_for_update(self) -> tuple[bytearray, bool]:
@@ -388,6 +388,32 @@ class _VorbisManager(_RatingSupportingMetadataManager):
388
388
  # Get current metadata
389
389
  current_metadata = self._extract_mutagen_metadata()
390
390
 
391
+ # Preserve total when existing DISCNUMBER is stored as combined n/m or n-m and only DISC_NUMBER is updated.
392
+ if (
393
+ UnifiedMetadataKey.DISC_NUMBER in unified_metadata
394
+ and UnifiedMetadataKey.DISC_TOTAL not in unified_metadata
395
+ and unified_metadata[UnifiedMetadataKey.DISC_NUMBER] is not None
396
+ ):
397
+ explicit_total = None
398
+ combined_discnumber = None
399
+ for raw_key, raw_values in current_metadata.items():
400
+ key_name = str(raw_key).upper()
401
+ if raw_values is None or len(raw_values) == 0 or raw_values[0] in (None, ""):
402
+ continue
403
+ if key_name == self.VorbisKey.DISC_TOTAL.value:
404
+ explicit_total = str(raw_values[0])
405
+ elif key_name == self.VorbisKey.DISC_NUMBER.value:
406
+ combined_discnumber = str(raw_values[0])
407
+
408
+ explicit_total_is_usable = (
409
+ explicit_total is not None and parse_explicit_non_negative_disctotal(explicit_total) is not None
410
+ )
411
+
412
+ if not explicit_total_is_usable and combined_discnumber is not None:
413
+ parsed_total = parse_disc_total_from_combined_str(combined_discnumber)
414
+ if parsed_total is not None:
415
+ unified_metadata[UnifiedMetadataKey.DISC_TOTAL] = parsed_total
416
+
391
417
  # Update metadata dict
392
418
  for unified_metadata_key in list(unified_metadata.keys()):
393
419
  app_metadata_value = unified_metadata[unified_metadata_key]
@@ -401,7 +427,7 @@ class _VorbisManager(_RatingSupportingMetadataManager):
401
427
 
402
428
  if unified_metadata_key not in self.metadata_keys_direct_map_write:
403
429
  metadata_format_name = self._get_formatted_metadata_format_name()
404
- msg = f"{unified_metadata_key} metadata not supported by {metadata_format_name} format"
430
+ msg = f"{unified_metadata_key.qualified_name()} metadata not supported by {metadata_format_name} format"
405
431
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
406
432
  raw_metadata_key = self.metadata_keys_direct_map_write[unified_metadata_key]
407
433
  if raw_metadata_key:
@@ -563,7 +589,7 @@ class _VorbisManager(_RatingSupportingMetadataManager):
563
589
  def _get_undirectly_mapped_metadata_value_other_than_rating_from_raw_clean_metadata(
564
590
  self, _raw_clean_metadata: RawMetadataDict, unified_metadata_key: UnifiedMetadataKey
565
591
  ) -> UnifiedMetadataValue:
566
- msg = f"Metadata key not handled: {unified_metadata_key}"
592
+ msg = f"Metadata key not handled: {unified_metadata_key.qualified_name()}"
567
593
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
568
594
 
569
595
  def _update_undirectly_mapped_metadata(
@@ -600,5 +626,5 @@ class _VorbisManager(_RatingSupportingMetadataManager):
600
626
  if self.VorbisKey.RATING_TRAKTOR in raw_mutagen_metadata:
601
627
  del raw_mutagen_metadata[self.VorbisKey.RATING_TRAKTOR]
602
628
  else:
603
- msg = f"Metadata key not handled: {unified_metadata_key}"
629
+ msg = f"Metadata key not handled: {unified_metadata_key.qualified_name()}"
604
630
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
@@ -161,7 +161,7 @@ class _Id3v1Manager(_MetadataManager):
161
161
  raw_clean_metadata=raw_clean_metadata_uppercase_keys,
162
162
  raw_metadata_ket=Id3v1RawMetadataKey.GENRE_CODE_OR_NAME,
163
163
  )
164
- msg = f"{unified_metadata_key} metadata is not undirectly handled"
164
+ msg = f"{unified_metadata_key.qualified_name()} metadata is not undirectly handled"
165
165
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
166
166
 
167
167
  def _update_undirectly_mapped_metadata(
@@ -187,7 +187,7 @@ class _Id3v1Manager(_MetadataManager):
187
187
  if genre_code is not None:
188
188
  tags[Id3v1RawMetadataKey.GENRE_CODE_OR_NAME] = [str(genre_code)]
189
189
  else:
190
- msg = f"{unified_metadata_key} metadata is not undirectly handled"
190
+ msg = f"{unified_metadata_key.qualified_name()} metadata is not undirectly handled"
191
191
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
192
192
 
193
193
  def _update_formatted_value_in_raw_mutagen_metadata(
@@ -204,8 +204,7 @@ class _Id3v1Manager(_MetadataManager):
204
204
 
205
205
  # If value is None, remove the field (delete from tags)
206
206
  if app_metadata_value is None:
207
- if raw_metadata_key in tags:
208
- del tags[raw_metadata_key]
207
+ tags.pop(raw_metadata_key, None)
209
208
  return
210
209
 
211
210
  # Convert and truncate the value according to ID3v1 constraints
@@ -258,7 +257,7 @@ class _Id3v1Manager(_MetadataManager):
258
257
  for unified_metadata_key in unified_metadata:
259
258
  if unified_metadata_key not in self.metadata_keys_direct_map_write:
260
259
  metadata_format_name = self._get_formatted_metadata_format_name()
261
- msg = f"{unified_metadata_key} metadata not supported by {metadata_format_name} format"
260
+ msg = f"{unified_metadata_key.qualified_name()} metadata not supported by {metadata_format_name} format"
262
261
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
263
262
 
264
263
  # Read the entire file
@@ -5,4 +5,4 @@ from .id3v1_metadata_deleter import ID3v1MetadataDeleter
5
5
  from .id3v1_metadata_getter import ID3v1MetadataGetter
6
6
  from .id3v1_metadata_setter import ID3v1MetadataSetter
7
7
 
8
- __all__ = ["ID3v1MetadataDeleter", "ID3v1MetadataSetter", "ID3v1HeaderVerifier", "ID3v1MetadataGetter"]
8
+ __all__ = ["ID3v1HeaderVerifier", "ID3v1MetadataDeleter", "ID3v1MetadataGetter", "ID3v1MetadataSetter"]
@@ -15,14 +15,10 @@ from .id3v2_metadata_setter import ID3v2MetadataSetter
15
15
 
16
16
 
17
17
  __all__ = [
18
- # Core operations
18
+ "ExternalMetadataToolError",
19
19
  "ID3v2HeaderVerifier",
20
20
  "ID3v2MetadataDeleter",
21
- "ID3v2MetadataSetter",
22
21
  "ID3v2MetadataGetter",
23
- # Specialized managers (moved to ID3v2MetadataSetter)
24
- # Advanced tools
22
+ "ID3v2MetadataSetter",
25
23
  "ManualID3v2FrameCreator",
26
- # External tool wrappers
27
- "ExternalMetadataToolError",
28
24
  ]
@@ -5,4 +5,4 @@ from .riff_metadata_deleter import RIFFMetadataDeleter
5
5
  from .riff_metadata_getter import RIFFMetadataGetter
6
6
  from .riff_metadata_setter import RIFFMetadataSetter
7
7
 
8
- __all__ = ["RIFFMetadataGetter", "RIFFHeaderVerifier", "RIFFMetadataDeleter", "RIFFMetadataSetter"]
8
+ __all__ = ["RIFFHeaderVerifier", "RIFFMetadataDeleter", "RIFFMetadataGetter", "RIFFMetadataSetter"]
@@ -5,4 +5,4 @@ from .vorbis_metadata_deleter import VorbisMetadataDeleter
5
5
  from .vorbis_metadata_getter import VorbisMetadataGetter
6
6
  from .vorbis_metadata_setter import VorbisMetadataSetter
7
7
 
8
- __all__ = ["VorbisMetadataGetter", "VorbisHeaderVerifier", "VorbisMetadataDeleter", "VorbisMetadataSetter"]
8
+ __all__ = ["VorbisHeaderVerifier", "VorbisMetadataDeleter", "VorbisMetadataGetter", "VorbisMetadataSetter"]
@@ -115,9 +115,9 @@ class TestCLIMultipleFilesErrors:
115
115
 
116
116
  # Should contain success messages for valid files
117
117
  stdout_output = result.stdout.lower()
118
- assert (
119
- "updated metadata for" in stdout_output
120
- ), f"Expected success message in stdout but got:\nSTDOUT: {result.stdout}\nSTDERR: {result.stderr}"
118
+ assert "updated metadata for" in stdout_output, (
119
+ f"Expected success message in stdout but got:\nSTDOUT: {result.stdout}\nSTDERR: {result.stderr}"
120
+ )
121
121
 
122
122
  # Should contain error message for unsupported file
123
123
  stderr_output = result.stderr.lower()
@@ -151,9 +151,9 @@ class TestCLIMultipleFilesErrors:
151
151
 
152
152
  # Should contain messages for processed files
153
153
  stdout_output = result.stdout.lower()
154
- assert (
155
- "deleted" in stdout_output or "found" in stdout_output
156
- ), f"Expected success message in stdout but got:\nSTDOUT: {result.stdout}\nSTDERR: {result.stderr}"
154
+ assert "deleted" in stdout_output or "found" in stdout_output, (
155
+ f"Expected success message in stdout but got:\nSTDOUT: {result.stdout}\nSTDERR: {result.stderr}"
156
+ )
157
157
 
158
158
  # Should contain error message for unsupported file
159
159
  stderr_output = result.stderr.lower()
@@ -51,14 +51,14 @@ class TestGetFullMetadataBinaryDataFiltering:
51
51
  for frame_id, frame_data in id3v2_frames.items():
52
52
  text = frame_data.get("text", "")
53
53
 
54
- assert not any(
55
- ord(c) < 32 and c not in "\t\n\r" for c in text
56
- ), f"Frame {frame_id} contains binary data in text: {text[:50]!r}"
54
+ assert not any(ord(c) < 32 and c not in "\t\n\r" for c in text), (
55
+ f"Frame {frame_id} contains binary data in text: {text[:50]!r}"
56
+ )
57
57
 
58
58
  if _is_binary_frame(frame_id):
59
- assert text.startswith(
60
- "<Binary data:"
61
- ), f"Binary frame {frame_id} should have placeholder text, got: {text}"
59
+ assert text.startswith("<Binary data:"), (
60
+ f"Binary frame {frame_id} should have placeholder text, got: {text}"
61
+ )
62
62
  assert text.endswith(" bytes>"), f"Binary frame {frame_id} should end with ' bytes>', got: {text}"
63
63
 
64
64
  def test_get_full_metadata_id3v2_binary_frames_sanitized(self, sample_mp3_file):
@@ -72,9 +72,9 @@ class TestGetFullMetadataBinaryDataFiltering:
72
72
  assert text.startswith("<Binary data:"), f"Binary frame {frame_id} should have placeholder text"
73
73
  assert text.endswith(" bytes>"), f"Binary frame {frame_id} should end with ' bytes>'"
74
74
  else:
75
- assert not any(
76
- ord(c) < 32 and c not in "\t\n\r" for c in text
77
- ), f"Text frame {frame_id} contains binary data: {text[:50]!r}"
75
+ assert not any(ord(c) < 32 and c not in "\t\n\r" for c in text), (
76
+ f"Text frame {frame_id} contains binary data: {text[:50]!r}"
77
+ )
78
78
 
79
79
  def test_get_full_metadata_vorbis_no_binary_data(self, sample_flac_file):
80
80
  """Test that get_full_metadata Vorbis comments don't contain binary data."""
@@ -86,9 +86,9 @@ class TestGetFullMetadataBinaryDataFiltering:
86
86
  assert isinstance(values, list), f"Vorbis comment {key} should be a list"
87
87
  for value in values:
88
88
  assert isinstance(value, str), f"Vorbis comment {key} value should be string"
89
- assert not any(
90
- ord(c) < 32 and c not in "\t\n\r" for c in value
91
- ), f"Vorbis comment {key} contains binary data: {value[:50]!r}"
89
+ assert not any(ord(c) < 32 and c not in "\t\n\r" for c in value), (
90
+ f"Vorbis comment {key} contains binary data: {value[:50]!r}"
91
+ )
92
92
 
93
93
  def test_get_full_metadata_vorbis_opaque_comment_sanitized(self):
94
94
  """TRAKTOR4 and other opaque Vorbis comment keys are replaced with size placeholder."""
@@ -133,9 +133,9 @@ class TestGetFullMetadataBinaryDataFiltering:
133
133
  for key, value in riff_fields.items():
134
134
  assert isinstance(value, str), f"RIFF field {key} should be string"
135
135
  # Check for binary data patterns
136
- assert not any(
137
- ord(c) < 32 and c not in "\t\n\r" for c in value
138
- ), f"RIFF field {key} contains binary data: {value[:50]!r}"
136
+ assert not any(ord(c) < 32 and c not in "\t\n\r" for c in value), (
137
+ f"RIFF field {key} contains binary data: {value[:50]!r}"
138
+ )
139
139
 
140
140
  def test_get_full_metadata_id3v1_no_binary_data(self, sample_mp3_file):
141
141
  """Test that get_full_metadata ID3v1 metadata doesn't contain binary data."""
@@ -147,9 +147,9 @@ class TestGetFullMetadataBinaryDataFiltering:
147
147
  for key, value in id3v1_fields.items():
148
148
  assert isinstance(value, str), f"ID3v1 field {key} should be string"
149
149
  # Check for binary data patterns
150
- assert not any(
151
- ord(c) < 32 and c not in "\t\n\r" for c in value
152
- ), f"ID3v1 field {key} contains binary data: {value[:50]!r}"
150
+ assert not any(ord(c) < 32 and c not in "\t\n\r" for c in value), (
151
+ f"ID3v1 field {key} contains binary data: {value[:50]!r}"
152
+ )
153
153
 
154
154
  def test_cli_output_no_binary_data(self, sample_mp3_file):
155
155
  """Test that CLI output doesn't contain binary data."""
@@ -92,9 +92,9 @@ class TestGetFullMetadataStructure:
92
92
 
93
93
  # If there are parsed fields, they should use UnifiedMetadataKey enum values as keys
94
94
  for key in parsed_fields:
95
- assert isinstance(
96
- key, UnifiedMetadataKey
97
- ), f"ID3v1 parsed_fields key {key} should be UnifiedMetadataKey enum, got {type(key)}"
95
+ assert isinstance(key, UnifiedMetadataKey), (
96
+ f"ID3v1 parsed_fields key {key} should be UnifiedMetadataKey enum, got {type(key)}"
97
+ )
98
98
  # Verify it's a valid UnifiedMetadataKey value
99
99
  assert key in UnifiedMetadataKey, f"ID3v1 parsed_fields key {key} is not a valid UnifiedMetadataKey"
100
100
 
@@ -138,9 +138,9 @@ class TestGetFullMetadataStructure:
138
138
  assert isinstance(key, str), f"ID3v1 parsed_fields key in CLI output should be string, got: {type(key)}"
139
139
 
140
140
  # Verify it's a valid UnifiedMetadataKey value
141
- assert key in [
142
- e.value for e in UnifiedMetadataKey
143
- ], f"ID3v1 parsed_fields key {key} is not a valid UnifiedMetadataKey value"
141
+ assert key in [e.value for e in UnifiedMetadataKey], (
142
+ f"ID3v1 parsed_fields key {key} is not a valid UnifiedMetadataKey value"
143
+ )
144
144
 
145
145
  def test_parsed_fields_consistency_across_formats(self, sample_mp3_file: Path):
146
146
  result = get_full_metadata(sample_mp3_file)
@@ -150,12 +150,12 @@ class TestGetFullMetadataStructure:
150
150
  # Check that all formats have the expected structure
151
151
  for metadata_format_name, format_data in raw_metadata.items():
152
152
  assert "parsed_fields" in format_data, f"Format {metadata_format_name} should have parsed_fields"
153
- assert isinstance(
154
- format_data["parsed_fields"], dict
155
- ), f"Format {metadata_format_name} parsed_fields should be a dictionary"
153
+ assert isinstance(format_data["parsed_fields"], dict), (
154
+ f"Format {metadata_format_name} parsed_fields should be a dictionary"
155
+ )
156
156
 
157
157
  # Check that parsed_fields values are strings (no binary data)
158
158
  for key, value in format_data["parsed_fields"].items():
159
- assert isinstance(
160
- value, str
161
- ), f"Format {metadata_format_name} parsed_fields value for {key} should be string, got {type(value)}"
159
+ assert isinstance(value, str), (
160
+ f"Format {metadata_format_name} parsed_fields value for {key} should be string, got {type(value)}"
161
+ )
@@ -1,7 +1,9 @@
1
1
  import pytest
2
2
 
3
3
  from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.test.helpers.id3v2.id3v2_metadata_setter import ID3v2MetadataSetter
4
5
  from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
6
+ from audiometa.test.helpers.vorbis.vorbis_metadata_setter import VorbisMetadataSetter
5
7
  from audiometa.utils.metadata_format import MetadataFormat
6
8
  from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
7
9
 
@@ -68,6 +70,34 @@ class TestDiscNumberWriting:
68
70
  assert disc_number == 1
69
71
  assert disc_total is None
70
72
 
73
+ def test_id3v2_update_disc_number_preserves_total_from_hyphen_tpos(self):
74
+ with temp_file_with_metadata({}, "mp3") as test_file:
75
+ ID3v2MetadataSetter.set_metadata(test_file, {"disc_number": "1-2"})
76
+
77
+ update_metadata(
78
+ test_file,
79
+ {UnifiedMetadataKey.DISC_NUMBER: 5},
80
+ metadata_format=MetadataFormat.ID3V2,
81
+ )
82
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
83
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
84
+ assert disc_number == 5
85
+ assert disc_total == 2
86
+
87
+ def test_id3v2_update_disc_total_preserves_disc_number_from_hyphen_tpos(self):
88
+ with temp_file_with_metadata({}, "mp3") as test_file:
89
+ ID3v2MetadataSetter.set_metadata(test_file, {"disc_number": "1-2"})
90
+
91
+ update_metadata(
92
+ test_file,
93
+ {UnifiedMetadataKey.DISC_TOTAL: 4},
94
+ metadata_format=MetadataFormat.ID3V2,
95
+ )
96
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
97
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
98
+ assert disc_number == 1
99
+ assert disc_total == 4
100
+
71
101
  def test_vorbis_disc_number_writes_separate_fields(self):
72
102
  with temp_file_with_metadata({}, "flac") as test_file:
73
103
  update_metadata(
@@ -80,6 +110,58 @@ class TestDiscNumberWriting:
80
110
  assert disc_number == 1
81
111
  assert disc_total == 2
82
112
 
113
+ @pytest.mark.parametrize(
114
+ "initial_disc_number",
115
+ ["1/2", "1-2"],
116
+ )
117
+ def test_vorbis_update_disc_number_preserves_total_from_combined_discnumber(self, initial_disc_number):
118
+ with temp_file_with_metadata({}, "flac") as test_file:
119
+ VorbisMetadataSetter.set_tag(test_file, "DISCNUMBER", initial_disc_number)
120
+
121
+ update_metadata(
122
+ test_file,
123
+ {UnifiedMetadataKey.DISC_NUMBER: 5},
124
+ metadata_format=MetadataFormat.VORBIS,
125
+ )
126
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
127
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
128
+ assert disc_number == 5
129
+ assert disc_total == 2
130
+
131
+ def test_vorbis_update_disc_number_preserves_explicit_total_when_conflicting(self):
132
+ with temp_file_with_metadata({}, "flac") as test_file:
133
+ VorbisMetadataSetter.set_tag(test_file, "DISCNUMBER", "1/3")
134
+ VorbisMetadataSetter.set_tag(test_file, "DISCTOTAL", "2")
135
+
136
+ update_metadata(
137
+ test_file,
138
+ {UnifiedMetadataKey.DISC_NUMBER: 5},
139
+ metadata_format=MetadataFormat.VORBIS,
140
+ )
141
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
142
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
143
+ assert disc_number == 5
144
+ assert disc_total == 2
145
+
146
+ @pytest.mark.parametrize(
147
+ "invalid_total",
148
+ ["bogus", "-1"],
149
+ )
150
+ def test_vorbis_update_disc_number_ignores_invalid_explicit_total_and_preserves_embedded(self, invalid_total):
151
+ with temp_file_with_metadata({}, "flac") as test_file:
152
+ VorbisMetadataSetter.set_tag(test_file, "DISCNUMBER", "1/2")
153
+ VorbisMetadataSetter.set_tag(test_file, "DISCTOTAL", invalid_total)
154
+
155
+ update_metadata(
156
+ test_file,
157
+ {UnifiedMetadataKey.DISC_NUMBER: 5},
158
+ metadata_format=MetadataFormat.VORBIS,
159
+ )
160
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
161
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
162
+ assert disc_number == 5
163
+ assert disc_total == 2
164
+
83
165
  def test_id3v2_disc_number_max_value_truncated(self):
84
166
  with temp_file_with_metadata({}, "mp3") as test_file:
85
167
  update_metadata(