audiometa-python 0.6.0__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 (352) hide show
  1. audiometa/__init__.py +1297 -0
  2. audiometa/__main__.py +6 -0
  3. audiometa/_audio_file.py +607 -0
  4. audiometa/cli.py +476 -0
  5. audiometa/exceptions.py +167 -0
  6. audiometa/manager/_MetadataManager.py +768 -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 +1032 -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 +1002 -0
  14. audiometa/manager/_rating_supporting/riff/__init__.py +25 -0
  15. audiometa/manager/_rating_supporting/riff/_riff_constants.py +17 -0
  16. audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +542 -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 +349 -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 +189 -0
  40. audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +506 -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 +298 -0
  44. audiometa/test/helpers/riff/riff_metadata_deleter.py +56 -0
  45. audiometa/test/helpers/riff/riff_metadata_getter.py +219 -0
  46. audiometa/test/helpers/riff/riff_metadata_setter.py +374 -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 +221 -0
  55. audiometa/test/tests/__init__.py +0 -0
  56. audiometa/test/tests/conftest.py +276 -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/read/__init__.py +0 -0
  69. audiometa/test/tests/e2e/cli/read/test_basic.py +58 -0
  70. audiometa/test/tests/e2e/cli/read/test_comprehensive.py +240 -0
  71. audiometa/test/tests/e2e/cli/read/test_formats.py +55 -0
  72. audiometa/test/tests/e2e/cli/read/test_metadata_content.py +164 -0
  73. audiometa/test/tests/e2e/cli/read/test_multiple_files.py +149 -0
  74. audiometa/test/tests/e2e/cli/read/test_options.py +88 -0
  75. audiometa/test/tests/e2e/cli/read/test_unified.py +84 -0
  76. audiometa/test/tests/e2e/cli/test_delete.py +20 -0
  77. audiometa/test/tests/e2e/cli/test_formatting.py +31 -0
  78. audiometa/test/tests/e2e/cli/test_help.py +41 -0
  79. audiometa/test/tests/e2e/cli/write/__init__.py +0 -0
  80. audiometa/test/tests/e2e/cli/write/test_basic.py +51 -0
  81. audiometa/test/tests/e2e/cli/write/test_comprehensive.py +210 -0
  82. audiometa/test/tests/e2e/cli/write/test_force_format.py +336 -0
  83. audiometa/test/tests/e2e/cli/write/test_integer_fields.py +145 -0
  84. audiometa/test/tests/e2e/cli/write/test_list_fields.py +107 -0
  85. audiometa/test/tests/e2e/cli/write/test_rating.py +74 -0
  86. audiometa/test/tests/e2e/cli/write/test_string_fields.py +54 -0
  87. audiometa/test/tests/e2e/cli/write/test_validation.py +85 -0
  88. audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
  89. audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +166 -0
  90. audiometa/test/tests/e2e/workflows/__init__.py +0 -0
  91. audiometa/test/tests/e2e/workflows/test_core_workflows.py +166 -0
  92. audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +318 -0
  93. audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +165 -0
  94. audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +129 -0
  95. audiometa/test/tests/e2e/workflows/test_rating_workflows.py +124 -0
  96. audiometa/test/tests/integration/__init__.py +0 -0
  97. audiometa/test/tests/integration/audio_format/__init__.py +0 -0
  98. audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
  99. audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +108 -0
  100. audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +61 -0
  101. audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +65 -0
  102. audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +69 -0
  103. audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
  104. audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +79 -0
  105. audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +61 -0
  106. audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +67 -0
  107. audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +60 -0
  108. audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
  109. audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +87 -0
  110. audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +62 -0
  111. audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +57 -0
  112. audiometa/test/tests/integration/audio_format/wav/test_wav_with_id3v2_tags.py +83 -0
  113. audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +62 -0
  114. audiometa/test/tests/integration/conftest.py +29 -0
  115. audiometa/test/tests/integration/delete_all_metadata/__init__.py +1 -0
  116. audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +102 -0
  117. audiometa/test/tests/integration/delete_all_metadata/test_audio_format_header_deletion.py +77 -0
  118. audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +47 -0
  119. audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +24 -0
  120. audiometa/test/tests/integration/encoding/__init__.py +1 -0
  121. audiometa/test/tests/integration/encoding/test_encoding.py +88 -0
  122. audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +223 -0
  123. audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
  124. audiometa/test/tests/integration/get_full_metadata/test_audio_formats.py +122 -0
  125. audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +250 -0
  126. audiometa/test/tests/integration/get_full_metadata/test_consistency.py +67 -0
  127. audiometa/test/tests/integration/get_full_metadata/test_edge_cases.py +123 -0
  128. audiometa/test/tests/integration/get_full_metadata/test_error_handling.py +40 -0
  129. audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +43 -0
  130. audiometa/test/tests/integration/get_full_metadata/test_options.py +207 -0
  131. audiometa/test/tests/integration/get_full_metadata/test_performance.py +95 -0
  132. audiometa/test/tests/integration/get_full_metadata/test_riff_bext.py +128 -0
  133. audiometa/test/tests/integration/get_full_metadata/test_structure.py +161 -0
  134. audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
  135. audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
  136. audiometa/test/tests/integration/metadata_field/album/test_deleting.py +73 -0
  137. audiometa/test/tests/integration/metadata_field/album/test_reading.py +36 -0
  138. audiometa/test/tests/integration/metadata_field/album/test_writing.py +50 -0
  139. audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
  140. audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +83 -0
  141. audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +38 -0
  142. audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +52 -0
  143. audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
  144. audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +68 -0
  145. audiometa/test/tests/integration/metadata_field/artists/test_reading.py +36 -0
  146. audiometa/test/tests/integration/metadata_field/artists/test_writing.py +46 -0
  147. audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
  148. audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +75 -0
  149. audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +32 -0
  150. audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +56 -0
  151. audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
  152. audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +68 -0
  153. audiometa/test/tests/integration/metadata_field/comment/test_reading.py +36 -0
  154. audiometa/test/tests/integration/metadata_field/comment/test_writing.py +49 -0
  155. audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
  156. audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +75 -0
  157. audiometa/test/tests/integration/metadata_field/composer/test_reading.py +34 -0
  158. audiometa/test/tests/integration/metadata_field/composer/test_writing.py +41 -0
  159. audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
  160. audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +81 -0
  161. audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +35 -0
  162. audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +41 -0
  163. audiometa/test/tests/integration/metadata_field/disc_number/__init__.py +0 -0
  164. audiometa/test/tests/integration/metadata_field/disc_number/test_deleting.py +97 -0
  165. audiometa/test/tests/integration/metadata_field/disc_number/test_reading.py +92 -0
  166. audiometa/test/tests/integration/metadata_field/disc_number/test_writing.py +153 -0
  167. audiometa/test/tests/integration/metadata_field/field_not_supported/__init__.py +0 -0
  168. audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +56 -0
  169. audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +54 -0
  170. audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +61 -0
  171. audiometa/test/tests/integration/metadata_field/genre/__init__.py +0 -0
  172. audiometa/test/tests/integration/metadata_field/genre/reading/__init__.py +0 -0
  173. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/__init__.py +0 -0
  174. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v1_reading.py +65 -0
  175. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v2_reading.py +25 -0
  176. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_riff_reading.py +58 -0
  177. audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_vorbis_reading.py +61 -0
  178. audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +191 -0
  179. audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +62 -0
  180. audiometa/test/tests/integration/metadata_field/genre/test_writing.py +64 -0
  181. audiometa/test/tests/integration/metadata_field/isrc/__init__.py +1 -0
  182. audiometa/test/tests/integration/metadata_field/isrc/test_deleting.py +31 -0
  183. audiometa/test/tests/integration/metadata_field/isrc/test_reading.py +35 -0
  184. audiometa/test/tests/integration/metadata_field/isrc/test_writing.py +165 -0
  185. audiometa/test/tests/integration/metadata_field/language/__init__.py +0 -0
  186. audiometa/test/tests/integration/metadata_field/language/test_deleting.py +75 -0
  187. audiometa/test/tests/integration/metadata_field/language/test_reading.py +39 -0
  188. audiometa/test/tests/integration/metadata_field/language/test_writing.py +43 -0
  189. audiometa/test/tests/integration/metadata_field/lyrics/__init__.py +0 -0
  190. audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +129 -0
  191. audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +57 -0
  192. audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +59 -0
  193. audiometa/test/tests/integration/metadata_field/publisher/__init__.py +0 -0
  194. audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +88 -0
  195. audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +32 -0
  196. audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +47 -0
  197. audiometa/test/tests/integration/metadata_field/rating/__init__.py +0 -0
  198. audiometa/test/tests/integration/metadata_field/rating/reading/__init__.py +0 -0
  199. audiometa/test/tests/integration/metadata_field/rating/reading/test_base_100_proportional.py +81 -0
  200. audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_non_proportional.py +33 -0
  201. audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_proportional.py +58 -0
  202. audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +117 -0
  203. audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +137 -0
  204. audiometa/test/tests/integration/metadata_field/rating/writing/__init__.py +0 -0
  205. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/__init__.py +0 -0
  206. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_id3v2.py +77 -0
  207. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_riff.py +55 -0
  208. audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_vorbis.py +57 -0
  209. audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +192 -0
  210. audiometa/test/tests/integration/metadata_field/release_date/__init__.py +0 -0
  211. audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +74 -0
  212. audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +82 -0
  213. audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +59 -0
  214. audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +49 -0
  215. audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +135 -0
  216. audiometa/test/tests/integration/metadata_field/title/__init__.py +0 -0
  217. audiometa/test/tests/integration/metadata_field/title/test_deleting.py +73 -0
  218. audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +47 -0
  219. audiometa/test/tests/integration/metadata_field/title/test_reading.py +36 -0
  220. audiometa/test/tests/integration/metadata_field/title/test_writing.py +64 -0
  221. audiometa/test/tests/integration/metadata_field/track_number/__init__.py +0 -0
  222. audiometa/test/tests/integration/metadata_field/track_number/reading/__init__.py +0 -0
  223. audiometa/test/tests/integration/metadata_field/track_number/reading/test_edge_cases.py +43 -0
  224. audiometa/test/tests/integration/metadata_field/track_number/reading/test_metadata_format.py +32 -0
  225. audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +59 -0
  226. audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +73 -0
  227. audiometa/test/tests/integration/multiple_values/__init__.py +1 -0
  228. audiometa/test/tests/integration/multiple_values/reading/__init__.py +1 -0
  229. audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +1 -0
  230. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +23 -0
  231. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_3.py +92 -0
  232. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_4.py +216 -0
  233. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +84 -0
  234. audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +169 -0
  235. audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +209 -0
  236. audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +198 -0
  237. audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +24 -0
  238. audiometa/test/tests/integration/multiple_values/writing/__init__.py +1 -0
  239. audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +1 -0
  240. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +62 -0
  241. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_3.py +36 -0
  242. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_4.py +34 -0
  243. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +32 -0
  244. audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +54 -0
  245. audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +42 -0
  246. audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +98 -0
  247. audiometa/test/tests/integration/reading/__init__.py +1 -0
  248. audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +80 -0
  249. audiometa/test/tests/integration/reading/test_reading_error_handling.py +36 -0
  250. audiometa/test/tests/integration/real_audio_files/__init__.py +0 -0
  251. audiometa/test/tests/integration/real_audio_files/test_reading.py +146 -0
  252. audiometa/test/tests/integration/real_audio_files/test_writing.py +198 -0
  253. audiometa/test/tests/integration/technical_info/__init__.py +0 -0
  254. audiometa/test/tests/integration/technical_info/flac_md5/__init__.py +0 -0
  255. audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +103 -0
  256. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/__init__.py +0 -0
  257. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_audio_data_corruption.py +21 -0
  258. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_flipped_md5.py +29 -0
  259. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_non_flac_error.py +13 -0
  260. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_partial_md5.py +29 -0
  261. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_random_md5.py +29 -0
  262. audiometa/test/tests/integration/technical_info/flac_md5/test_invalid_md5/test_unset_md5.py +56 -0
  263. audiometa/test/tests/integration/technical_info/flac_md5/test_valid_md5.py +21 -0
  264. audiometa/test/tests/integration/technical_info/test_bitrate.py +79 -0
  265. audiometa/test/tests/integration/technical_info/test_channels.py +38 -0
  266. audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +38 -0
  267. audiometa/test/tests/integration/technical_info/test_sample_rate.py +40 -0
  268. audiometa/test/tests/integration/test_audio_file.py +35 -0
  269. audiometa/test/tests/integration/test_audio_format_readable_after_update_all_metadata_formats.py +95 -0
  270. audiometa/test/tests/integration/writing/__init__.py +0 -0
  271. audiometa/test/tests/integration/writing/test_error_handling.py +44 -0
  272. audiometa/test/tests/integration/writing/test_forced_format.py +224 -0
  273. audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +223 -0
  274. audiometa/test/tests/integration/writing/test_partial_update.py +36 -0
  275. audiometa/test/tests/integration/writing/writing_strategies/__init__.py +0 -0
  276. audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +79 -0
  277. audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +76 -0
  278. audiometa/test/tests/integration/writing/writing_strategies/test_sync_strategy.py +215 -0
  279. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/__init__.py +0 -0
  280. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_fail_behavior.py +42 -0
  281. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_no_writing_on_failure.py +93 -0
  282. audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_strategy_specific.py +99 -0
  283. audiometa/test/tests/unit/__init__.py +0 -0
  284. audiometa/test/tests/unit/audio_file/__init__.py +0 -0
  285. audiometa/test/tests/unit/audio_file/technical_info/__init__.py +0 -0
  286. audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +26 -0
  287. audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +31 -0
  288. audiometa/test/tests/unit/audio_file/technical_info/test_duration_in_sec.py +38 -0
  289. audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +190 -0
  290. audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +51 -0
  291. audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +28 -0
  292. audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +31 -0
  293. audiometa/test/tests/unit/audio_file/test_context_manager.py +30 -0
  294. audiometa/test/tests/unit/audio_file/test_file_validation.py +40 -0
  295. audiometa/test/tests/unit/audio_file/test_is_audio_file.py +49 -0
  296. audiometa/test/tests/unit/audio_file/test_operations.py +20 -0
  297. audiometa/test/tests/unit/audio_file/test_path_handling.py +23 -0
  298. audiometa/test/tests/unit/cli/__init__.py +0 -0
  299. audiometa/test/tests/unit/cli/test_expand_file_patterns.py +234 -0
  300. audiometa/test/tests/unit/metadata_managers/__init__.py +0 -0
  301. audiometa/test/tests/unit/metadata_managers/conftest.py +142 -0
  302. audiometa/test/tests/unit/metadata_managers/header_info/__init__.py +0 -0
  303. audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +49 -0
  304. audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +66 -0
  305. audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +343 -0
  306. audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +53 -0
  307. audiometa/test/tests/unit/metadata_managers/metadata_field/__init__.py +0 -0
  308. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/__init__.py +0 -0
  309. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/__init__.py +0 -0
  310. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/test_smart_parsing.py +186 -0
  311. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/__init__.py +0 -0
  312. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_separator_selection.py +142 -0
  313. audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_value_filtering.py +76 -0
  314. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/__init__.py +0 -0
  315. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/__init__.py +0 -0
  316. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_normalization.py +152 -0
  317. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_profiles_values.py +23 -0
  318. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/test_rating_validation.py +77 -0
  319. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
  320. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_configuration_error.py +43 -0
  321. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_validation.py +151 -0
  322. audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_writing_profiles.py +61 -0
  323. audiometa/test/tests/unit/metadata_managers/metadata_field/test_date_format_validation.py +135 -0
  324. audiometa/test/tests/unit/metadata_managers/metadata_field/test_disc_number_validation.py +75 -0
  325. audiometa/test/tests/unit/metadata_managers/metadata_field/test_isrc_format_validation.py +121 -0
  326. audiometa/test/tests/unit/metadata_managers/metadata_field/test_isrc_type_validation.py +30 -0
  327. audiometa/test/tests/unit/metadata_managers/metadata_field/test_track_number_validation.py +46 -0
  328. audiometa/test/tests/unit/metadata_managers/metadata_field/test_type_validation_exception.py +22 -0
  329. audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +83 -0
  330. audiometa/test/tests/unit/metadata_managers/test_metadata_format_managers_write_and_read.py +74 -0
  331. audiometa/test/tests/unit/metadata_managers/test_riff_configuration_error.py +26 -0
  332. audiometa/utils/__init__.py +1 -0
  333. audiometa/utils/id3v1_genre_code_map.py +205 -0
  334. audiometa/utils/metadata_format.py +31 -0
  335. audiometa/utils/metadata_writing_strategy.py +16 -0
  336. audiometa/utils/mutagen_exception_handler.py +24 -0
  337. audiometa/utils/os_dependencies_checker/__init__.py +24 -0
  338. audiometa/utils/os_dependencies_checker/base.py +62 -0
  339. audiometa/utils/os_dependencies_checker/config.py +77 -0
  340. audiometa/utils/os_dependencies_checker/macos.py +236 -0
  341. audiometa/utils/os_dependencies_checker/ubuntu.py +95 -0
  342. audiometa/utils/os_dependencies_checker/windows.py +227 -0
  343. audiometa/utils/rating_profiles.py +110 -0
  344. audiometa/utils/tool_path_resolver.py +135 -0
  345. audiometa/utils/types.py +82 -0
  346. audiometa/utils/unified_metadata_key.py +87 -0
  347. audiometa_python-0.6.0.dist-info/METADATA +1593 -0
  348. audiometa_python-0.6.0.dist-info/RECORD +352 -0
  349. audiometa_python-0.6.0.dist-info/WHEEL +5 -0
  350. audiometa_python-0.6.0.dist-info/entry_points.txt +2 -0
  351. audiometa_python-0.6.0.dist-info/licenses/LICENSE +202 -0
  352. audiometa_python-0.6.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,36 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field
4
+ from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
5
+ from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
6
+ from audiometa.test.helpers.riff import RIFFMetadataSetter
7
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
8
+ from audiometa.test.helpers.vorbis import VorbisMetadataSetter
9
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
10
+
11
+
12
+ @pytest.mark.integration
13
+ class TestAlbumReading:
14
+ def test_id3v1(self):
15
+ with temp_file_with_metadata({"title": "Test Song"}, "id3v1") as test_file:
16
+ ID3v1MetadataSetter.set_max_metadata(test_file)
17
+ album = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM)
18
+ assert album == "a" * 30
19
+
20
+ def test_id3v2(self):
21
+ with temp_file_with_metadata({"title": "Test Song"}, "mp3") as test_file:
22
+ ID3v2MetadataSetter.set_max_metadata(test_file)
23
+ album = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM)
24
+ assert album == "a" * 1000
25
+
26
+ def test_vorbis(self):
27
+ with temp_file_with_metadata({"title": "Test Song"}, "flac") as test_file:
28
+ VorbisMetadataSetter.set_max_metadata(test_file)
29
+ album = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM)
30
+ assert album == "a" * 1000
31
+
32
+ def test_riff(self):
33
+ with temp_file_with_metadata({"title": "Test Song"}, "wav") as test_file:
34
+ RIFFMetadataSetter.set_max_metadata(test_file)
35
+ album = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM)
36
+ assert album == "a" * 1000
@@ -0,0 +1,50 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata, 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 TestAlbumWriting:
11
+ def test_id3v2(self):
12
+ with temp_file_with_metadata({}, "mp3") as test_file:
13
+ test_album = "Test Album ID3v2"
14
+ test_metadata = {UnifiedMetadataKey.ALBUM: test_album}
15
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V2)
16
+ metadata = get_unified_metadata(test_file)
17
+ assert metadata.get(UnifiedMetadataKey.ALBUM) == test_album
18
+
19
+ def test_riff(self):
20
+ with temp_file_with_metadata({}, "wav") as test_file:
21
+ test_album = "Test Album RIFF"
22
+ test_metadata = {UnifiedMetadataKey.ALBUM: test_album}
23
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.RIFF)
24
+ metadata = get_unified_metadata(test_file)
25
+ assert metadata.get(UnifiedMetadataKey.ALBUM) == test_album
26
+
27
+ def test_vorbis(self):
28
+ with temp_file_with_metadata({}, "flac") as test_file:
29
+ test_album = "Test Album Vorbis"
30
+ test_metadata = {UnifiedMetadataKey.ALBUM: test_album}
31
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.VORBIS)
32
+ metadata = get_unified_metadata(test_file)
33
+ assert metadata.get(UnifiedMetadataKey.ALBUM) == test_album
34
+
35
+ def test_id3v1(self):
36
+ with temp_file_with_metadata({}, "id3v1") as test_file:
37
+ test_album = "Test Album ID3v1"
38
+ test_metadata = {UnifiedMetadataKey.ALBUM: test_album}
39
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V1)
40
+ metadata = get_unified_metadata(test_file)
41
+ assert metadata.get(UnifiedMetadataKey.ALBUM) == test_album
42
+
43
+ def test_invalid_type_raises(self):
44
+ from audiometa.exceptions import InvalidMetadataFieldTypeError
45
+
46
+ with temp_file_with_metadata({}, "mp3") as test_file:
47
+ # pass an int where a string is expected
48
+ bad_metadata = {UnifiedMetadataKey.ALBUM: 123}
49
+ with pytest.raises(InvalidMetadataFieldTypeError):
50
+ update_metadata(test_file, bad_metadata)
@@ -0,0 +1,83 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
5
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
6
+ from audiometa.test.helpers.vorbis import VorbisMetadataSetter
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 TestAlbumArtistsDeleting:
13
+ def test_delete_album_artists_id3v2(self):
14
+ with temp_file_with_metadata({}, "mp3") as test_file:
15
+ # Set metadata using max metadata method (includes album artists)
16
+ ID3v2MetadataSetter.set_max_metadata(test_file)
17
+ # Verify album artists are set
18
+ album_artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS)
19
+ assert album_artists is not None
20
+
21
+ # Delete metadata by setting to None
22
+ update_metadata(test_file, {UnifiedMetadataKey.ALBUM_ARTISTS: None}, metadata_format=MetadataFormat.ID3V2)
23
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS) is None
24
+
25
+ def test_delete_album_artists_riff(self):
26
+ with temp_file_with_metadata({}, "wav") as test_file:
27
+ # Set album artists using the unified API
28
+ update_metadata(
29
+ test_file,
30
+ {UnifiedMetadataKey.ALBUM_ARTISTS: ["Test Album Artist"]},
31
+ metadata_format=MetadataFormat.RIFF,
32
+ )
33
+ # Verify album artists are set
34
+ album_artists = get_unified_metadata_field(
35
+ test_file, UnifiedMetadataKey.ALBUM_ARTISTS, metadata_format=MetadataFormat.RIFF
36
+ )
37
+ assert album_artists == ["Test Album Artist"]
38
+
39
+ # Delete metadata by setting to None
40
+ update_metadata(test_file, {UnifiedMetadataKey.ALBUM_ARTISTS: None}, metadata_format=MetadataFormat.RIFF)
41
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS) is None
42
+
43
+ def test_delete_album_artists_vorbis(self):
44
+ with temp_file_with_metadata({}, "flac") as test_file:
45
+ # Set metadata using max metadata method (includes album artists)
46
+ VorbisMetadataSetter.set_max_metadata(test_file)
47
+ # Verify album artists are set
48
+ album_artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS)
49
+ assert album_artists is not None
50
+
51
+ # Delete metadata by setting to None
52
+ update_metadata(test_file, {UnifiedMetadataKey.ALBUM_ARTISTS: None}, metadata_format=MetadataFormat.VORBIS)
53
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS) is None
54
+
55
+ def test_delete_album_artists_preserves_other_fields(self):
56
+ with temp_file_with_metadata({}, "mp3") as test_file:
57
+ # Set metadata using max metadata method (includes album artists and other fields)
58
+ ID3v2MetadataSetter.set_max_metadata(test_file)
59
+ # Verify album artists are set
60
+ album_artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS)
61
+ assert album_artists is not None
62
+
63
+ # Delete only album artists
64
+ update_metadata(test_file, {UnifiedMetadataKey.ALBUM_ARTISTS: None}, metadata_format=MetadataFormat.ID3V2)
65
+
66
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS) is None
67
+ # Verify other fields are preserved
68
+ title = get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE)
69
+ assert title is not None
70
+
71
+ def test_delete_album_artists_already_none(self):
72
+ with temp_file_with_metadata({}, "mp3") as test_file:
73
+ # Try to delete album artists that don't exist
74
+ update_metadata(test_file, {UnifiedMetadataKey.ALBUM_ARTISTS: None}, metadata_format=MetadataFormat.ID3V2)
75
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS) is None
76
+
77
+ def test_delete_album_artists_with_existing_metadata(self):
78
+ with temp_file_with_metadata({}, "mp3") as test_file:
79
+ # Set metadata using max metadata method (includes album artists)
80
+ ID3v2MetadataSetter.set_max_metadata(test_file)
81
+ # Delete the album artists
82
+ update_metadata(test_file, {UnifiedMetadataKey.ALBUM_ARTISTS: None}, metadata_format=MetadataFormat.ID3V2)
83
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS) is None
@@ -0,0 +1,38 @@
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.riff.riff_metadata_getter import RIFFMetadataGetter
6
+ from audiometa.test.helpers.riff.riff_metadata_setter import RIFFMetadataSetter
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.unified_metadata_key import UnifiedMetadataKey
10
+
11
+
12
+ @pytest.mark.integration
13
+ class TestAlbumArtistsReading:
14
+ def test_id3v1(self):
15
+ with temp_file_with_metadata({"title": "Test Song"}, "id3v1") as test_file:
16
+ album_artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS)
17
+ assert album_artists is None
18
+
19
+ def test_id3v2(self):
20
+ with temp_file_with_metadata({"title": "Test Song"}, "mp3") as test_file:
21
+ ID3v2MetadataSetter.set_max_metadata(test_file)
22
+ album_artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS)
23
+ assert album_artists == ["a" * 1000]
24
+
25
+ def test_vorbis(self):
26
+ with temp_file_with_metadata({"title": "Test Song"}, "flac") as test_file:
27
+ VorbisMetadataSetter.set_max_metadata(test_file)
28
+ album_artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS)
29
+ assert album_artists == ["a" * 1000]
30
+
31
+ def test_riff(self):
32
+ with temp_file_with_metadata({"title": "Test Song"}, "wav") as test_file:
33
+ RIFFMetadataSetter.set_multiple_album_artists(test_file, ["Test Album Artist"])
34
+ raw_metadata = RIFFMetadataGetter.get_raw_metadata(test_file)
35
+ assert "TAG:IAAR=Test Album Artist" in raw_metadata
36
+
37
+ album_artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM_ARTISTS)
38
+ assert album_artists == ["Test Album Artist"]
@@ -0,0 +1,52 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata, update_metadata
4
+ from audiometa.exceptions import InvalidMetadataFieldTypeError
5
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
6
+ from audiometa.utils.metadata_format import MetadataFormat
7
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
8
+
9
+
10
+ @pytest.mark.integration
11
+ class TestAlbumArtistsWriting:
12
+ def test_id3v2(self):
13
+ test_album_artists = ["Album Artist 1", "Album Artist 2"]
14
+ test_metadata = {UnifiedMetadataKey.ALBUM_ARTISTS: test_album_artists}
15
+ with temp_file_with_metadata({}, "mp3") as test_file:
16
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V2)
17
+ metadata = get_unified_metadata(test_file)
18
+ assert metadata.get(UnifiedMetadataKey.ALBUM_ARTISTS) == test_album_artists
19
+
20
+ def test_riff(self):
21
+ test_album_artists = ["RIFF Album Artist 1", "RIFF Album Artist 2"]
22
+ test_metadata = {UnifiedMetadataKey.ALBUM_ARTISTS: test_album_artists}
23
+ with temp_file_with_metadata({}, "wav") as test_file:
24
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.RIFF)
25
+ metadata = get_unified_metadata(test_file)
26
+ assert metadata.get(UnifiedMetadataKey.ALBUM_ARTISTS) == test_album_artists
27
+
28
+ def test_vorbis(self):
29
+ test_album_artists = ["Vorbis Album Artist 1", "Vorbis Album Artist 2"]
30
+ test_metadata = {UnifiedMetadataKey.ALBUM_ARTISTS: test_album_artists}
31
+ with temp_file_with_metadata({}, "flac") as test_file:
32
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.VORBIS)
33
+ metadata = get_unified_metadata(test_file)
34
+ assert metadata.get(UnifiedMetadataKey.ALBUM_ARTISTS) == test_album_artists
35
+
36
+ def test_id3v1(self):
37
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
38
+
39
+ test_album_artists = ["ID3v1 Album Artist"]
40
+ test_metadata = {UnifiedMetadataKey.ALBUM_ARTISTS: test_album_artists}
41
+ with (
42
+ temp_file_with_metadata({}, "mp3") as test_file,
43
+ pytest.raises(
44
+ MetadataFieldNotSupportedByMetadataFormatError,
45
+ match="UnifiedMetadataKey.ALBUM_ARTISTS metadata not supported by ID3v1 format",
46
+ ),
47
+ ):
48
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V1)
49
+
50
+ def test_invalid_type_raises(self):
51
+ with temp_file_with_metadata({}, "mp3") as test_file, pytest.raises(InvalidMetadataFieldTypeError):
52
+ update_metadata(test_file, {UnifiedMetadataKey.ALBUM_ARTISTS: "Single Album Artist"})
@@ -0,0 +1,68 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
5
+ from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
6
+ from audiometa.test.helpers.riff import RIFFMetadataSetter
7
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
8
+ from audiometa.test.helpers.vorbis 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 TestArtistsDeleting:
15
+ def test_delete_artists_id3v2(self):
16
+ with temp_file_with_metadata({}, "mp3") as test_file:
17
+ ID3v2MetadataSetter.set_artists(test_file, "Artist 1; Artist 2")
18
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Artist 1", "Artist 2"]
19
+
20
+ # Delete metadata using library API
21
+ update_metadata(test_file, {UnifiedMetadataKey.ARTISTS: None}, metadata_format=MetadataFormat.ID3V2)
22
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) is None
23
+
24
+ def test_delete_artists_id3v1(self):
25
+ with temp_file_with_metadata({}, "id3v1") as test_file:
26
+ ID3v1MetadataSetter.set_artist(test_file, "Artist 1")
27
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Artist 1"]
28
+
29
+ # Delete metadata using library API
30
+ update_metadata(test_file, {UnifiedMetadataKey.ARTISTS: None}, metadata_format=MetadataFormat.ID3V1)
31
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) is None
32
+
33
+ def test_delete_artists_riff(self):
34
+ with temp_file_with_metadata({}, "wav") as test_file:
35
+ RIFFMetadataSetter.set_artist(test_file, "Artist 1")
36
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Artist 1"]
37
+
38
+ # Delete metadata using library API
39
+ update_metadata(test_file, {UnifiedMetadataKey.ARTISTS: None}, metadata_format=MetadataFormat.RIFF)
40
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) is None
41
+
42
+ def test_delete_artists_vorbis(self):
43
+ with temp_file_with_metadata({}, "flac") as test_file:
44
+ VorbisMetadataSetter.set_artists(test_file, ["Artist 1", "Artist 2"])
45
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Artist 1", "Artist 2"]
46
+
47
+ # Delete metadata using library API
48
+ update_metadata(test_file, {UnifiedMetadataKey.ARTISTS: None}, metadata_format=MetadataFormat.VORBIS)
49
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) is None
50
+
51
+ def test_delete_artists_preserves_other_fields(self):
52
+ with temp_file_with_metadata({}, "mp3") as test_file:
53
+ ID3v2MetadataSetter.set_artists(test_file, "Test Artist")
54
+ ID3v2MetadataSetter.set_title(test_file, "Test Title")
55
+ ID3v2MetadataSetter.set_album(test_file, "Test Album")
56
+
57
+ # Delete only artists using library API
58
+ update_metadata(test_file, {UnifiedMetadataKey.ARTISTS: None}, metadata_format=MetadataFormat.ID3V2)
59
+
60
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) is None
61
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE) == "Test Title"
62
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ALBUM) == "Test Album"
63
+
64
+ def test_delete_artists_already_none(self):
65
+ with temp_file_with_metadata({}, "mp3") as test_file:
66
+ # Try to delete artists that don't exist
67
+ update_metadata(test_file, {UnifiedMetadataKey.ARTISTS: None}, metadata_format=MetadataFormat.ID3V2)
68
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) is None
@@ -0,0 +1,36 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field
4
+ from audiometa.test.helpers.id3v1 import ID3v1MetadataSetter
5
+ from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
6
+ from audiometa.test.helpers.riff import RIFFMetadataSetter
7
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
8
+ from audiometa.test.helpers.vorbis import VorbisMetadataSetter
9
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
10
+
11
+
12
+ @pytest.mark.integration
13
+ class TestArtistsReading:
14
+ def test_id3v1(self):
15
+ with temp_file_with_metadata({"title": "Test Song"}, "id3v1") as test_file:
16
+ ID3v1MetadataSetter.set_max_metadata(test_file)
17
+ artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS)
18
+ assert artists == ["a" * 30]
19
+
20
+ def test_id3v2(self):
21
+ with temp_file_with_metadata({"title": "Test Song"}, "mp3") as test_file:
22
+ ID3v2MetadataSetter.set_max_metadata(test_file)
23
+ artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS)
24
+ assert artists == ["a" * 1000]
25
+
26
+ def test_vorbis(self):
27
+ with temp_file_with_metadata({"title": "Test Song"}, "flac") as test_file:
28
+ VorbisMetadataSetter.set_max_metadata(test_file)
29
+ artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS)
30
+ assert artists == ["a" * 1000]
31
+
32
+ def test_riff(self):
33
+ with temp_file_with_metadata({"title": "Test Song"}, "wav") as test_file:
34
+ RIFFMetadataSetter.set_max_metadata(test_file)
35
+ artists = get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS)
36
+ assert artists == ["a" * 1000]
@@ -0,0 +1,46 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata, update_metadata
4
+ from audiometa.exceptions import InvalidMetadataFieldTypeError
5
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
6
+ from audiometa.utils.metadata_format import MetadataFormat
7
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
8
+
9
+
10
+ @pytest.mark.integration
11
+ class TestArtistsWriting:
12
+ def test_id3v2(self):
13
+ test_artists = ["Test Artist 1", "Test Artist 2"]
14
+ test_metadata = {UnifiedMetadataKey.ARTISTS: test_artists}
15
+ with temp_file_with_metadata({}, "mp3") as test_file:
16
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V2)
17
+ metadata = get_unified_metadata(test_file)
18
+ assert metadata.get(UnifiedMetadataKey.ARTISTS) == test_artists
19
+
20
+ def test_riff(self):
21
+ test_artists = ["RIFF Artist 1", "RIFF Artist 2"]
22
+ test_metadata = {UnifiedMetadataKey.ARTISTS: test_artists}
23
+ with temp_file_with_metadata({}, "wav") as test_file:
24
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.RIFF)
25
+ metadata = get_unified_metadata(test_file)
26
+ assert metadata.get(UnifiedMetadataKey.ARTISTS) == test_artists
27
+
28
+ def test_vorbis(self):
29
+ test_artists = ["Vorbis Artist 1", "Vorbis Artist 2"]
30
+ test_metadata = {UnifiedMetadataKey.ARTISTS: test_artists}
31
+ with temp_file_with_metadata({}, "flac") as test_file:
32
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.VORBIS)
33
+ metadata = get_unified_metadata(test_file)
34
+ assert metadata.get(UnifiedMetadataKey.ARTISTS) == test_artists
35
+
36
+ def test_id3v1(self):
37
+ test_artists = ["ID3v1 Artist"]
38
+ test_metadata = {UnifiedMetadataKey.ARTISTS: test_artists}
39
+ with temp_file_with_metadata({}, "mp3") as test_file:
40
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V1)
41
+ metadata = get_unified_metadata(test_file)
42
+ assert metadata.get(UnifiedMetadataKey.ARTISTS) == test_artists
43
+
44
+ def test_invalid_type_raises(self):
45
+ with temp_file_with_metadata({}, "mp3") as test_file, pytest.raises(InvalidMetadataFieldTypeError):
46
+ update_metadata(test_file, {UnifiedMetadataKey.ARTISTS: "Single Artist"})
@@ -0,0 +1,75 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.test.helpers.id3v2 import ID3v2MetadataSetter
5
+ from audiometa.test.helpers.riff.riff_metadata_getter import RIFFMetadataGetter
6
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
7
+ from audiometa.test.helpers.vorbis import VorbisMetadataSetter
8
+ from audiometa.utils.metadata_format import MetadataFormat
9
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
10
+
11
+
12
+ @pytest.mark.integration
13
+ class TestBpmDeleting:
14
+ def test_delete_bpm_id3v2(self):
15
+ with temp_file_with_metadata({}, "mp3") as test_file:
16
+ ID3v2MetadataSetter.set_bpm(test_file, 120)
17
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM) == 120
18
+
19
+ # Delete metadata using library API
20
+ update_metadata(test_file, {UnifiedMetadataKey.BPM: None}, metadata_format=MetadataFormat.ID3V2)
21
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM) is None
22
+
23
+ def test_delete_bpm_id3v1(self):
24
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
25
+
26
+ with (
27
+ temp_file_with_metadata({}, "mp3") as test_file,
28
+ pytest.raises(MetadataFieldNotSupportedByMetadataFormatError),
29
+ ):
30
+ update_metadata(test_file, {UnifiedMetadataKey.BPM: None}, metadata_format=MetadataFormat.ID3V1)
31
+
32
+ def test_delete_bpm_riff(self):
33
+ with temp_file_with_metadata({"bpm": 120}, "wav") as test_file:
34
+ raw_metadata = RIFFMetadataGetter.get_raw_metadata(test_file)
35
+ assert "ibpm=120" in raw_metadata
36
+
37
+ update_metadata(test_file, {UnifiedMetadataKey.BPM: None}, metadata_format=MetadataFormat.RIFF)
38
+ raw_metadata_after = RIFFMetadataGetter.get_raw_metadata(test_file)
39
+ assert "ibpm=120" not in raw_metadata_after
40
+
41
+ def test_delete_bpm_vorbis(self):
42
+ with temp_file_with_metadata({}, "flac") as test_file:
43
+ VorbisMetadataSetter.set_bpm(test_file, 120)
44
+ assert (
45
+ get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM, metadata_format=MetadataFormat.VORBIS)
46
+ == 120
47
+ )
48
+
49
+ update_metadata(test_file, {UnifiedMetadataKey.BPM: None}, metadata_format=MetadataFormat.VORBIS)
50
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM) is None
51
+
52
+ def test_delete_bpm_preserves_other_fields(self):
53
+ with temp_file_with_metadata({}, "mp3") as test_file:
54
+ ID3v2MetadataSetter.set_bpm(test_file, 120)
55
+ ID3v2MetadataSetter.set_title(test_file, "Test Title")
56
+ ID3v2MetadataSetter.set_artists(test_file, "Test Artist")
57
+
58
+ update_metadata(test_file, {UnifiedMetadataKey.BPM: None}, metadata_format=MetadataFormat.ID3V2)
59
+
60
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM) is None
61
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE) == "Test Title"
62
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Test Artist"]
63
+
64
+ def test_delete_bpm_already_none(self):
65
+ with temp_file_with_metadata({}, "mp3") as test_file:
66
+ update_metadata(test_file, {UnifiedMetadataKey.BPM: None}, metadata_format=MetadataFormat.ID3V2)
67
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM) is None
68
+
69
+ def test_delete_bpm_zero(self):
70
+ with temp_file_with_metadata({}, "mp3") as test_file:
71
+ ID3v2MetadataSetter.set_bpm(test_file, 0)
72
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM) == 0
73
+
74
+ update_metadata(test_file, {UnifiedMetadataKey.BPM: None}, metadata_format=MetadataFormat.ID3V2)
75
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM) is None
@@ -0,0 +1,32 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field
4
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
5
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
6
+ from audiometa.utils.metadata_format import MetadataFormat
7
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
8
+
9
+
10
+ @pytest.mark.integration
11
+ class TestBpmReading:
12
+ def test_id3v1(self):
13
+ with (
14
+ temp_file_with_metadata({"title": "Test Song"}, "id3v1") as test_file,
15
+ pytest.raises(MetadataFieldNotSupportedByMetadataFormatError),
16
+ ):
17
+ get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM, metadata_format=MetadataFormat.ID3V1)
18
+
19
+ def test_id3v2(self):
20
+ with temp_file_with_metadata({"title": "Test Song", "bpm": 999}, "id3v2.4") as test_file:
21
+ bpm = get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM, metadata_format=MetadataFormat.ID3V2)
22
+ assert bpm == 999
23
+
24
+ def test_vorbis(self):
25
+ with temp_file_with_metadata({"title": "Test Song", "bpm": 999}, "flac") as test_file:
26
+ bpm = get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM, metadata_format=MetadataFormat.VORBIS)
27
+ assert bpm == 999
28
+
29
+ def test_riff(self):
30
+ with temp_file_with_metadata({"title": "Test Song", "bpm": 999}, "wav") as test_file:
31
+ bpm = get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM, metadata_format=MetadataFormat.RIFF)
32
+ assert bpm == 999
@@ -0,0 +1,56 @@
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 TestBpmWriting:
11
+ def test_id3v2(self):
12
+ with temp_file_with_metadata({}, "mp3") as test_file:
13
+ test_bpm = 128
14
+ test_metadata = {UnifiedMetadataKey.BPM: test_bpm}
15
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V2)
16
+ bpm = get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM)
17
+ assert bpm == test_bpm
18
+
19
+ def test_riff(self):
20
+ with temp_file_with_metadata({}, "wav") as test_file:
21
+ test_bpm = 120
22
+ test_metadata = {UnifiedMetadataKey.BPM: test_bpm}
23
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.RIFF)
24
+
25
+ raw_metadata = get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM)
26
+ assert raw_metadata == test_bpm
27
+
28
+ def test_vorbis(self):
29
+ with temp_file_with_metadata({}, "flac") as test_file:
30
+ test_bpm = 140
31
+ test_metadata = {UnifiedMetadataKey.BPM: test_bpm}
32
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.VORBIS)
33
+ bpm = get_unified_metadata_field(test_file, UnifiedMetadataKey.BPM)
34
+ assert bpm == test_bpm
35
+
36
+ def test_id3v1(self):
37
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
38
+
39
+ with temp_file_with_metadata({}, "mp3") as test_file:
40
+ test_bpm = 128
41
+ test_metadata = {UnifiedMetadataKey.BPM: test_bpm}
42
+
43
+ # ID3v1 format raises exception for unsupported metadata when format is forced
44
+ with pytest.raises(
45
+ MetadataFieldNotSupportedByMetadataFormatError,
46
+ match="UnifiedMetadataKey.BPM metadata not supported by ID3v1 format",
47
+ ):
48
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V1)
49
+
50
+ def test_invalid_type_raises(self):
51
+ from audiometa.exceptions import InvalidMetadataFieldTypeError
52
+
53
+ with temp_file_with_metadata({}, "mp3") as test_file:
54
+ bad_metadata = {UnifiedMetadataKey.BPM: "not-an-int"}
55
+ with pytest.raises(InvalidMetadataFieldTypeError):
56
+ update_metadata(test_file, bad_metadata)