audiometa-python 0.2.9__tar.gz → 0.3.0__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 (331) hide show
  1. {audiometa_python-0.2.9/audiometa_python.egg-info → audiometa_python-0.3.0}/PKG-INFO +1 -1
  2. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/__init__.py +15 -0
  3. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_MetadataManager.py +64 -1
  4. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/id3v2/_Id3v2Manager.py +85 -0
  5. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +15 -0
  6. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +2 -0
  7. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/vorbis/vorbis_metadata_setter.py +2 -0
  8. audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/disc_number/test_deleting.py +97 -0
  9. audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/disc_number/test_reading.py +92 -0
  10. audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/disc_number/test_writing.py +153 -0
  11. audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
  12. audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field/test_disc_number_validation.py +75 -0
  13. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/unified_metadata_key.py +4 -0
  14. {audiometa_python-0.2.9 → audiometa_python-0.3.0/audiometa_python.egg-info}/PKG-INFO +1 -1
  15. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa_python.egg-info/SOURCES.txt +5 -0
  16. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/pyproject.toml +1 -1
  17. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/LICENSE +0 -0
  18. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/README.md +0 -0
  19. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/__main__.py +0 -0
  20. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/_audio_file.py +0 -0
  21. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/cli.py +0 -0
  22. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/exceptions.py +0 -0
  23. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/__init__.py +0 -0
  24. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/_RatingSupportingMetadataManager.py +0 -0
  25. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/__init__.py +0 -0
  26. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/id3v2/__init__.py +0 -0
  27. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/id3v2/_id3v2_constants.py +0 -0
  28. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/riff/_RiffManager.py +0 -0
  29. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/riff/__init__.py +0 -0
  30. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/riff/_riff_constants.py +0 -0
  31. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/vorbis/__init__.py +0 -0
  32. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/_rating_supporting/vorbis/_vorbis_constants.py +0 -0
  33. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/id3v1/_Id3v1Manager.py +0 -0
  34. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/id3v1/__init__.py +0 -0
  35. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/id3v1/_constants.py +0 -0
  36. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/id3v1/id3v1_raw_metadata.py +0 -0
  37. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/manager/id3v1/id3v1_raw_metadata_key.py +0 -0
  38. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/__init__.py +0 -0
  39. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/assets/create_test_files.py +0 -0
  40. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/__init__.py +0 -0
  41. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/common/__init__.py +0 -0
  42. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/common/audio_file_creator.py +0 -0
  43. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/common/external_tool_runner.py +0 -0
  44. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v1/__init__.py +0 -0
  45. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v1/id3v1_header_verifier.py +0 -0
  46. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v1/id3v1_metadata_deleter.py +0 -0
  47. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v1/id3v1_metadata_getter.py +0 -0
  48. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v1/id3v1_metadata_setter.py +0 -0
  49. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v2/__init__.py +0 -0
  50. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v2/id3v2_frame_manual_creator.py +0 -0
  51. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v2/id3v2_header_verifier.py +0 -0
  52. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v2/id3v2_metadata_deleter.py +0 -0
  53. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/id3v2/id3v2_metadata_getter.py +0 -0
  54. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/riff/__init__.py +0 -0
  55. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/riff/riff_header_verifier.py +0 -0
  56. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/riff/riff_manual_metadata_creator.py +0 -0
  57. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/riff/riff_metadata_deleter.py +0 -0
  58. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/riff/riff_metadata_getter.py +0 -0
  59. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/riff/riff_metadata_setter.py +0 -0
  60. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/scripts/__init__.py +0 -0
  61. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/technical_info_inspector.py +0 -0
  62. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/temp_file_with_metadata.py +0 -0
  63. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/vorbis/__init__.py +0 -0
  64. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/vorbis/vorbis_header_verifier.py +0 -0
  65. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/vorbis/vorbis_metadata_deleter.py +0 -0
  66. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/helpers/vorbis/vorbis_metadata_getter.py +0 -0
  67. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/__init__.py +0 -0
  68. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/conftest.py +0 -0
  69. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/__init__.py +0 -0
  70. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/__init__.py +0 -0
  71. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/__init__.py +0 -0
  72. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_command_structure_errors.py +0 -0
  73. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_file_access_errors.py +0 -0
  74. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_format_output_errors.py +0 -0
  75. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_input_validation_errors.py +0 -0
  76. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_missing_fields_validation.py +0 -0
  77. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_multiple_files_errors.py +0 -0
  78. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_rating_validation.py +0 -0
  79. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/error_handling/test_year_validation.py +0 -0
  80. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/test_cli_delete.py +0 -0
  81. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/test_cli_formatting.py +0 -0
  82. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/test_cli_help.py +0 -0
  83. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/test_cli_read.py +0 -0
  84. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/test_cli_unified.py +0 -0
  85. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/cli/test_cli_write.py +0 -0
  86. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
  87. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +0 -0
  88. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/workflows/__init__.py +0 -0
  89. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/workflows/test_core_workflows.py +0 -0
  90. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +0 -0
  91. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +0 -0
  92. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +0 -0
  93. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/e2e/workflows/test_rating_workflows.py +0 -0
  94. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/__init__.py +0 -0
  95. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/__init__.py +0 -0
  96. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
  97. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +0 -0
  98. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +0 -0
  99. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +0 -0
  100. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +0 -0
  101. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
  102. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +0 -0
  103. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +0 -0
  104. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +0 -0
  105. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +0 -0
  106. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
  107. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +0 -0
  108. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +0 -0
  109. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +0 -0
  110. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/wav/test_wav_with_id3v2_tags.py +0 -0
  111. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +0 -0
  112. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/conftest.py +0 -0
  113. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/delete_all_metadata/__init__.py +0 -0
  114. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +0 -0
  115. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_header_deletion.py +0 -0
  116. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +0 -0
  117. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +0 -0
  118. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/encoding/__init__.py +0 -0
  119. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/encoding/test_encoding.py +0 -0
  120. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +0 -0
  121. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
  122. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +0 -0
  123. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +0 -0
  124. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata_edge_cases.py +0 -0
  125. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/get_full_metadata/test_options.py +0 -0
  126. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/get_full_metadata/test_parsed_fields_keys.py +0 -0
  127. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
  128. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
  129. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album/test_deleting.py +0 -0
  130. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album/test_reading.py +0 -0
  131. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album/test_writing.py +0 -0
  132. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
  133. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +0 -0
  134. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +0 -0
  135. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +0 -0
  136. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
  137. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +0 -0
  138. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/artists/test_reading.py +0 -0
  139. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/artists/test_writing.py +0 -0
  140. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
  141. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +0 -0
  142. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +0 -0
  143. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +0 -0
  144. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
  145. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +0 -0
  146. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/comment/test_reading.py +0 -0
  147. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/comment/test_writing.py +0 -0
  148. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
  149. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +0 -0
  150. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/composer/test_reading.py +0 -0
  151. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/composer/test_writing.py +0 -0
  152. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
  153. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +0 -0
  154. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +0 -0
  155. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +0 -0
  156. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/field_not_supported → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/disc_number}/__init__.py +0 -0
  157. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/genre → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/field_not_supported}/__init__.py +0 -0
  158. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +0 -0
  159. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +0 -0
  160. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +0 -0
  161. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/genre/reading → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/genre}/__init__.py +0 -0
  162. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/genre/reading}/__init__.py +0 -0
  163. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/language → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format}/__init__.py +0 -0
  164. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v1_reading.py +0 -0
  165. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v2_reading.py +0 -0
  166. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_riff_reading.py +0 -0
  167. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_vorbis_reading.py +0 -0
  168. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +0 -0
  169. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +0 -0
  170. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/genre/test_writing.py +0 -0
  171. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/lyrics → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/language}/__init__.py +0 -0
  172. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/language/test_deleting.py +0 -0
  173. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/language/test_reading.py +0 -0
  174. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/language/test_writing.py +0 -0
  175. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/publisher → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/lyrics}/__init__.py +0 -0
  176. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +0 -0
  177. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +0 -0
  178. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +0 -0
  179. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/rating → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/publisher}/__init__.py +0 -0
  180. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +0 -0
  181. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +0 -0
  182. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +0 -0
  183. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/rating/reading → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/rating}/__init__.py +0 -0
  184. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/rating/writing → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/rating/reading}/__init__.py +0 -0
  185. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_100_proportional.py +0 -0
  186. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_non_proportional.py +0 -0
  187. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_proportional.py +0 -0
  188. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +0 -0
  189. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +0 -0
  190. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/rating/writing}/__init__.py +0 -0
  191. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/release_date → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format}/__init__.py +0 -0
  192. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_id3v2.py +0 -0
  193. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_riff.py +0 -0
  194. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_vorbis.py +0 -0
  195. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +0 -0
  196. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/title → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/release_date}/__init__.py +0 -0
  197. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +0 -0
  198. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +0 -0
  199. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +0 -0
  200. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +0 -0
  201. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +0 -0
  202. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/track_number → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/title}/__init__.py +0 -0
  203. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/title/test_deleting.py +0 -0
  204. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +0 -0
  205. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/title/test_reading.py +0 -0
  206. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/title/test_writing.py +0 -0
  207. {audiometa_python-0.2.9/audiometa/test/tests/integration/metadata_field/track_number/reading → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/track_number}/__init__.py +0 -0
  208. {audiometa_python-0.2.9/audiometa/test/tests/integration/real_audio_files → audiometa_python-0.3.0/audiometa/test/tests/integration/metadata_field/track_number/reading}/__init__.py +0 -0
  209. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_edge_cases.py +0 -0
  210. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_metadata_format.py +0 -0
  211. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +0 -0
  212. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +0 -0
  213. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/__init__.py +0 -0
  214. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/__init__.py +0 -0
  215. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +0 -0
  216. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +0 -0
  217. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_3.py +0 -0
  218. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_4.py +0 -0
  219. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +0 -0
  220. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +0 -0
  221. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +0 -0
  222. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +0 -0
  223. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +0 -0
  224. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/__init__.py +0 -0
  225. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +0 -0
  226. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +0 -0
  227. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_3.py +0 -0
  228. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_4.py +0 -0
  229. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +0 -0
  230. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +0 -0
  231. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +0 -0
  232. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +0 -0
  233. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/reading/__init__.py +0 -0
  234. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +0 -0
  235. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/reading/test_reading_error_handling.py +0 -0
  236. {audiometa_python-0.2.9/audiometa/test/tests/integration/technical_info → audiometa_python-0.3.0/audiometa/test/tests/integration/real_audio_files}/__init__.py +0 -0
  237. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/real_audio_files/test_reading.py +0 -0
  238. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/real_audio_files/test_writing.py +0 -0
  239. {audiometa_python-0.2.9/audiometa/test/tests/integration/technical_info/flac_md5 → audiometa_python-0.3.0/audiometa/test/tests/integration/technical_info}/__init__.py +0 -0
  240. {audiometa_python-0.2.9/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5 → audiometa_python-0.3.0/audiometa/test/tests/integration/technical_info/flac_md5}/__init__.py +0 -0
  241. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +0 -0
  242. {audiometa_python-0.2.9/audiometa/test/tests/integration/writing → audiometa_python-0.3.0/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5}/__init__.py +0 -0
  243. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_audio_data_corruption.py +0 -0
  244. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_flipped_md5.py +0 -0
  245. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_non_flac_error.py +0 -0
  246. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_partial_md5.py +0 -0
  247. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_random_md5.py +0 -0
  248. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_unset_md5.py +0 -0
  249. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +0 -0
  250. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/test_bitrate.py +0 -0
  251. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/test_channels.py +0 -0
  252. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +0 -0
  253. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/technical_info/test_sample_rate.py +0 -0
  254. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/test_audio_file.py +0 -0
  255. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/test_audio_format_readable_after_update_all_metadata_formats.py +0 -0
  256. {audiometa_python-0.2.9/audiometa/test/tests/integration/writing/writing_strategies → audiometa_python-0.3.0/audiometa/test/tests/integration/writing}/__init__.py +0 -0
  257. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/test_error_handling.py +0 -0
  258. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/test_forced_format.py +0 -0
  259. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +0 -0
  260. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/test_partial_update.py +0 -0
  261. {audiometa_python-0.2.9/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields → audiometa_python-0.3.0/audiometa/test/tests/integration/writing/writing_strategies}/__init__.py +0 -0
  262. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +0 -0
  263. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +0 -0
  264. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/writing_strategies/test_sync_strategy.py +0 -0
  265. {audiometa_python-0.2.9/audiometa/test/tests/unit → audiometa_python-0.3.0/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields}/__init__.py +0 -0
  266. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_fail_behavior.py +0 -0
  267. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_no_writing_on_failure.py +0 -0
  268. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_strategy_specific.py +0 -0
  269. {audiometa_python-0.2.9/audiometa/test/tests/unit/audio_file → audiometa_python-0.3.0/audiometa/test/tests/unit}/__init__.py +0 -0
  270. {audiometa_python-0.2.9/audiometa/test/tests/unit/audio_file/technical_info → audiometa_python-0.3.0/audiometa/test/tests/unit/audio_file}/__init__.py +0 -0
  271. {audiometa_python-0.2.9/audiometa/test/tests/unit/cli → audiometa_python-0.3.0/audiometa/test/tests/unit/audio_file/technical_info}/__init__.py +0 -0
  272. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +0 -0
  273. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +0 -0
  274. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/technical_info/test_duration_in_sec.py +0 -0
  275. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +0 -0
  276. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +0 -0
  277. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +0 -0
  278. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +0 -0
  279. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/test_context_manager.py +0 -0
  280. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/test_file_validation.py +0 -0
  281. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/test_operations.py +0 -0
  282. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/audio_file/test_path_handling.py +0 -0
  283. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers → audiometa_python-0.3.0/audiometa/test/tests/unit/cli}/__init__.py +0 -0
  284. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/cli/test_expand_file_patterns.py +0 -0
  285. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/header_info → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers}/__init__.py +0 -0
  286. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/conftest.py +0 -0
  287. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/metadata_field → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/header_info}/__init__.py +0 -0
  288. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +0 -0
  289. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +0 -0
  290. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +0 -0
  291. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +0 -0
  292. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field}/__init__.py +0 -0
  293. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values}/__init__.py +0 -0
  294. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading}/__init__.py +0 -0
  295. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/test_smart_parsing.py +0 -0
  296. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/metadata_field/rating → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing}/__init__.py +0 -0
  297. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_separator_selection.py +0 -0
  298. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_value_filtering.py +0 -0
  299. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field/rating}/__init__.py +0 -0
  300. {audiometa_python-0.2.9/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing → audiometa_python-0.3.0/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading}/__init__.py +0 -0
  301. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_normalization.py +0 -0
  302. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_profiles_values.py +0 -0
  303. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/test_rating_validation.py +0 -0
  304. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_configuration_error.py +0 -0
  305. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_validation.py +0 -0
  306. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_writing_profiles.py +0 -0
  307. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_date_format_validation.py +0 -0
  308. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_track_number_validation.py +0 -0
  309. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_type_validation_exception.py +0 -0
  310. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +0 -0
  311. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/test_metadata_format_managers_write_and_read.py +0 -0
  312. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/test/tests/unit/metadata_managers/test_riff_configuration_error.py +0 -0
  313. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/__init__.py +0 -0
  314. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/id3v1_genre_code_map.py +0 -0
  315. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/metadata_format.py +0 -0
  316. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/metadata_writing_strategy.py +0 -0
  317. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/mutagen_exception_handler.py +0 -0
  318. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/os_dependencies_checker/__init__.py +0 -0
  319. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/os_dependencies_checker/base.py +0 -0
  320. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/os_dependencies_checker/config.py +0 -0
  321. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/os_dependencies_checker/macos.py +0 -0
  322. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/os_dependencies_checker/ubuntu.py +0 -0
  323. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/os_dependencies_checker/windows.py +0 -0
  324. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/rating_profiles.py +0 -0
  325. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/tool_path_resolver.py +0 -0
  326. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa/utils/types.py +0 -0
  327. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa_python.egg-info/dependency_links.txt +0 -0
  328. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa_python.egg-info/entry_points.txt +0 -0
  329. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa_python.egg-info/requires.txt +0 -0
  330. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/audiometa_python.egg-info/top_level.txt +0 -0
  331. {audiometa_python-0.2.9 → audiometa_python-0.3.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: audiometa-python
3
- Version: 0.2.9
3
+ Version: 0.3.0
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>
@@ -510,6 +510,21 @@ def validate_metadata_for_update(
510
510
  if isinstance(track_number_value, str | int):
511
511
  _MetadataManager.validate_track_number(track_number_value)
512
512
 
513
+ # Validate disc number if present and non-empty
514
+ if UnifiedMetadataKey.DISC_NUMBER in normalized_metadata:
515
+ disc_number_value = normalized_metadata[UnifiedMetadataKey.DISC_NUMBER]
516
+ if disc_number_value is not None:
517
+ from .manager._MetadataManager import _MetadataManager
518
+
519
+ _MetadataManager.validate_disc_number(disc_number_value)
520
+
521
+ # Validate disc total if present
522
+ if UnifiedMetadataKey.DISC_TOTAL in normalized_metadata:
523
+ disc_total_value = normalized_metadata[UnifiedMetadataKey.DISC_TOTAL]
524
+ from .manager._MetadataManager import _MetadataManager
525
+
526
+ _MetadataManager.validate_disc_total(disc_total_value)
527
+
513
528
 
514
529
  def update_metadata(
515
530
  file: PublicFileType,
@@ -158,6 +158,63 @@ class _MetadataManager:
158
158
  track_number,
159
159
  )
160
160
 
161
+ @staticmethod
162
+ def validate_disc_number(disc_number: int) -> None:
163
+ """Validate disc number format.
164
+
165
+ Disc numbers must be non-negative integers.
166
+
167
+ Args:
168
+ disc_number: The disc number to validate (int)
169
+
170
+ Raises:
171
+ InvalidMetadataFieldFormatError: If the disc number format is invalid
172
+
173
+ Examples:
174
+ >>> _MetadataManager.validate_disc_number(1) # Valid
175
+ >>> _MetadataManager.validate_disc_number(0) # Valid
176
+ >>> _MetadataManager.validate_disc_number(-1) # Raises InvalidMetadataFieldFormatError
177
+ """
178
+ if not isinstance(disc_number, int):
179
+ raise InvalidMetadataFieldFormatError(
180
+ UnifiedMetadataKey.DISC_NUMBER.value, "integer", str(type(disc_number).__name__)
181
+ )
182
+
183
+ if disc_number < 0:
184
+ raise InvalidMetadataFieldFormatError(
185
+ UnifiedMetadataKey.DISC_NUMBER.value, "non-negative integer", str(disc_number)
186
+ )
187
+
188
+ @staticmethod
189
+ def validate_disc_total(disc_total: int | None) -> None:
190
+ """Validate disc total format.
191
+
192
+ Disc totals must be non-negative integers or None.
193
+
194
+ Args:
195
+ disc_total: The disc total to validate (int or None)
196
+
197
+ Raises:
198
+ InvalidMetadataFieldFormatError: If the disc total format is invalid
199
+
200
+ Examples:
201
+ >>> _MetadataManager.validate_disc_total(2) # Valid
202
+ >>> _MetadataManager.validate_disc_total(None) # Valid
203
+ >>> _MetadataManager.validate_disc_total(-1) # Raises InvalidMetadataFieldFormatError
204
+ """
205
+ if disc_total is None:
206
+ return
207
+
208
+ if not isinstance(disc_total, int):
209
+ raise InvalidMetadataFieldFormatError(
210
+ UnifiedMetadataKey.DISC_TOTAL.value, "integer or None", str(type(disc_total).__name__)
211
+ )
212
+
213
+ if disc_total < 0:
214
+ raise InvalidMetadataFieldFormatError(
215
+ UnifiedMetadataKey.DISC_TOTAL.value, "non-negative integer", str(disc_total)
216
+ )
217
+
161
218
  @abstractmethod
162
219
  def _extract_mutagen_metadata(self) -> MutagenMetadata:
163
220
  raise NotImplementedError
@@ -535,7 +592,7 @@ class _MetadataManager:
535
592
  if unified_metadata_key_optional_type is float:
536
593
  return float(value[0]) if value else None
537
594
  if origin is not None and (origin == Union or (hasattr(origin, "__name__") and origin.__name__ == "UnionType")):
538
- # Handle union types like int | float
595
+ # Handle union types like int | float or int | None
539
596
  arg_types = get_args(unified_metadata_key_optional_type)
540
597
  if int in arg_types and float in arg_types:
541
598
  # For int | float, prefer int if it's a whole number, otherwise float
@@ -547,6 +604,12 @@ class _MetadataManager:
547
604
  return num_value
548
605
  except (ValueError, TypeError):
549
606
  return None
607
+ if int in arg_types and type(None) in arg_types:
608
+ # For int | None, convert to int if value exists, otherwise None
609
+ try:
610
+ return int(value[0]) if value else None
611
+ except (ValueError, TypeError):
612
+ return None
550
613
  if unified_metadata_key_optional_type is str:
551
614
  return str(value[0]) if value else None
552
615
  if unified_metadata_key_optional_type == list[str]:
@@ -25,6 +25,7 @@ from mutagen.id3._frames import (
25
25
  TMOO,
26
26
  TPE1,
27
27
  TPE2,
28
+ TPOS,
28
29
  TPUB,
29
30
  TRCK,
30
31
  TSRC,
@@ -213,6 +214,7 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
213
214
  YEAR = "TYER" # ID3v2.3 year
214
215
  DATE = "TDAT" # ID3v2.3 date (DDMM)
215
216
  TRACK_NUMBER = "TRCK"
217
+ DISC_NUMBER = "TPOS"
216
218
  BPM = "TBPM"
217
219
 
218
220
  # Additional metadata fields
@@ -240,6 +242,7 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
240
242
  Id3TextFrame.YEAR: TYER,
241
243
  Id3TextFrame.DATE: TDAT,
242
244
  Id3TextFrame.TRACK_NUMBER: TRCK,
245
+ Id3TextFrame.DISC_NUMBER: TPOS,
243
246
  Id3TextFrame.BPM: TBPM,
244
247
  Id3TextFrame.RATING: POPM,
245
248
  Id3TextFrame.COMPOSERS: TCOM,
@@ -271,6 +274,8 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
271
274
  UnifiedMetadataKey.LANGUAGE: self.Id3TextFrame.LANGUAGE,
272
275
  UnifiedMetadataKey.RELEASE_DATE: self.Id3TextFrame.RECORDING_TIME,
273
276
  UnifiedMetadataKey.TRACK_NUMBER: self.Id3TextFrame.TRACK_NUMBER,
277
+ UnifiedMetadataKey.DISC_NUMBER: None,
278
+ UnifiedMetadataKey.DISC_TOTAL: None,
274
279
  UnifiedMetadataKey.BPM: self.Id3TextFrame.BPM,
275
280
  UnifiedMetadataKey.COMPOSERS: self.Id3TextFrame.COMPOSERS,
276
281
  UnifiedMetadataKey.PUBLISHER: self.Id3TextFrame.PUBLISHER,
@@ -289,6 +294,8 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
289
294
  UnifiedMetadataKey.LANGUAGE: self.Id3TextFrame.LANGUAGE,
290
295
  UnifiedMetadataKey.RELEASE_DATE: self.Id3TextFrame.RECORDING_TIME,
291
296
  UnifiedMetadataKey.TRACK_NUMBER: self.Id3TextFrame.TRACK_NUMBER,
297
+ UnifiedMetadataKey.DISC_NUMBER: None,
298
+ UnifiedMetadataKey.DISC_TOTAL: None,
292
299
  UnifiedMetadataKey.BPM: self.Id3TextFrame.BPM,
293
300
  UnifiedMetadataKey.COMPOSERS: self.Id3TextFrame.COMPOSERS,
294
301
  UnifiedMetadataKey.PUBLISHER: self.Id3TextFrame.PUBLISHER,
@@ -434,6 +441,56 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
434
441
  if app_metadata_value is not None:
435
442
  # Add new TXXX frame with desc 'REPLAYGAIN'
436
443
  raw_mutagen_metadata.add(TXXX(encoding=3, desc="REPLAYGAIN", text=str(app_metadata_value)))
444
+ elif unified_metadata_key in (UnifiedMetadataKey.DISC_NUMBER, UnifiedMetadataKey.DISC_TOTAL):
445
+ tpos_key = self.Id3TextFrame.DISC_NUMBER
446
+ tpos_frame_class = TPOS
447
+ encoding = 0 if self.id3v2_version[1] == ID3V2_VERSION_3 else 3
448
+
449
+ if unified_metadata_key == UnifiedMetadataKey.DISC_NUMBER:
450
+ current_tpos = raw_mutagen_metadata.get(tpos_key)
451
+ current_total = None
452
+ if current_tpos and len(current_tpos.text) > 0:
453
+ tpos_str = str(current_tpos.text[0])
454
+ import re
455
+
456
+ match = re.match(r"^(\d+)/(\d+)$", tpos_str)
457
+ if match:
458
+ current_total = int(match.group(2))
459
+
460
+ raw_mutagen_metadata.delall(tpos_key)
461
+ if app_metadata_value is not None:
462
+ if not isinstance(app_metadata_value, int):
463
+ msg = f"DISC_NUMBER must be an integer, got {type(app_metadata_value).__name__}"
464
+ raise TypeError(msg)
465
+ disc_number = min(255, max(0, app_metadata_value))
466
+ tpos_value = f"{disc_number}/{current_total}" if current_total is not None else str(disc_number)
467
+ raw_mutagen_metadata.add(tpos_frame_class(encoding=encoding, text=tpos_value))
468
+ elif unified_metadata_key == UnifiedMetadataKey.DISC_TOTAL:
469
+ current_tpos = raw_mutagen_metadata.get(tpos_key)
470
+ current_disc_number = None
471
+ if current_tpos and len(current_tpos.text) > 0:
472
+ tpos_str = str(current_tpos.text[0])
473
+ import re
474
+
475
+ match = re.match(r"^(\d+)(?:/(\d+))?$", tpos_str)
476
+ if match:
477
+ current_disc_number = int(match.group(1))
478
+
479
+ raw_mutagen_metadata.delall(tpos_key)
480
+ if app_metadata_value is not None:
481
+ if not isinstance(app_metadata_value, int):
482
+ msg = f"DISC_TOTAL must be an integer, got {type(app_metadata_value).__name__}"
483
+ raise TypeError(msg)
484
+ disc_total = min(255, max(0, app_metadata_value))
485
+ if current_disc_number is not None:
486
+ tpos_value = f"{current_disc_number}/{disc_total}"
487
+ raw_mutagen_metadata.add(tpos_frame_class(encoding=encoding, text=tpos_value))
488
+ else:
489
+ msg = "Cannot set DISC_TOTAL without DISC_NUMBER"
490
+ raise ValueError(msg)
491
+ elif current_disc_number is not None:
492
+ tpos_value = str(current_disc_number)
493
+ raw_mutagen_metadata.add(tpos_frame_class(encoding=encoding, text=tpos_value))
437
494
  else:
438
495
  super()._update_undirectly_mapped_metadata( # type: ignore[safe-super]
439
496
  cast(Any, raw_mutagen_metadata), app_metadata_value, unified_metadata_key
@@ -453,6 +510,34 @@ class _Id3v2Manager(_RatingSupportingMetadataManager):
453
510
  return None
454
511
  first_value = replaygain_value[0]
455
512
  return cast(UnifiedMetadataValue, first_value)
513
+ if unified_metadata_key == UnifiedMetadataKey.DISC_NUMBER:
514
+ tpos_key = self.Id3TextFrame.DISC_NUMBER
515
+ if tpos_key not in raw_clean_metadata:
516
+ return None
517
+ tpos_value = raw_clean_metadata[tpos_key]
518
+ if tpos_value is None or len(tpos_value) == 0:
519
+ return None
520
+ tpos_str = str(tpos_value[0])
521
+ import re
522
+
523
+ match = re.match(r"^(\d+)(?:/(\d+))?$", tpos_str)
524
+ if match:
525
+ return int(match.group(1))
526
+ return None
527
+ if unified_metadata_key == UnifiedMetadataKey.DISC_TOTAL:
528
+ tpos_key = self.Id3TextFrame.DISC_NUMBER
529
+ if tpos_key not in raw_clean_metadata:
530
+ return None
531
+ tpos_value = raw_clean_metadata[tpos_key]
532
+ if tpos_value is None or len(tpos_value) == 0:
533
+ return None
534
+ tpos_str = str(tpos_value[0])
535
+ import re
536
+
537
+ match = re.match(r"^(\d+)/(\d+)$", tpos_str)
538
+ if match:
539
+ return int(match.group(2))
540
+ return None
456
541
  msg = f"Metadata key not handled: {unified_metadata_key}"
457
542
  raise MetadataFieldNotSupportedByMetadataFormatError(msg)
458
543
 
@@ -48,6 +48,8 @@ class _VorbisManager(_RatingSupportingMetadataManager):
48
48
  GENRES_NAMES = "GENRE"
49
49
  DATE = "DATE" # Creation/Release date
50
50
  TRACK_NUMBER = "TRACKNUMBER"
51
+ DISC_NUMBER = "DISCNUMBER"
52
+ DISC_TOTAL = "DISCTOTAL"
51
53
  COMMENT = "COMMENT"
52
54
  PERFORMER = "PERFORMER"
53
55
  COPYRIGHT = "COPYRIGHT"
@@ -80,6 +82,8 @@ class _VorbisManager(_RatingSupportingMetadataManager):
80
82
  UnifiedMetadataKey.LANGUAGE: self.VorbisKey.LANGUAGE,
81
83
  UnifiedMetadataKey.RELEASE_DATE: self.VorbisKey.DATE,
82
84
  UnifiedMetadataKey.TRACK_NUMBER: self.VorbisKey.TRACK_NUMBER,
85
+ UnifiedMetadataKey.DISC_NUMBER: self.VorbisKey.DISC_NUMBER,
86
+ UnifiedMetadataKey.DISC_TOTAL: self.VorbisKey.DISC_TOTAL,
83
87
  UnifiedMetadataKey.BPM: self.VorbisKey.BPM,
84
88
  UnifiedMetadataKey.COMPOSERS: self.VorbisKey.COMPOSERS,
85
89
  UnifiedMetadataKey.COPYRIGHT: self.VorbisKey.COPYRIGHT,
@@ -98,6 +102,8 @@ class _VorbisManager(_RatingSupportingMetadataManager):
98
102
  UnifiedMetadataKey.LANGUAGE: self.VorbisKey.LANGUAGE,
99
103
  UnifiedMetadataKey.RELEASE_DATE: self.VorbisKey.DATE,
100
104
  UnifiedMetadataKey.TRACK_NUMBER: self.VorbisKey.TRACK_NUMBER,
105
+ UnifiedMetadataKey.DISC_NUMBER: self.VorbisKey.DISC_NUMBER,
106
+ UnifiedMetadataKey.DISC_TOTAL: self.VorbisKey.DISC_TOTAL,
101
107
  UnifiedMetadataKey.BPM: self.VorbisKey.BPM,
102
108
  UnifiedMetadataKey.COMPOSERS: self.VorbisKey.COMPOSERS,
103
109
  UnifiedMetadataKey.COPYRIGHT: self.VorbisKey.COPYRIGHT,
@@ -312,6 +318,13 @@ class _VorbisManager(_RatingSupportingMetadataManager):
312
318
 
313
319
  self._validate_and_process_rating(unified_metadata)
314
320
 
321
+ # Handle DISC_NUMBER and DISC_TOTAL relationship: if DISC_NUMBER is None, DISC_TOTAL should also be None
322
+ if (
323
+ UnifiedMetadataKey.DISC_NUMBER in unified_metadata
324
+ and unified_metadata[UnifiedMetadataKey.DISC_NUMBER] is None
325
+ ):
326
+ unified_metadata[UnifiedMetadataKey.DISC_TOTAL] = None
327
+
315
328
  # Get current metadata
316
329
  current_metadata = self._extract_mutagen_metadata()
317
330
 
@@ -365,6 +378,8 @@ class _VorbisManager(_RatingSupportingMetadataManager):
365
378
  "GENRE": "GENRE",
366
379
  "COMMENT": "COMMENT",
367
380
  "TRACKNUMBER": "TRACKNUMBER",
381
+ "DISCNUMBER": "DISCNUMBER",
382
+ "DISCTOTAL": "DISCTOTAL",
368
383
  "BPM": "BPM",
369
384
  "COMPOSER": "COMPOSER",
370
385
  "COPYRIGHT": "COPYRIGHT",
@@ -43,6 +43,7 @@ class ID3v2MetadataSetter:
43
43
  "mood": "--TMOO",
44
44
  "key": "--TKEY",
45
45
  "publisher": "--TPUB",
46
+ "disc_number": "--TPOS",
46
47
  }
47
48
  else:
48
49
  tool = "mid3v2"
@@ -70,6 +71,7 @@ class ID3v2MetadataSetter:
70
71
  "key": "--TKEY",
71
72
  "publisher": "--TPUB",
72
73
  "bpm": "--TBPM",
74
+ "disc_number": "--TPOS",
73
75
  }
74
76
 
75
77
  metadata_added = False
@@ -60,6 +60,8 @@ class VorbisMetadataSetter:
60
60
  "url": "URL",
61
61
  "isrc": "ISRC",
62
62
  "publisher": "PUBLISHER",
63
+ "disc_number": "DISCNUMBER",
64
+ "disc_total": "DISCTOTAL",
63
65
  }
64
66
 
65
67
  metadata_added = False
@@ -0,0 +1,97 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
5
+ from audiometa.utils.metadata_format import MetadataFormat
6
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
7
+
8
+
9
+ @pytest.mark.integration
10
+ class TestDiscNumberDeleting:
11
+ def test_delete_disc_number_id3v2(self):
12
+ with temp_file_with_metadata({}, "mp3") as test_file:
13
+ update_metadata(
14
+ test_file,
15
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
16
+ metadata_format=MetadataFormat.ID3V2,
17
+ )
18
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
19
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
20
+
21
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None}, metadata_format=MetadataFormat.ID3V2)
22
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
23
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
24
+
25
+ def test_delete_disc_total_only_id3v2(self):
26
+ with temp_file_with_metadata({}, "mp3") as test_file:
27
+ update_metadata(
28
+ test_file,
29
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
30
+ metadata_format=MetadataFormat.ID3V2,
31
+ )
32
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
33
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
34
+
35
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_TOTAL: None}, metadata_format=MetadataFormat.ID3V2)
36
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
37
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
38
+
39
+ def test_delete_disc_number_vorbis(self):
40
+ with temp_file_with_metadata({}, "flac") as test_file:
41
+ update_metadata(
42
+ test_file,
43
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
44
+ metadata_format=MetadataFormat.VORBIS,
45
+ )
46
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
47
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
48
+
49
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None}, metadata_format=MetadataFormat.VORBIS)
50
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
51
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
52
+
53
+ def test_delete_disc_total_only_vorbis(self):
54
+ with temp_file_with_metadata({}, "flac") as test_file:
55
+ update_metadata(
56
+ test_file,
57
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
58
+ metadata_format=MetadataFormat.VORBIS,
59
+ )
60
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
61
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
62
+
63
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_TOTAL: None}, metadata_format=MetadataFormat.VORBIS)
64
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
65
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
66
+
67
+ def test_delete_disc_number_preserves_other_fields(self):
68
+ with temp_file_with_metadata({}, "mp3") as test_file:
69
+ update_metadata(
70
+ test_file,
71
+ {
72
+ UnifiedMetadataKey.DISC_NUMBER: 1,
73
+ UnifiedMetadataKey.DISC_TOTAL: 2,
74
+ UnifiedMetadataKey.TITLE: "Test Title",
75
+ UnifiedMetadataKey.ARTISTS: ["Test Artist"],
76
+ },
77
+ )
78
+
79
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None})
80
+
81
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
82
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
83
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE) == "Test Title"
84
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Test Artist"]
85
+
86
+ def test_delete_disc_number_already_none(self):
87
+ with temp_file_with_metadata({}, "mp3") as test_file:
88
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None})
89
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
90
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
91
+
92
+ def test_delete_disc_number_zero(self):
93
+ with temp_file_with_metadata({}, "mp3") as test_file:
94
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: 0}, metadata_format=MetadataFormat.ID3V2)
95
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 0
96
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None})
97
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
@@ -0,0 +1,92 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field
4
+ from audiometa.test.helpers.id3v2.id3v2_metadata_setter import ID3v2MetadataSetter
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
7
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
8
+
9
+
10
+ @pytest.mark.integration
11
+ class TestDiscNumberReading:
12
+ def test_id3v2_with_total(self):
13
+ with temp_file_with_metadata({}, "mp3") as test_file:
14
+ ID3v2MetadataSetter.set_metadata(test_file, {"disc_number": "1/2"})
15
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
16
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
17
+ assert disc_number == 1
18
+ assert disc_total == 2
19
+
20
+ def test_id3v2_without_total(self):
21
+ with temp_file_with_metadata({}, "mp3") as test_file:
22
+ ID3v2MetadataSetter.set_metadata(test_file, {"disc_number": "1"})
23
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
24
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
25
+ assert disc_number == 1
26
+ assert disc_total is None
27
+
28
+ def test_id3v2_max_value(self):
29
+ with temp_file_with_metadata({}, "mp3") as test_file:
30
+ ID3v2MetadataSetter.set_metadata(test_file, {"disc_number": "99/99"})
31
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
32
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
33
+ assert disc_number == 99
34
+ assert disc_total == 99
35
+
36
+ def test_vorbis_with_total(self):
37
+ with temp_file_with_metadata({}, "flac") as test_file:
38
+ VorbisMetadataSetter.set_metadata(test_file, {"disc_number": "1", "disc_total": "2"})
39
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
40
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
41
+ assert disc_number == 1
42
+ assert disc_total == 2
43
+
44
+ def test_vorbis_without_total(self):
45
+ with temp_file_with_metadata({}, "flac") as test_file:
46
+ VorbisMetadataSetter.set_metadata(test_file, {"disc_number": "2"})
47
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
48
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
49
+ assert disc_number == 2
50
+ assert disc_total is None
51
+
52
+ def test_id3v1_not_supported(self):
53
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
54
+ from audiometa.utils.metadata_format import MetadataFormat
55
+
56
+ with temp_file_with_metadata({}, "id3v1") as test_file:
57
+ with pytest.raises(
58
+ MetadataFieldNotSupportedByMetadataFormatError,
59
+ match="UnifiedMetadataKey.DISC_NUMBER metadata not supported by ID3v1 format",
60
+ ):
61
+ get_unified_metadata_field(
62
+ test_file, UnifiedMetadataKey.DISC_NUMBER, metadata_format=MetadataFormat.ID3V1
63
+ )
64
+
65
+ with pytest.raises(
66
+ MetadataFieldNotSupportedByMetadataFormatError,
67
+ match="UnifiedMetadataKey.DISC_TOTAL metadata not supported by ID3v1 format",
68
+ ):
69
+ get_unified_metadata_field(
70
+ test_file, UnifiedMetadataKey.DISC_TOTAL, metadata_format=MetadataFormat.ID3V1
71
+ )
72
+
73
+ def test_riff_not_supported(self):
74
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
75
+ from audiometa.utils.metadata_format import MetadataFormat
76
+
77
+ with temp_file_with_metadata({}, "wav") as test_file:
78
+ with pytest.raises(
79
+ MetadataFieldNotSupportedByMetadataFormatError,
80
+ match="UnifiedMetadataKey.DISC_NUMBER metadata not supported by RIFF format",
81
+ ):
82
+ get_unified_metadata_field(
83
+ test_file, UnifiedMetadataKey.DISC_NUMBER, metadata_format=MetadataFormat.RIFF
84
+ )
85
+
86
+ with pytest.raises(
87
+ MetadataFieldNotSupportedByMetadataFormatError,
88
+ match="UnifiedMetadataKey.DISC_TOTAL metadata not supported by RIFF format",
89
+ ):
90
+ get_unified_metadata_field(
91
+ test_file, UnifiedMetadataKey.DISC_TOTAL, metadata_format=MetadataFormat.RIFF
92
+ )
@@ -0,0 +1,153 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
5
+ from audiometa.utils.metadata_format import MetadataFormat
6
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
7
+
8
+
9
+ @pytest.mark.integration
10
+ class TestDiscNumberWriting:
11
+ @pytest.mark.parametrize(
12
+ ("disc_number", "disc_total", "expected_disc_number", "expected_disc_total"),
13
+ [
14
+ (1, None, 1, None),
15
+ (1, 2, 1, 2),
16
+ (99, 99, 99, 99),
17
+ ],
18
+ )
19
+ def test_id3v2_disc_number_writing(self, disc_number, disc_total, expected_disc_number, expected_disc_total):
20
+ with temp_file_with_metadata({}, "mp3") as test_file:
21
+ metadata = {UnifiedMetadataKey.DISC_NUMBER: disc_number}
22
+ if disc_total is not None:
23
+ metadata[UnifiedMetadataKey.DISC_TOTAL] = disc_total
24
+ update_metadata(test_file, metadata, metadata_format=MetadataFormat.ID3V2)
25
+
26
+ result_disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
27
+ result_disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
28
+ assert result_disc_number == expected_disc_number
29
+ assert result_disc_total == expected_disc_total
30
+
31
+ @pytest.mark.parametrize(
32
+ ("disc_number", "disc_total", "expected_disc_number", "expected_disc_total"),
33
+ [
34
+ (1, None, 1, None),
35
+ (1, 2, 1, 2),
36
+ (99, 99, 99, 99),
37
+ ],
38
+ )
39
+ def test_vorbis_disc_number_writing(self, disc_number, disc_total, expected_disc_number, expected_disc_total):
40
+ with temp_file_with_metadata({}, "flac") as test_file:
41
+ metadata = {UnifiedMetadataKey.DISC_NUMBER: disc_number}
42
+ if disc_total is not None:
43
+ metadata[UnifiedMetadataKey.DISC_TOTAL] = disc_total
44
+ update_metadata(test_file, metadata, metadata_format=MetadataFormat.VORBIS)
45
+
46
+ result_disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
47
+ result_disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
48
+ assert result_disc_number == expected_disc_number
49
+ assert result_disc_total == expected_disc_total
50
+
51
+ def test_id3v2_disc_number_with_total_combines_format(self):
52
+ with temp_file_with_metadata({}, "mp3") as test_file:
53
+ update_metadata(
54
+ test_file,
55
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
56
+ metadata_format=MetadataFormat.ID3V2,
57
+ )
58
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
59
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
60
+ assert disc_number == 1
61
+ assert disc_total == 2
62
+
63
+ def test_id3v2_disc_number_without_total_writes_simple_format(self):
64
+ with temp_file_with_metadata({}, "mp3") as test_file:
65
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: 1}, metadata_format=MetadataFormat.ID3V2)
66
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
67
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
68
+ assert disc_number == 1
69
+ assert disc_total is None
70
+
71
+ def test_vorbis_disc_number_writes_separate_fields(self):
72
+ with temp_file_with_metadata({}, "flac") as test_file:
73
+ update_metadata(
74
+ test_file,
75
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
76
+ metadata_format=MetadataFormat.VORBIS,
77
+ )
78
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
79
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
80
+ assert disc_number == 1
81
+ assert disc_total == 2
82
+
83
+ def test_id3v2_disc_number_max_value_truncated(self):
84
+ with temp_file_with_metadata({}, "mp3") as test_file:
85
+ update_metadata(
86
+ test_file,
87
+ {UnifiedMetadataKey.DISC_NUMBER: 256, UnifiedMetadataKey.DISC_TOTAL: 300},
88
+ metadata_format=MetadataFormat.ID3V2,
89
+ )
90
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
91
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
92
+ assert disc_number == 255
93
+ assert disc_total == 255
94
+
95
+ def test_vorbis_disc_number_no_limit(self):
96
+ with temp_file_with_metadata({}, "flac") as test_file:
97
+ update_metadata(
98
+ test_file,
99
+ {UnifiedMetadataKey.DISC_NUMBER: 256, UnifiedMetadataKey.DISC_TOTAL: 300},
100
+ metadata_format=MetadataFormat.VORBIS,
101
+ )
102
+ disc_number = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER)
103
+ disc_total = get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL)
104
+ assert disc_number == 256
105
+ assert disc_total == 300
106
+
107
+ def test_id3v1_not_supported(self):
108
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
109
+
110
+ with temp_file_with_metadata({}, "mp3") as test_file:
111
+ with pytest.raises(
112
+ MetadataFieldNotSupportedByMetadataFormatError,
113
+ match="UnifiedMetadataKey.DISC_NUMBER metadata not supported by ID3v1 format",
114
+ ):
115
+ update_metadata(
116
+ test_file,
117
+ {UnifiedMetadataKey.DISC_NUMBER: 1},
118
+ metadata_format=MetadataFormat.ID3V1,
119
+ )
120
+
121
+ with pytest.raises(
122
+ MetadataFieldNotSupportedByMetadataFormatError,
123
+ match="UnifiedMetadataKey.DISC_TOTAL metadata not supported by ID3v1 format",
124
+ ):
125
+ update_metadata(
126
+ test_file,
127
+ {UnifiedMetadataKey.DISC_TOTAL: 2},
128
+ metadata_format=MetadataFormat.ID3V1,
129
+ )
130
+
131
+ def test_riff_not_supported(self):
132
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
133
+
134
+ with temp_file_with_metadata({}, "wav") as test_file:
135
+ with pytest.raises(
136
+ MetadataFieldNotSupportedByMetadataFormatError,
137
+ match="UnifiedMetadataKey.DISC_NUMBER metadata not supported by RIFF format",
138
+ ):
139
+ update_metadata(
140
+ test_file,
141
+ {UnifiedMetadataKey.DISC_NUMBER: 1},
142
+ metadata_format=MetadataFormat.RIFF,
143
+ )
144
+
145
+ with pytest.raises(
146
+ MetadataFieldNotSupportedByMetadataFormatError,
147
+ match="UnifiedMetadataKey.DISC_TOTAL metadata not supported by RIFF format",
148
+ ):
149
+ update_metadata(
150
+ test_file,
151
+ {UnifiedMetadataKey.DISC_TOTAL: 2},
152
+ metadata_format=MetadataFormat.RIFF,
153
+ )