audiometa-python 0.2.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (318) hide show
  1. audiometa/__init__.py +1240 -0
  2. audiometa/__main__.py +6 -0
  3. audiometa/_audio_file.py +602 -0
  4. audiometa/cli.py +347 -0
  5. audiometa/exceptions.py +167 -0
  6. audiometa/manager/_MetadataManager.py +665 -0
  7. audiometa/manager/__init__.py +1 -0
  8. audiometa/manager/_rating_supporting/_RatingSupportingMetadataManager.py +250 -0
  9. audiometa/manager/_rating_supporting/__init__.py +1 -0
  10. audiometa/manager/_rating_supporting/id3v2/_Id3v2Manager.py +945 -0
  11. audiometa/manager/_rating_supporting/id3v2/__init__.py +25 -0
  12. audiometa/manager/_rating_supporting/id3v2/_id3v2_constants.py +11 -0
  13. audiometa/manager/_rating_supporting/riff/_RiffManager.py +778 -0
  14. audiometa/manager/_rating_supporting/riff/__init__.py +25 -0
  15. audiometa/manager/_rating_supporting/riff/_riff_constants.py +10 -0
  16. audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +525 -0
  17. audiometa/manager/_rating_supporting/vorbis/__init__.py +17 -0
  18. audiometa/manager/_rating_supporting/vorbis/_vorbis_constants.py +6 -0
  19. audiometa/manager/id3v1/_Id3v1Manager.py +512 -0
  20. audiometa/manager/id3v1/__init__.py +1 -0
  21. audiometa/manager/id3v1/_constants.py +8 -0
  22. audiometa/manager/id3v1/id3v1_raw_metadata.py +242 -0
  23. audiometa/manager/id3v1/id3v1_raw_metadata_key.py +13 -0
  24. audiometa/test/__init__.py +1 -0
  25. audiometa/test/assets/create_test_files.py +72 -0
  26. audiometa/test/helpers/__init__.py +51 -0
  27. audiometa/test/helpers/common/__init__.py +6 -0
  28. audiometa/test/helpers/common/audio_file_creator.py +68 -0
  29. audiometa/test/helpers/common/external_tool_runner.py +74 -0
  30. audiometa/test/helpers/id3v1/__init__.py +8 -0
  31. audiometa/test/helpers/id3v1/id3v1_header_verifier.py +18 -0
  32. audiometa/test/helpers/id3v1/id3v1_metadata_deleter.py +37 -0
  33. audiometa/test/helpers/id3v1/id3v1_metadata_getter.py +61 -0
  34. audiometa/test/helpers/id3v1/id3v1_metadata_setter.py +82 -0
  35. audiometa/test/helpers/id3v2/__init__.py +28 -0
  36. audiometa/test/helpers/id3v2/id3v2_frame_manual_creator.py +305 -0
  37. audiometa/test/helpers/id3v2/id3v2_header_verifier.py +38 -0
  38. audiometa/test/helpers/id3v2/id3v2_metadata_deleter.py +56 -0
  39. audiometa/test/helpers/id3v2/id3v2_metadata_getter.py +188 -0
  40. audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +428 -0
  41. audiometa/test/helpers/riff/__init__.py +8 -0
  42. audiometa/test/helpers/riff/riff_header_verifier.py +85 -0
  43. audiometa/test/helpers/riff/riff_manual_metadata_creator.py +216 -0
  44. audiometa/test/helpers/riff/riff_metadata_deleter.py +56 -0
  45. audiometa/test/helpers/riff/riff_metadata_getter.py +118 -0
  46. audiometa/test/helpers/riff/riff_metadata_setter.py +196 -0
  47. audiometa/test/helpers/scripts/__init__.py +0 -0
  48. audiometa/test/helpers/technical_info_inspector.py +115 -0
  49. audiometa/test/helpers/temp_file_with_metadata.py +82 -0
  50. audiometa/test/helpers/vorbis/__init__.py +8 -0
  51. audiometa/test/helpers/vorbis/vorbis_header_verifier.py +31 -0
  52. audiometa/test/helpers/vorbis/vorbis_metadata_deleter.py +49 -0
  53. audiometa/test/helpers/vorbis/vorbis_metadata_getter.py +67 -0
  54. audiometa/test/helpers/vorbis/vorbis_metadata_setter.py +200 -0
  55. audiometa/test/tests/__init__.py +0 -0
  56. audiometa/test/tests/conftest.py +261 -0
  57. audiometa/test/tests/e2e/__init__.py +0 -0
  58. audiometa/test/tests/e2e/cli/__init__.py +0 -0
  59. audiometa/test/tests/e2e/cli/error_handling/__init__.py +1 -0
  60. audiometa/test/tests/e2e/cli/error_handling/test_command_structure_errors.py +77 -0
  61. audiometa/test/tests/e2e/cli/error_handling/test_file_access_errors.py +130 -0
  62. audiometa/test/tests/e2e/cli/error_handling/test_format_output_errors.py +118 -0
  63. audiometa/test/tests/e2e/cli/error_handling/test_input_validation_errors.py +172 -0
  64. audiometa/test/tests/e2e/cli/error_handling/test_missing_fields_validation.py +49 -0
  65. audiometa/test/tests/e2e/cli/error_handling/test_multiple_files_errors.py +160 -0
  66. audiometa/test/tests/e2e/cli/error_handling/test_rating_validation.py +90 -0
  67. audiometa/test/tests/e2e/cli/error_handling/test_year_validation.py +51 -0
  68. audiometa/test/tests/e2e/cli/test_cli_delete.py +20 -0
  69. audiometa/test/tests/e2e/cli/test_cli_formatting.py +31 -0
  70. audiometa/test/tests/e2e/cli/test_cli_help.py +40 -0
  71. audiometa/test/tests/e2e/cli/test_cli_read.py +79 -0
  72. audiometa/test/tests/e2e/cli/test_cli_unified.py +33 -0
  73. audiometa/test/tests/e2e/cli/test_cli_write.py +116 -0
  74. audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
  75. audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +166 -0
  76. audiometa/test/tests/e2e/workflows/__init__.py +0 -0
  77. audiometa/test/tests/e2e/workflows/test_core_workflows.py +166 -0
  78. audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +318 -0
  79. audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +165 -0
  80. audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +129 -0
  81. audiometa/test/tests/e2e/workflows/test_rating_workflows.py +124 -0
  82. audiometa/test/tests/integration/__init__.py +0 -0
  83. audiometa/test/tests/integration/audio_format/__init__.py +0 -0
  84. audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
  85. audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +108 -0
  86. audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +61 -0
  87. audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +65 -0
  88. audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +69 -0
  89. audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
  90. audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +79 -0
  91. audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +61 -0
  92. audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +67 -0
  93. audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +60 -0
  94. audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
  95. audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +87 -0
  96. audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +62 -0
  97. audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +57 -0
  98. audiometa/test/tests/integration/audio_format/wav/test_wav_with_id3v2_tags.py +83 -0
  99. audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +62 -0
  100. audiometa/test/tests/integration/conftest.py +29 -0
  101. audiometa/test/tests/integration/delete_all_metadata/__init__.py +1 -0
  102. audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +102 -0
  103. audiometa/test/tests/integration/delete_all_metadata/test_audio_format_header_deletion.py +77 -0
  104. audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +47 -0
  105. audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +24 -0
  106. audiometa/test/tests/integration/encoding/__init__.py +1 -0
  107. audiometa/test/tests/integration/encoding/test_encoding.py +88 -0
  108. audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +223 -0
  109. audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
  110. audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +250 -0
  111. audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +297 -0
  112. audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata_edge_cases.py +231 -0
  113. audiometa/test/tests/integration/get_full_metadata/test_options.py +207 -0
  114. audiometa/test/tests/integration/get_full_metadata/test_parsed_fields_keys.py +85 -0
  115. audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
  116. audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
  117. audiometa/test/tests/integration/metadata_field/album/test_deleting.py +73 -0
  118. audiometa/test/tests/integration/metadata_field/album/test_reading.py +36 -0
  119. audiometa/test/tests/integration/metadata_field/album/test_writing.py +50 -0
  120. audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
  121. audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +83 -0
  122. audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +38 -0
  123. audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +52 -0
  124. audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
  125. audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +68 -0
  126. audiometa/test/tests/integration/metadata_field/artists/test_reading.py +36 -0
  127. audiometa/test/tests/integration/metadata_field/artists/test_writing.py +46 -0
  128. audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
  129. audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +75 -0
  130. audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +32 -0
  131. audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +56 -0
  132. audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
  133. audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +68 -0
  134. audiometa/test/tests/integration/metadata_field/comment/test_reading.py +36 -0
  135. audiometa/test/tests/integration/metadata_field/comment/test_writing.py +49 -0
  136. audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
  137. audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +75 -0
  138. audiometa/test/tests/integration/metadata_field/composer/test_reading.py +34 -0
  139. audiometa/test/tests/integration/metadata_field/composer/test_writing.py +41 -0
  140. audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
  141. audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +81 -0
  142. audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +35 -0
  143. audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +41 -0
  144. audiometa/test/tests/integration/metadata_field/field_not_supported/__init__.py +0 -0
  145. audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +56 -0
  146. audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +54 -0
  147. audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +61 -0
  148. audiometa/test/tests/integration/metadata_field/genre/__init__.py +0 -0
  149. audiometa/test/tests/integration/metadata_field/genre/reading/__init__.py +0 -0
  150. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/__init__.py +0 -0
  151. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v1_reading.py +65 -0
  152. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v2_reading.py +25 -0
  153. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_riff_reading.py +58 -0
  154. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_vorbis_reading.py +61 -0
  155. audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +191 -0
  156. audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +62 -0
  157. audiometa/test/tests/integration/metadata_field/genre/test_writing.py +64 -0
  158. audiometa/test/tests/integration/metadata_field/language/__init__.py +0 -0
  159. audiometa/test/tests/integration/metadata_field/language/test_deleting.py +75 -0
  160. audiometa/test/tests/integration/metadata_field/language/test_reading.py +39 -0
  161. audiometa/test/tests/integration/metadata_field/language/test_writing.py +43 -0
  162. audiometa/test/tests/integration/metadata_field/lyrics/__init__.py +0 -0
  163. audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +129 -0
  164. audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +57 -0
  165. audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +59 -0
  166. audiometa/test/tests/integration/metadata_field/publisher/__init__.py +0 -0
  167. audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +88 -0
  168. audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +32 -0
  169. audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +47 -0
  170. audiometa/test/tests/integration/metadata_field/rating/__init__.py +0 -0
  171. audiometa/test/tests/integration/metadata_field/rating/reading/__init__.py +0 -0
  172. audiometa/test/tests/integration/metadata_field/rating/reading/test_base_100_proportional.py +81 -0
  173. audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_non_proportional.py +33 -0
  174. audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_proportional.py +58 -0
  175. audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +117 -0
  176. audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +137 -0
  177. audiometa/test/tests/integration/metadata_field/rating/writing/__init__.py +0 -0
  178. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/__init__.py +0 -0
  179. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_id3v2.py +77 -0
  180. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_riff.py +55 -0
  181. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_vorbis.py +57 -0
  182. audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +192 -0
  183. audiometa/test/tests/integration/metadata_field/release_date/__init__.py +0 -0
  184. audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +74 -0
  185. audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +82 -0
  186. audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +59 -0
  187. audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +49 -0
  188. audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +134 -0
  189. audiometa/test/tests/integration/metadata_field/title/__init__.py +0 -0
  190. audiometa/test/tests/integration/metadata_field/title/test_deleting.py +73 -0
  191. audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +47 -0
  192. audiometa/test/tests/integration/metadata_field/title/test_reading.py +36 -0
  193. audiometa/test/tests/integration/metadata_field/title/test_writing.py +64 -0
  194. audiometa/test/tests/integration/metadata_field/track_number/__init__.py +0 -0
  195. audiometa/test/tests/integration/metadata_field/track_number/reading/__init__.py +0 -0
  196. audiometa/test/tests/integration/metadata_field/track_number/reading/test_edge_cases.py +43 -0
  197. audiometa/test/tests/integration/metadata_field/track_number/reading/test_metadata_format.py +32 -0
  198. audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +59 -0
  199. audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +73 -0
  200. audiometa/test/tests/integration/multiple_values/__init__.py +1 -0
  201. audiometa/test/tests/integration/multiple_values/reading/__init__.py +1 -0
  202. audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +1 -0
  203. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +23 -0
  204. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_3.py +92 -0
  205. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_4.py +216 -0
  206. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +84 -0
  207. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +169 -0
  208. audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +209 -0
  209. audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +198 -0
  210. audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +24 -0
  211. audiometa/test/tests/integration/multiple_values/writing/__init__.py +1 -0
  212. audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +1 -0
  213. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +62 -0
  214. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_3.py +36 -0
  215. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_4.py +34 -0
  216. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +32 -0
  217. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +54 -0
  218. audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +42 -0
  219. audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +98 -0
  220. audiometa/test/tests/integration/reading/__init__.py +1 -0
  221. audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +80 -0
  222. audiometa/test/tests/integration/reading/test_reading_error_handling.py +36 -0
  223. audiometa/test/tests/integration/real_audio_files/__init__.py +0 -0
  224. audiometa/test/tests/integration/real_audio_files/test_reading.py +146 -0
  225. audiometa/test/tests/integration/real_audio_files/test_writing.py +198 -0
  226. audiometa/test/tests/integration/technical_info/__init__.py +0 -0
  227. audiometa/test/tests/integration/technical_info/flac_md5/__init__.py +0 -0
  228. audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +103 -0
  229. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/__init__.py +0 -0
  230. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_audio_data_corruption.py +21 -0
  231. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_flipped_md5.py +29 -0
  232. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_non_flac_error.py +13 -0
  233. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_partial_md5.py +29 -0
  234. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_random_md5.py +29 -0
  235. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_unset_md5.py +56 -0
  236. audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +21 -0
  237. audiometa/test/tests/integration/technical_info/test_bitrate.py +38 -0
  238. audiometa/test/tests/integration/technical_info/test_channels.py +38 -0
  239. audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +38 -0
  240. audiometa/test/tests/integration/technical_info/test_sample_rate.py +40 -0
  241. audiometa/test/tests/integration/test_audio_file.py +23 -0
  242. audiometa/test/tests/integration/test_audio_format_readable_after_update_all_metadata_formats.py +95 -0
  243. audiometa/test/tests/integration/writing/__init__.py +0 -0
  244. audiometa/test/tests/integration/writing/test_error_handling.py +44 -0
  245. audiometa/test/tests/integration/writing/test_forced_format.py +224 -0
  246. audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +223 -0
  247. audiometa/test/tests/integration/writing/test_partial_update.py +36 -0
  248. audiometa/test/tests/integration/writing/writing_strategies/__init__.py +0 -0
  249. audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +79 -0
  250. audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +76 -0
  251. audiometa/test/tests/integration/writing/writing_strategies/test_sync_strategy.py +215 -0
  252. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/__init__.py +0 -0
  253. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_fail_behavior.py +42 -0
  254. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_no_writing_on_failure.py +93 -0
  255. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_strategy_specific.py +99 -0
  256. audiometa/test/tests/unit/__init__.py +0 -0
  257. audiometa/test/tests/unit/audio_file/__init__.py +0 -0
  258. audiometa/test/tests/unit/audio_file/technical_info/__init__.py +0 -0
  259. audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +26 -0
  260. audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +31 -0
  261. audiometa/test/tests/unit/audio_file/technical_info/test_duration_in_sec.py +38 -0
  262. audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +130 -0
  263. audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +51 -0
  264. audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +28 -0
  265. audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +31 -0
  266. audiometa/test/tests/unit/audio_file/test_context_manager.py +30 -0
  267. audiometa/test/tests/unit/audio_file/test_file_validation.py +40 -0
  268. audiometa/test/tests/unit/audio_file/test_operations.py +20 -0
  269. audiometa/test/tests/unit/audio_file/test_path_handling.py +23 -0
  270. audiometa/test/tests/unit/cli/__init__.py +0 -0
  271. audiometa/test/tests/unit/cli/test_expand_file_patterns.py +234 -0
  272. audiometa/test/tests/unit/metadata_managers/__init__.py +0 -0
  273. audiometa/test/tests/unit/metadata_managers/conftest.py +142 -0
  274. audiometa/test/tests/unit/metadata_managers/header_info/__init__.py +0 -0
  275. audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +49 -0
  276. audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +66 -0
  277. audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +57 -0
  278. audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +53 -0
  279. audiometa/test/tests/unit/metadata_managers/metadata_field/__init__.py +0 -0
  280. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/__init__.py +0 -0
  281. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/__init__.py +0 -0
  282. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/test_smart_parsing.py +186 -0
  283. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/__init__.py +0 -0
  284. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_separator_selection.py +142 -0
  285. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_value_filtering.py +76 -0
  286. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/__init__.py +0 -0
  287. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/__init__.py +0 -0
  288. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_normalization.py +152 -0
  289. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_profiles_values.py +23 -0
  290. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/test_rating_validation.py +77 -0
  291. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
  292. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_validation.py +151 -0
  293. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_writing_profiles.py +61 -0
  294. audiometa/test/tests/unit/metadata_managers/metadata_field/test_date_format_validation.py +135 -0
  295. audiometa/test/tests/unit/metadata_managers/metadata_field/test_track_number_validation.py +46 -0
  296. audiometa/test/tests/unit/metadata_managers/metadata_field/test_type_validation_exception.py +22 -0
  297. audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +83 -0
  298. audiometa/test/tests/unit/metadata_managers/test_metadata_format_managers_write_and_read.py +74 -0
  299. audiometa/utils/__init__.py +1 -0
  300. audiometa/utils/id3v1_genre_code_map.py +205 -0
  301. audiometa/utils/metadata_format.py +31 -0
  302. audiometa/utils/metadata_writing_strategy.py +16 -0
  303. audiometa/utils/os_dependencies_checker/__init__.py +24 -0
  304. audiometa/utils/os_dependencies_checker/base.py +62 -0
  305. audiometa/utils/os_dependencies_checker/config.py +51 -0
  306. audiometa/utils/os_dependencies_checker/macos.py +236 -0
  307. audiometa/utils/os_dependencies_checker/ubuntu.py +95 -0
  308. audiometa/utils/os_dependencies_checker/windows.py +227 -0
  309. audiometa/utils/rating_profiles.py +110 -0
  310. audiometa/utils/tool_path_resolver.py +135 -0
  311. audiometa/utils/types.py +82 -0
  312. audiometa/utils/unified_metadata_key.py +81 -0
  313. audiometa_python-0.2.2.dist-info/METADATA +1464 -0
  314. audiometa_python-0.2.2.dist-info/RECORD +318 -0
  315. audiometa_python-0.2.2.dist-info/WHEEL +5 -0
  316. audiometa_python-0.2.2.dist-info/entry_points.txt +2 -0
  317. audiometa_python-0.2.2.dist-info/licenses/LICENSE +202 -0
  318. audiometa_python-0.2.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,124 @@
1
+ """End-to-end tests for rating normalization workflows.
2
+
3
+ These tests verify that the system correctly handles different rating scales and normalization values across different
4
+ audio formats.
5
+ """
6
+
7
+ import pytest
8
+
9
+ from audiometa import delete_all_metadata, get_unified_metadata, update_metadata
10
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
11
+ from audiometa.utils.metadata_format import MetadataFormat
12
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
13
+
14
+
15
+ @pytest.mark.e2e
16
+ class TestRatingWorkflows:
17
+ def test_metadata_with_different_rating_normalizations(self):
18
+ # Use external script to set initial metadata
19
+ initial_metadata = {"title": "Initial Rating Test", "artist": "Initial Artist"}
20
+ with temp_file_with_metadata(initial_metadata, "mp3") as test_file:
21
+ # Test with 0-100 rating scale
22
+ test_metadata_100 = {UnifiedMetadataKey.TITLE: "Rating Test 100", UnifiedMetadataKey.RATING: 60}
23
+ update_metadata(
24
+ test_file, test_metadata_100, normalized_rating_max_value=100, metadata_format=MetadataFormat.ID3V2
25
+ )
26
+
27
+ metadata_100 = get_unified_metadata(test_file, normalized_rating_max_value=100)
28
+ assert metadata_100.get(UnifiedMetadataKey.TITLE) == "Rating Test 100"
29
+ assert metadata_100.get(UnifiedMetadataKey.RATING) == 60
30
+
31
+ # Test with 0-255 rating scale
32
+ test_metadata_255 = {
33
+ UnifiedMetadataKey.TITLE: "Rating Test 255",
34
+ UnifiedMetadataKey.RATING: 153, # 60% of 255
35
+ }
36
+ update_metadata(
37
+ test_file, test_metadata_255, normalized_rating_max_value=255, metadata_format=MetadataFormat.ID3V2
38
+ )
39
+
40
+ metadata_255 = get_unified_metadata(test_file, normalized_rating_max_value=255)
41
+ assert metadata_255.get(UnifiedMetadataKey.TITLE) == "Rating Test 255"
42
+ assert metadata_255.get(UnifiedMetadataKey.RATING) == 153
43
+
44
+ def test_rating_deletion_workflow(self):
45
+ # E2E test for deleting ratings with different normalizations
46
+ initial_metadata = {"title": "Rating Deletion Test", "artist": "Rating Deletion Artist"}
47
+
48
+ with temp_file_with_metadata(initial_metadata, "mp3") as test_file:
49
+ # 1. Add rating with 100 scale
50
+ rating_metadata_100 = {UnifiedMetadataKey.RATING: 80}
51
+ update_metadata(
52
+ test_file,
53
+ rating_metadata_100,
54
+ normalized_rating_max_value=100,
55
+ metadata_format=MetadataFormat.ID3V2,
56
+ )
57
+
58
+ # 2. Verify rating was added
59
+ metadata_with_rating = get_unified_metadata(test_file, normalized_rating_max_value=100)
60
+ assert metadata_with_rating.get(UnifiedMetadataKey.RATING) == 80
61
+
62
+ # 3. Delete rating by setting to None
63
+ rating_deletion = {UnifiedMetadataKey.RATING: None}
64
+ update_metadata(
65
+ test_file, rating_deletion, normalized_rating_max_value=100, metadata_format=MetadataFormat.ID3V2
66
+ )
67
+
68
+ # 4. Verify rating was deleted
69
+ metadata_after_deletion = get_unified_metadata(test_file, normalized_rating_max_value=100)
70
+ assert metadata_after_deletion.get(UnifiedMetadataKey.RATING) is None
71
+
72
+ # 5. Add rating with 255 scale
73
+ rating_metadata_255 = {UnifiedMetadataKey.RATING: 204} # 80% of 255
74
+ update_metadata(
75
+ test_file,
76
+ rating_metadata_255,
77
+ normalized_rating_max_value=255,
78
+ metadata_format=MetadataFormat.ID3V2,
79
+ )
80
+
81
+ # 6. Verify rating was added with 255 scale
82
+ metadata_with_rating_255 = get_unified_metadata(test_file, normalized_rating_max_value=255)
83
+ assert metadata_with_rating_255.get(UnifiedMetadataKey.RATING) == 204
84
+
85
+ # 7. Delete rating with 255 scale
86
+ update_metadata(
87
+ test_file, rating_deletion, normalized_rating_max_value=255, metadata_format=MetadataFormat.ID3V2
88
+ )
89
+
90
+ # 8. Verify rating was deleted
91
+ final_metadata = get_unified_metadata(test_file, normalized_rating_max_value=255)
92
+ assert final_metadata.get(UnifiedMetadataKey.RATING) is None
93
+
94
+ def test_complete_rating_cleanup_workflow(self):
95
+ # E2E test for complete cleanup including ratings
96
+ initial_metadata = {"title": "Complete Rating Cleanup", "artist": "Complete Rating Artist"}
97
+
98
+ with temp_file_with_metadata(initial_metadata, "mp3") as test_file:
99
+ # 1. Add comprehensive metadata including rating
100
+ comprehensive_metadata = {
101
+ UnifiedMetadataKey.RATING: 90,
102
+ UnifiedMetadataKey.BPM: 130,
103
+ UnifiedMetadataKey.COMMENT: "Rating cleanup test",
104
+ }
105
+ update_metadata(test_file, comprehensive_metadata, normalized_rating_max_value=100)
106
+
107
+ # 2. Verify all metadata exists
108
+ full_metadata = get_unified_metadata(test_file, normalized_rating_max_value=100)
109
+ assert full_metadata.get(UnifiedMetadataKey.RATING) == 90
110
+ assert full_metadata.get(UnifiedMetadataKey.BPM) == 130
111
+ assert full_metadata.get(UnifiedMetadataKey.COMMENT) == "Rating cleanup test"
112
+
113
+ # 3. Delete all metadata including rating
114
+ delete_result = delete_all_metadata(test_file)
115
+ assert delete_result is True
116
+
117
+ # 4. Verify all metadata including rating was deleted
118
+ cleaned_metadata = get_unified_metadata(test_file, normalized_rating_max_value=100)
119
+ assert cleaned_metadata.get(UnifiedMetadataKey.RATING) is None
120
+ assert cleaned_metadata.get(UnifiedMetadataKey.BPM) is None
121
+ assert (
122
+ cleaned_metadata.get(UnifiedMetadataKey.COMMENT) is None
123
+ or cleaned_metadata.get(UnifiedMetadataKey.COMMENT) != "Rating cleanup test"
124
+ )
File without changes
@@ -0,0 +1,108 @@
1
+ import pytest
2
+
3
+ from audiometa import delete_all_metadata, get_unified_metadata
4
+ from audiometa.exceptions import MetadataFormatNotSupportedByAudioFormatError
5
+ from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
6
+ from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
7
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
8
+ from audiometa.test.helpers.vorbis.vorbis_metadata_setter import VorbisMetadataSetter
9
+ from audiometa.utils.metadata_format import MetadataFormat
10
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
11
+
12
+
13
+ @pytest.mark.integration
14
+ class TestDeleteAllMetadataFormatSpecificFLAC:
15
+ def test_flac(self):
16
+ with temp_file_with_metadata({}, "flac") as test_file:
17
+ # Add ID3v1 metadata using external tools for proper test isolation
18
+ ID3v1MetadataSetter.set_metadata(test_file, {"title": "ID3v1 Title", "artist": "ID3v1 Artist"})
19
+
20
+ # Verify ID3v1 has metadata before adding ID3v2
21
+ id3v1_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
22
+ assert id3v1_before.get(UnifiedMetadataKey.TITLE) == "ID3v1 Title"
23
+
24
+ # Add ID3v2 metadata using external tools for proper test isolation
25
+ ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title", "artist": "ID3V2 Artist"})
26
+
27
+ # Verify ID3v2 has metadata
28
+ id3v2_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
29
+ assert id3v2_before.get(UnifiedMetadataKey.TITLE) == "ID3v2 Title"
30
+
31
+ # Add Vorbis metadata using external tools for proper test isolation
32
+ VorbisMetadataSetter.add_title(test_file, "Vorbis Title")
33
+
34
+ # Verify Vorbis has metadata
35
+ vorbis_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
36
+ assert vorbis_before.get(UnifiedMetadataKey.TITLE) == "Vorbis Title"
37
+
38
+ # Delete all metadata
39
+ result = delete_all_metadata(test_file)
40
+ assert result is True
41
+
42
+ # Verify both formats were deleted
43
+ id3v2_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
44
+ id3v1_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
45
+ vorbis_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
46
+ assert id3v2_after.get(UnifiedMetadataKey.TITLE) is None
47
+ assert id3v1_after.get(UnifiedMetadataKey.TITLE) is None
48
+ assert vorbis_after.get(UnifiedMetadataKey.TITLE) is None
49
+
50
+ def test_vorbis(self):
51
+ with temp_file_with_metadata(
52
+ {"title": "Test Vorbis Title", "artist": "Test Vorbis Artist"}, "flac"
53
+ ) as test_file:
54
+ # Verify Vorbis metadata is set
55
+ vorbis_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
56
+ assert vorbis_before.get(UnifiedMetadataKey.TITLE) == "Test Vorbis Title"
57
+
58
+ result = delete_all_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
59
+ assert result is True
60
+
61
+ # Verify Vorbis metadata is deleted
62
+ vorbis_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
63
+ assert vorbis_after.get(UnifiedMetadataKey.TITLE) is None
64
+
65
+ def test_id3v2(self):
66
+ with temp_file_with_metadata(
67
+ {"title": "Test Vorbis Title", "artist": "Test Vorbis Artist"}, "flac"
68
+ ) as test_file:
69
+ # Add ID3V2 metadata
70
+ ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3V2 Title", "artist": "ID3V2 Artist"})
71
+
72
+ # Verify ID3V2 metadata is set
73
+ id3v2_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
74
+ assert id3v2_before.get(UnifiedMetadataKey.TITLE) == "ID3V2 Title"
75
+
76
+ result = delete_all_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
77
+ assert result is True
78
+
79
+ # Verify ID3V2 metadata is deleted
80
+ id3v2_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
81
+ assert id3v2_after.get(UnifiedMetadataKey.TITLE) is None
82
+
83
+ def test_id3v1(self):
84
+ with temp_file_with_metadata(
85
+ {"title": "Test Vorbis Title", "artist": "Test Vorbis Artist"}, "flac"
86
+ ) as test_file:
87
+ # Add ID3V1 metadata
88
+ ID3v1MetadataSetter.set_metadata(test_file, {"title": "ID3V1 Title", "artist": "ID3V1 Artist"})
89
+
90
+ # Verify ID3V1 metadata is set
91
+ id3v1_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
92
+ assert id3v1_before.get(UnifiedMetadataKey.TITLE) == "ID3V1 Title"
93
+
94
+ result = delete_all_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
95
+ assert result is True
96
+
97
+ # Verify ID3V1 metadata is deleted
98
+ id3v1_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
99
+ assert id3v1_after.get(UnifiedMetadataKey.TITLE) is None
100
+
101
+ def test_riff(self):
102
+ with (
103
+ temp_file_with_metadata(
104
+ {"title": "Test Vorbis Title", "artist": "Test Vorbis Artist"}, "flac"
105
+ ) as test_file,
106
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
107
+ ):
108
+ delete_all_metadata(test_file, metadata_format=MetadataFormat.RIFF)
@@ -0,0 +1,61 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata
4
+ from audiometa.exceptions import MetadataFormatNotSupportedByAudioFormatError
5
+ from audiometa.test.helpers.id3v1.id3v1_metadata_getter import ID3v1MetadataGetter
6
+ from audiometa.test.helpers.id3v1.id3v1_metadata_setter import ID3v1MetadataSetter
7
+ from audiometa.test.helpers.id3v2.id3v2_metadata_setter import ID3v2MetadataSetter
8
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
9
+ from audiometa.test.helpers.vorbis import VorbisMetadataSetter
10
+ from audiometa.utils.metadata_format import MetadataFormat
11
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
12
+
13
+
14
+ @pytest.mark.integration
15
+ class TestFlacReading:
16
+ def test_all_metadata_reading_flac(self):
17
+ with temp_file_with_metadata({}, "flac") as test_file:
18
+ VorbisMetadataSetter.add_title(test_file, "a" * 30)
19
+
20
+ metadata = get_unified_metadata(test_file)
21
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "a" * 30
22
+
23
+ def test_vorbis_metadata_reading_flac(self):
24
+ with temp_file_with_metadata({}, "flac") as test_file:
25
+ VorbisMetadataSetter.add_title(test_file, "a" * 30)
26
+
27
+ metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
28
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "a" * 30
29
+
30
+ def test_id3v2_3_metadata_reading_flac(self):
31
+ with temp_file_with_metadata({}, "flac") as test_file:
32
+ ID3v2MetadataSetter.set_metadata(
33
+ test_file, {"title": "ID3v2.3 Long Title That Exceeds ID3v1 Limits"}, version="2.3"
34
+ )
35
+
36
+ metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 3, 0))
37
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "ID3v2.3 Long Title That Exceeds ID3v1 Limits"
38
+
39
+ def test_id3v2_4_metadata_reading_flac(self):
40
+ with temp_file_with_metadata({}, "flac") as test_file:
41
+ ID3v2MetadataSetter.set_metadata(
42
+ test_file, {"title": "ID3v2.4 Long Title That Exceeds ID3v1 Limits"}, version="2.4"
43
+ )
44
+
45
+ metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 4, 0))
46
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "ID3v2.4 Long Title That Exceeds ID3v1 Limits"
47
+
48
+ def test_id3v1_metadata_reading_flac(self):
49
+ with temp_file_with_metadata({}, "flac") as test_file:
50
+ ID3v1MetadataSetter.set_metadata(test_file, {"title": "a" * 30})
51
+ assert ID3v1MetadataGetter.get_title(test_file) == "a" * 30
52
+
53
+ metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
54
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "a" * 30
55
+
56
+ def test_riff_metadata_reading_flac(self):
57
+ with (
58
+ temp_file_with_metadata({}, "flac") as test_file,
59
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
60
+ ):
61
+ get_unified_metadata(test_file, metadata_format=MetadataFormat.RIFF)
@@ -0,0 +1,65 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field
4
+ from audiometa.exceptions import MetadataFormatNotSupportedByAudioFormatError
5
+ from audiometa.test.helpers.id3v1.id3v1_metadata_getter import ID3v1MetadataGetter
6
+ from audiometa.test.helpers.id3v1.id3v1_metadata_setter import ID3v1MetadataSetter
7
+ from audiometa.test.helpers.id3v2.id3v2_metadata_setter import ID3v2MetadataSetter
8
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
9
+ from audiometa.test.helpers.vorbis.vorbis_metadata_setter import VorbisMetadataSetter
10
+ from audiometa.utils.metadata_format import MetadataFormat
11
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
12
+
13
+
14
+ @pytest.mark.integration
15
+ class TestFlacReading:
16
+ def test_all_metadata_format_reading_flac(self):
17
+ with temp_file_with_metadata({}, "flac") as test_file:
18
+ VorbisMetadataSetter.add_title(test_file, "a" * 30)
19
+
20
+ title = get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE)
21
+ assert title == "a" * 30
22
+
23
+ def test_vorbis_metadata_reading_flac(self):
24
+ with temp_file_with_metadata({}, "flac") as test_file:
25
+ VorbisMetadataSetter.add_title(test_file, "a" * 30)
26
+
27
+ title = get_unified_metadata_field(
28
+ test_file, UnifiedMetadataKey.TITLE, metadata_format=MetadataFormat.VORBIS
29
+ )
30
+ assert title == "a" * 30
31
+
32
+ def test_id3v2_3_metadata_reading_flac(self):
33
+ with temp_file_with_metadata({}, "flac") as test_file:
34
+ ID3v2MetadataSetter.set_title(test_file, "ID3v2.3 Long Title That Exceeds ID3v1 Limits")
35
+
36
+ title = get_unified_metadata_field(
37
+ test_file, UnifiedMetadataKey.TITLE, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 3, 0)
38
+ )
39
+ assert title == "ID3v2.3 Long Title That Exceeds ID3v1 Limits"
40
+
41
+ def test_id3v2_4_metadata_reading_flac(self):
42
+ with temp_file_with_metadata({}, "flac") as test_file:
43
+ ID3v2MetadataSetter.set_title(test_file, "ID3v2.4 Long Title That Exceeds ID3v1 Limits")
44
+
45
+ title = get_unified_metadata_field(
46
+ test_file, UnifiedMetadataKey.TITLE, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 4, 0)
47
+ )
48
+ assert title == "ID3v2.4 Long Title That Exceeds ID3v1 Limits"
49
+
50
+ def test_id3v1_metadata_reading_flac(self):
51
+ with temp_file_with_metadata({}, "flac") as test_file:
52
+ ID3v1MetadataSetter.set_title(test_file, "a" * 30)
53
+ assert ID3v1MetadataGetter.get_title(test_file) == "a" * 30
54
+
55
+ title = get_unified_metadata_field(
56
+ test_file, UnifiedMetadataKey.TITLE, metadata_format=MetadataFormat.ID3V1
57
+ )
58
+ assert title == "a" * 30
59
+
60
+ def test_riff_metadata_reading_flac(self):
61
+ with (
62
+ temp_file_with_metadata({}, "flac") as test_file,
63
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
64
+ ):
65
+ get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE, metadata_format=MetadataFormat.RIFF)
@@ -0,0 +1,69 @@
1
+ import pytest
2
+
3
+ from audiometa import update_metadata
4
+ from audiometa.exceptions import MetadataFormatNotSupportedByAudioFormatError
5
+ from audiometa.test.helpers.id3v1.id3v1_metadata_getter import ID3v1MetadataGetter
6
+ from audiometa.test.helpers.id3v2.id3v2_header_verifier import ID3v2HeaderVerifier
7
+ from audiometa.test.helpers.id3v2.id3v2_metadata_getter import ID3v2MetadataGetter
8
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
9
+ from audiometa.test.helpers.vorbis.vorbis_metadata_getter import VorbisMetadataGetter
10
+ from audiometa.utils.metadata_format import MetadataFormat
11
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
12
+
13
+
14
+ @pytest.mark.integration
15
+ class TestFlacWriting:
16
+ def test_writing_default_format_flac(self):
17
+ with temp_file_with_metadata({}, "flac") as temp_flac_file_path:
18
+ metadata = {UnifiedMetadataKey.TITLE: "Test Title Default"}
19
+ update_metadata(temp_flac_file_path, metadata)
20
+
21
+ vorbis_title = VorbisMetadataGetter.get_title(temp_flac_file_path)
22
+ assert vorbis_title == "Test Title Default"
23
+
24
+ def test_vorbis_metadata_writing_flac(self):
25
+ with temp_file_with_metadata({}, "flac") as temp_flac_file_path:
26
+ metadata = {UnifiedMetadataKey.TITLE: "Test Title Vorbis"}
27
+ update_metadata(temp_flac_file_path, metadata, metadata_format=MetadataFormat.VORBIS)
28
+ title = VorbisMetadataGetter.get_title(temp_flac_file_path)
29
+ assert title == "Test Title Vorbis"
30
+
31
+ def test_id3v2_3_metadata_writing_flac(self):
32
+ with temp_file_with_metadata({}, "flac") as temp_flac_file_path:
33
+ metadata = {UnifiedMetadataKey.TITLE: "Test Title ID3v2.3"}
34
+ update_metadata(
35
+ temp_flac_file_path, metadata, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 3, 0)
36
+ )
37
+
38
+ assert ID3v2HeaderVerifier.get_id3v2_version(temp_flac_file_path) == (2, 3, 0)
39
+
40
+ title = ID3v2MetadataGetter.get_title(temp_flac_file_path)
41
+ assert title == "Test Title ID3v2.3"
42
+
43
+ def test_id3v2_4_metadata_writing_flac(self):
44
+ with temp_file_with_metadata({}, "flac") as temp_flac_file_path:
45
+ metadata = {UnifiedMetadataKey.TITLE: "Test Title ID3v2.4"}
46
+ update_metadata(
47
+ temp_flac_file_path, metadata, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 4, 0)
48
+ )
49
+
50
+ assert ID3v2HeaderVerifier.get_id3v2_version(temp_flac_file_path) == (2, 4, 0)
51
+
52
+ title = ID3v2MetadataGetter.get_title(temp_flac_file_path)
53
+ assert title == "Test Title ID3v2.4"
54
+
55
+ def test_id3v1_metadata_writing_flac(self):
56
+ with temp_file_with_metadata({}, "flac") as temp_flac_file_path:
57
+ metadata = {UnifiedMetadataKey.TITLE: "Test Title ID3v1"}
58
+ update_metadata(temp_flac_file_path, metadata, metadata_format=MetadataFormat.ID3V1)
59
+ title = ID3v1MetadataGetter.get_title(temp_flac_file_path)
60
+ assert title == "Test Title ID3v1"
61
+
62
+ def test_riff_metadata_writing_flac(self):
63
+ with (
64
+ temp_file_with_metadata({}, "flac") as test_file,
65
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
66
+ ):
67
+ update_metadata(
68
+ test_file, {UnifiedMetadataKey.TITLE: "Test Title RIFF"}, metadata_format=MetadataFormat.RIFF
69
+ )
@@ -0,0 +1,79 @@
1
+ import pytest
2
+
3
+ from audiometa import delete_all_metadata, get_unified_metadata
4
+ from audiometa.exceptions import MetadataFormatNotSupportedByAudioFormatError
5
+ from audiometa.test.helpers.id3v2.id3v2_metadata_setter import ID3v2MetadataSetter
6
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
7
+ from audiometa.utils.metadata_format import MetadataFormat
8
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
9
+
10
+
11
+ @pytest.mark.integration
12
+ class TestDeleteAllMetadataFormatSpecificMP3:
13
+ def test_delete_all_metadata_formats_mp3(self):
14
+ with temp_file_with_metadata({"title": "ID3v1 Title", "artist": "ID3v1 Artist"}, "id3v1") as test_file:
15
+ # Verify ID3v1 has metadata before adding ID3v2
16
+ id3v1_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
17
+ assert id3v1_before.get(UnifiedMetadataKey.TITLE) == "ID3v1 Title"
18
+
19
+ # Add ID3v2 metadata using external tools for proper test isolation
20
+ ID3v2MetadataSetter.set_metadata(test_file, {"title": "ID3v2 Title", "artist": "ID3V2 Artist"})
21
+
22
+ # Verify ID3v2 has metadata
23
+ id3v2_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
24
+ assert id3v2_before.get(UnifiedMetadataKey.TITLE) == "ID3v2 Title"
25
+
26
+ # Delete all metadata
27
+ result = delete_all_metadata(test_file)
28
+ assert result is True
29
+
30
+ # Verify both formats were deleted
31
+ id3v2_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
32
+ id3v1_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
33
+ assert id3v2_after.get(UnifiedMetadataKey.TITLE) is None
34
+ assert id3v1_after.get(UnifiedMetadataKey.TITLE) is None
35
+
36
+ def test_id3v2(self):
37
+ with temp_file_with_metadata({"title": "Test Title", "artist": "Test Artist"}, "mp3") as test_file:
38
+ # Verify metadata is set
39
+ id3v2_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
40
+ assert id3v2_before.get(UnifiedMetadataKey.TITLE) == "Test Title"
41
+
42
+ result = delete_all_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
43
+ assert result is True
44
+
45
+ # Verify ID3V2 metadata is deleted
46
+ id3v2_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2)
47
+ assert id3v2_after.get(UnifiedMetadataKey.TITLE) is None
48
+
49
+ def test_id3v1(self):
50
+ with temp_file_with_metadata({"title": "Test Title", "artist": "Test Artist"}, "mp3") as test_file:
51
+ # Add ID3V1 metadata
52
+ from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
53
+
54
+ ID3v1MetadataSetter.set_metadata(test_file, {"title": "ID3V1 Title", "artist": "ID3V1 Artist"})
55
+
56
+ # Verify ID3V1 metadata is set
57
+ id3v1_before = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
58
+ assert id3v1_before.get(UnifiedMetadataKey.TITLE) == "ID3V1 Title"
59
+
60
+ result = delete_all_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
61
+ assert result is True
62
+
63
+ # Verify ID3V1 metadata is deleted
64
+ id3v1_after = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
65
+ assert id3v1_after.get(UnifiedMetadataKey.TITLE) is None
66
+
67
+ def test_vorbis(self):
68
+ with (
69
+ temp_file_with_metadata({"title": "Test Title", "artist": "Test Artist"}, "mp3") as test_file,
70
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
71
+ ):
72
+ delete_all_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
73
+
74
+ def test_riff(self):
75
+ with (
76
+ temp_file_with_metadata({"title": "Test Title", "artist": "Test Artist"}, "mp3") as test_file,
77
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
78
+ ):
79
+ delete_all_metadata(test_file, metadata_format=MetadataFormat.RIFF)
@@ -0,0 +1,61 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata
4
+ from audiometa.exceptions import MetadataFormatNotSupportedByAudioFormatError
5
+ from audiometa.test.helpers.id3v1.id3v1_metadata_getter import ID3v1MetadataGetter
6
+ from audiometa.test.helpers.id3v1.id3v1_metadata_setter import ID3v1MetadataSetter
7
+ from audiometa.test.helpers.id3v2.id3v2_metadata_setter import ID3v2MetadataSetter
8
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
9
+ from audiometa.utils.metadata_format import MetadataFormat
10
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
11
+
12
+
13
+ @pytest.mark.integration
14
+ class TestMp3Reading:
15
+ def test_all_metadata_reading_mp3(self):
16
+ with temp_file_with_metadata({}, "mp3") as test_file:
17
+ ID3v1MetadataSetter.set_metadata(test_file, {"title": "a" * 30})
18
+ assert ID3v1MetadataGetter.get_title(test_file) == "a" * 30
19
+
20
+ metadata = get_unified_metadata(test_file)
21
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "a" * 30
22
+
23
+ def test_id3v2_3_metadata_reading_mp3(self):
24
+ with temp_file_with_metadata({}, "id3v2.3") as test_file:
25
+ ID3v2MetadataSetter.set_metadata(
26
+ test_file, {"title": "ID3v2.3 Long Title That Exceeds ID3v1 Limits"}, version="2.3"
27
+ )
28
+
29
+ metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 3, 0))
30
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "ID3v2.3 Long Title That Exceeds ID3v1 Limits"
31
+
32
+ def test_id3v2_4_metadata_reading_mp3(self):
33
+ with temp_file_with_metadata({}, "id3v2.4") as test_file:
34
+ ID3v2MetadataSetter.set_metadata(
35
+ test_file, {"title": "ID3v2.4 Long Title That Exceeds ID3v1 Limits"}, version="2.4"
36
+ )
37
+
38
+ metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V2, id3v2_version=(2, 4, 0))
39
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "ID3v2.4 Long Title That Exceeds ID3v1 Limits"
40
+
41
+ def test_id3v1_metadata_reading_mp3(self):
42
+ with temp_file_with_metadata({}, "mp3") as test_file:
43
+ ID3v1MetadataSetter.set_metadata(test_file, {"title": "a" * 30})
44
+ assert ID3v1MetadataGetter.get_title(test_file) == "a" * 30
45
+
46
+ metadata = get_unified_metadata(test_file, metadata_format=MetadataFormat.ID3V1)
47
+ assert metadata.get(UnifiedMetadataKey.TITLE) == "a" * 30
48
+
49
+ def test_riff_metadata_reading_mp3(self):
50
+ with (
51
+ temp_file_with_metadata({}, "mp3") as test_file,
52
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
53
+ ):
54
+ get_unified_metadata(test_file, metadata_format=MetadataFormat.RIFF)
55
+
56
+ def test_vorbis_metadata_reading_mp3(self):
57
+ with (
58
+ temp_file_with_metadata({}, "mp3") as test_file,
59
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
60
+ ):
61
+ get_unified_metadata(test_file, metadata_format=MetadataFormat.VORBIS)
@@ -0,0 +1,67 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field
4
+ from audiometa.exceptions import MetadataFormatNotSupportedByAudioFormatError
5
+ from audiometa.test.helpers.id3v1.id3v1_metadata_setter import ID3v1MetadataSetter
6
+ from audiometa.test.helpers.id3v2.id3v2_header_verifier import ID3v2HeaderVerifier
7
+ from audiometa.test.helpers.id3v2.id3v2_metadata_setter import ID3v2MetadataSetter
8
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
9
+ from audiometa.utils.metadata_format import MetadataFormat
10
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
11
+
12
+
13
+ @pytest.mark.integration
14
+ class TestMp3Reading:
15
+ def test_all_metadata_format_reading_mp3(self):
16
+ with temp_file_with_metadata({}, "mp3") as test_file:
17
+ ID3v1MetadataSetter.set_title(test_file, "Title ID3v1")
18
+
19
+ title = get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE)
20
+ assert title == "Title ID3v1"
21
+
22
+ def test_id3v1_metadata_reading_mp3(self):
23
+ with temp_file_with_metadata({}, "id3v1") as test_file:
24
+ ID3v1MetadataSetter.set_title(test_file, "Title ID3v1")
25
+
26
+ title = get_unified_metadata_field(
27
+ file=test_file, metadata_format=MetadataFormat.ID3V1, unified_metadata_key=UnifiedMetadataKey.TITLE
28
+ )
29
+ assert title == "Title ID3v1"
30
+
31
+ def test_id3v2_3_metadata_reading_mp3(self):
32
+ with temp_file_with_metadata({}, "id3v2.3") as test_file:
33
+ metadata = {UnifiedMetadataKey.TITLE: "Title ID3v2.3"}
34
+ ID3v2MetadataSetter.set_metadata(test_file, metadata, version="2.3")
35
+
36
+ assert ID3v2HeaderVerifier.get_id3v2_version(test_file) == (2, 3, 0)
37
+
38
+ title = get_unified_metadata_field(
39
+ file=test_file, metadata_format=MetadataFormat.ID3V2, unified_metadata_key=UnifiedMetadataKey.TITLE
40
+ )
41
+ assert title == "Title ID3v2.3"
42
+
43
+ def test_id3v2_4_metadata_reading_mp3(self):
44
+ with temp_file_with_metadata({}, "id3v2.4") as test_file:
45
+ metadata = {UnifiedMetadataKey.TITLE: "Title ID3v2.4"}
46
+ ID3v2MetadataSetter.set_metadata(test_file, metadata, version="2.4")
47
+
48
+ assert ID3v2HeaderVerifier.get_id3v2_version(test_file) == (2, 4, 0)
49
+
50
+ title = get_unified_metadata_field(
51
+ file=test_file, metadata_format=MetadataFormat.ID3V2, unified_metadata_key=UnifiedMetadataKey.TITLE
52
+ )
53
+ assert title == "Title ID3v2.4"
54
+
55
+ def test_riff_metadata_reading_mp3(self):
56
+ with (
57
+ temp_file_with_metadata({}, "mp3") as test_file,
58
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
59
+ ):
60
+ get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE, metadata_format=MetadataFormat.RIFF)
61
+
62
+ def test_vorbis_metadata_reading_mp3(self):
63
+ with (
64
+ temp_file_with_metadata({}, "mp3") as test_file,
65
+ pytest.raises(MetadataFormatNotSupportedByAudioFormatError),
66
+ ):
67
+ get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE, metadata_format=MetadataFormat.VORBIS)