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,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 TestCommentDeleting:
15
+ def test_delete_comment_id3v2(self):
16
+ with temp_file_with_metadata({}, "mp3") as test_file:
17
+ ID3v2MetadataSetter.set_metadata(test_file, {"comment": "Test comment"})
18
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) == "Test comment"
19
+
20
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: None}, metadata_format=MetadataFormat.ID3V2)
21
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) is None
22
+
23
+ def test_delete_comment_id3v1(self):
24
+ with temp_file_with_metadata({}, "id3v1") as test_file:
25
+ ID3v1MetadataSetter.set_comment(test_file, "Test comment")
26
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) == "Test comment"
27
+
28
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: None}, metadata_format=MetadataFormat.ID3V1)
29
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) is None
30
+
31
+ def test_delete_comment_riff(self):
32
+ with temp_file_with_metadata({}, "wav") as test_file:
33
+ RIFFMetadataSetter.set_comment(test_file, "Test comment")
34
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) == "Test comment"
35
+
36
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: None}, metadata_format=MetadataFormat.RIFF)
37
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) is None
38
+
39
+ def test_delete_comment_vorbis(self):
40
+ with temp_file_with_metadata({}, "flac") as test_file:
41
+ VorbisMetadataSetter.set_comment(test_file, "Test comment")
42
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) == "Test comment"
43
+
44
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: None}, metadata_format=MetadataFormat.VORBIS)
45
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) is None
46
+
47
+ def test_delete_comment_preserves_other_fields(self):
48
+ with temp_file_with_metadata({}, "mp3") as test_file:
49
+ ID3v2MetadataSetter.set_metadata(test_file, {"comment": "Test comment"})
50
+ ID3v2MetadataSetter.set_title(test_file, "Test Title")
51
+ ID3v2MetadataSetter.set_artists(test_file, "Test Artist")
52
+
53
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: None}, metadata_format=MetadataFormat.ID3V2)
54
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: None}, metadata_format=MetadataFormat.ID3V2)
55
+
56
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) is None
57
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE) == "Test Title"
58
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Test Artist"]
59
+
60
+ def test_delete_comment_already_none(self):
61
+ with temp_file_with_metadata({}, "mp3") as test_file:
62
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: None}, metadata_format=MetadataFormat.ID3V2)
63
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) is None
64
+
65
+ def test_delete_comment_empty_string(self):
66
+ with temp_file_with_metadata({}, "mp3") as test_file:
67
+ update_metadata(test_file, {UnifiedMetadataKey.COMMENT: ""}, metadata_format=MetadataFormat.ID3V2)
68
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT) 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 TestCommentReading:
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
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
18
+ assert comment == "a" * 28
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
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
24
+ assert comment == "a" * 4000
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
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
30
+ assert comment == "a" * 1000
31
+
32
+ def test_riff(self):
33
+ with temp_file_with_metadata({"title": "Test Song"}, "wav") as test_file:
34
+ RIFFMetadataSetter.set_metadata(test_file, {"comment": "Test Comment RIFF"})
35
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
36
+ assert comment == "Test Comment RIFF"
@@ -0,0 +1,49 @@
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 TestCommentWriting:
11
+ def test_id3v2(self):
12
+ with temp_file_with_metadata({}, "mp3") as test_file:
13
+ test_comment = "Test Comment ID3v2"
14
+ test_metadata = {UnifiedMetadataKey.COMMENT: test_comment}
15
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V2)
16
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
17
+ assert comment == test_comment
18
+
19
+ def test_riff(self):
20
+ with temp_file_with_metadata({}, "wav") as test_file:
21
+ test_comment = "Test Comment RIFF"
22
+ test_metadata = {UnifiedMetadataKey.COMMENT: test_comment}
23
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.RIFF)
24
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
25
+ assert comment == test_comment
26
+
27
+ def test_vorbis(self):
28
+ with temp_file_with_metadata({}, "flac") as test_file:
29
+ test_comment = "Test Comment Vorbis"
30
+ test_metadata = {UnifiedMetadataKey.COMMENT: test_comment}
31
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.VORBIS)
32
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
33
+ assert comment == test_comment
34
+
35
+ def test_id3v1(self):
36
+ with temp_file_with_metadata({}, "mp3") as test_file:
37
+ test_comment = "Test Comment ID3v1"
38
+ test_metadata = {UnifiedMetadataKey.COMMENT: test_comment}
39
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V1)
40
+ comment = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMMENT)
41
+ assert comment == test_comment
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
+ bad_metadata = {UnifiedMetadataKey.COMMENT: 12345}
48
+ with pytest.raises(InvalidMetadataFieldTypeError):
49
+ update_metadata(test_file, bad_metadata)
@@ -0,0 +1,75 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.exceptions import MetadataFieldNotSupportedByMetadataFormatError
5
+ from audiometa.test.helpers.id3v2 import ID3v2MetadataGetter
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 TestComposerDeleting:
13
+ def test_delete_composer_id3v1(self):
14
+ with (
15
+ temp_file_with_metadata({}, "mp3") as test_file,
16
+ pytest.raises(
17
+ MetadataFieldNotSupportedByMetadataFormatError,
18
+ match="UnifiedMetadataKey.COMPOSERS metadata not supported by ID3v1 format",
19
+ ),
20
+ ):
21
+ update_metadata(
22
+ test_file,
23
+ {UnifiedMetadataKey.COMPOSERS: ["Test Composer"]},
24
+ metadata_format=MetadataFormat.ID3V1,
25
+ )
26
+
27
+ def test_delete_composer_id3v2(self):
28
+ with temp_file_with_metadata({"composer": "Test Composer"}, "id3v2.4") as test_file:
29
+ raw_metadata = ID3v2MetadataGetter.get_raw_metadata(test_file, version="2.4")
30
+ assert raw_metadata["TCOM"] == ["Test Composer"]
31
+
32
+ update_metadata(test_file, {UnifiedMetadataKey.COMPOSERS: None}, metadata_format=MetadataFormat.ID3V2)
33
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS) is None
34
+
35
+ def test_delete_composer_riff(self):
36
+ with temp_file_with_metadata({}, "wav") as test_file:
37
+ update_metadata(
38
+ test_file, {UnifiedMetadataKey.COMPOSERS: ["Test Composer"]}, metadata_format=MetadataFormat.RIFF
39
+ )
40
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS) == ["Test Composer"]
41
+
42
+ update_metadata(test_file, {UnifiedMetadataKey.COMPOSERS: None}, metadata_format=MetadataFormat.RIFF)
43
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS) is None
44
+
45
+ def test_delete_composer_vorbis(self):
46
+ with temp_file_with_metadata({}, "flac") as test_file:
47
+ update_metadata(
48
+ test_file, {UnifiedMetadataKey.COMPOSERS: ["Test Composer"]}, metadata_format=MetadataFormat.VORBIS
49
+ )
50
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS) == ["Test Composer"]
51
+
52
+ update_metadata(test_file, {UnifiedMetadataKey.COMPOSERS: None}, metadata_format=MetadataFormat.VORBIS)
53
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS) is None
54
+
55
+ def test_delete_composer_preserves_other_fields(self):
56
+ with temp_file_with_metadata({}, "mp3") as test_file:
57
+ update_metadata(
58
+ test_file,
59
+ {
60
+ UnifiedMetadataKey.COMPOSERS: ["Test Composer"],
61
+ UnifiedMetadataKey.TITLE: "Test Title",
62
+ UnifiedMetadataKey.ARTISTS: ["Test Artist"],
63
+ },
64
+ )
65
+
66
+ update_metadata(test_file, {UnifiedMetadataKey.COMPOSERS: None})
67
+
68
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS) is None
69
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE) == "Test Title"
70
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Test Artist"]
71
+
72
+ def test_delete_composer_already_none(self):
73
+ with temp_file_with_metadata({}, "mp3") as test_file:
74
+ update_metadata(test_file, {UnifiedMetadataKey.COMPOSERS: None})
75
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS) is None
@@ -0,0 +1,34 @@
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.temp_file_with_metadata import temp_file_with_metadata
7
+ from audiometa.test.helpers.vorbis import VorbisMetadataSetter
8
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
9
+
10
+
11
+ @pytest.mark.integration
12
+ class TestComposerReading:
13
+ def test_id3v1(self):
14
+ with temp_file_with_metadata({"title": "Test Song"}, "id3v1") as test_file:
15
+ ID3v1MetadataSetter.set_max_metadata(test_file)
16
+ composer = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS)
17
+ assert composer 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
+ composer = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS)
23
+ assert composer == ["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
+ composer = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS)
29
+ assert composer == ["a" * 1000]
30
+
31
+ def test_riff(self):
32
+ with temp_file_with_metadata({"title": "Test Song"}, "wav") as test_file:
33
+ composer = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS)
34
+ assert composer is None
@@ -0,0 +1,41 @@
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 TestComposerWriting:
11
+ def test_id3v2(self):
12
+ with temp_file_with_metadata({}, "mp3") as test_file:
13
+ test_composer = "Test Composer ID3v2"
14
+ test_metadata = {UnifiedMetadataKey.COMPOSERS: [test_composer]}
15
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V2)
16
+ composer = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS)
17
+ assert composer == [test_composer]
18
+
19
+ def test_riff(self):
20
+ with temp_file_with_metadata({}, "wav") as test_file:
21
+ test_composer = "Test Composer RIFF"
22
+ test_metadata = {UnifiedMetadataKey.COMPOSERS: [test_composer]}
23
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.RIFF)
24
+ composer = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS)
25
+ assert composer == [test_composer]
26
+
27
+ def test_vorbis(self):
28
+ with temp_file_with_metadata({}, "flac") as test_file:
29
+ test_composer = "Test Composer Vorbis"
30
+ test_metadata = {UnifiedMetadataKey.COMPOSERS: [test_composer]}
31
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.VORBIS)
32
+ composer = get_unified_metadata_field(test_file, UnifiedMetadataKey.COMPOSERS)
33
+ assert composer == [test_composer]
34
+
35
+ def test_invalid_type_raises(self):
36
+ from audiometa.exceptions import InvalidMetadataFieldTypeError
37
+
38
+ with temp_file_with_metadata({}, "mp3") as test_file:
39
+ bad_metadata = {UnifiedMetadataKey.COMPOSERS: 12345}
40
+ with pytest.raises(InvalidMetadataFieldTypeError):
41
+ update_metadata(test_file, bad_metadata)
@@ -0,0 +1,81 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
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 TestCopyrightDeleting:
12
+ def test_delete_copyright_id3v2(self):
13
+ with temp_file_with_metadata({}, "mp3") as test_file:
14
+ update_metadata(
15
+ test_file, {UnifiedMetadataKey.COPYRIGHT: "Test Copyright"}, metadata_format=MetadataFormat.ID3V2
16
+ )
17
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) == "Test Copyright"
18
+
19
+ update_metadata(test_file, {UnifiedMetadataKey.COPYRIGHT: None}, metadata_format=MetadataFormat.ID3V2)
20
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) is None
21
+
22
+ def test_delete_copyright_id3v1(self):
23
+ with (
24
+ temp_file_with_metadata({}, "mp3") as test_file,
25
+ pytest.raises(
26
+ MetadataFieldNotSupportedByMetadataFormatError,
27
+ match="UnifiedMetadataKey.COPYRIGHT metadata not supported by ID3v1 format",
28
+ ),
29
+ ):
30
+ update_metadata(
31
+ test_file,
32
+ {UnifiedMetadataKey.COPYRIGHT: "Test Copyright"},
33
+ metadata_format=MetadataFormat.ID3V1,
34
+ )
35
+
36
+ def test_delete_copyright_riff(self):
37
+ with temp_file_with_metadata({}, "wav") as test_file:
38
+ update_metadata(
39
+ test_file, {UnifiedMetadataKey.COPYRIGHT: "Test Copyright"}, metadata_format=MetadataFormat.RIFF
40
+ )
41
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) == "Test Copyright"
42
+
43
+ update_metadata(test_file, {UnifiedMetadataKey.COPYRIGHT: None}, metadata_format=MetadataFormat.RIFF)
44
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) is None
45
+
46
+ def test_delete_copyright_vorbis(self):
47
+ with temp_file_with_metadata({}, "flac") as test_file:
48
+ update_metadata(
49
+ test_file, {UnifiedMetadataKey.COPYRIGHT: "Test Copyright"}, metadata_format=MetadataFormat.VORBIS
50
+ )
51
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) == "Test Copyright"
52
+
53
+ update_metadata(test_file, {UnifiedMetadataKey.COPYRIGHT: None}, metadata_format=MetadataFormat.VORBIS)
54
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) is None
55
+
56
+ def test_delete_copyright_preserves_other_fields(self):
57
+ with temp_file_with_metadata({}, "mp3") as test_file:
58
+ update_metadata(
59
+ test_file,
60
+ {
61
+ UnifiedMetadataKey.COPYRIGHT: "Test Copyright",
62
+ UnifiedMetadataKey.TITLE: "Test Title",
63
+ UnifiedMetadataKey.ARTISTS: ["Test Artist"],
64
+ },
65
+ )
66
+
67
+ update_metadata(test_file, {UnifiedMetadataKey.COPYRIGHT: None})
68
+
69
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) is None
70
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE) == "Test Title"
71
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Test Artist"]
72
+
73
+ def test_delete_copyright_already_none(self):
74
+ with temp_file_with_metadata({}, "mp3") as test_file:
75
+ update_metadata(test_file, {UnifiedMetadataKey.COPYRIGHT: None})
76
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) is None
77
+
78
+ def test_delete_copyright_empty_string(self):
79
+ with temp_file_with_metadata({}, "mp3") as test_file:
80
+ update_metadata(test_file, {UnifiedMetadataKey.COPYRIGHT: ""}, metadata_format=MetadataFormat.ID3V2)
81
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT) is None
@@ -0,0 +1,35 @@
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 TestCopyrightReading:
12
+ def test_id3v1(self):
13
+ with (
14
+ temp_file_with_metadata({"title": "Test Song"}, "id3v1") as test_file,
15
+ pytest.raises(
16
+ MetadataFieldNotSupportedByMetadataFormatError,
17
+ match="UnifiedMetadataKey.COPYRIGHT metadata not supported by ID3v1 format",
18
+ ),
19
+ ):
20
+ get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT, metadata_format=MetadataFormat.ID3V1)
21
+
22
+ def test_id3v2(self):
23
+ with temp_file_with_metadata({"title": "Test Song", "copyright": "Test Copyright"}, "mp3") as test_file:
24
+ copyright_info = get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT)
25
+ assert copyright_info == "Test Copyright"
26
+
27
+ def test_vorbis(self):
28
+ with temp_file_with_metadata({"title": "Test Song", "copyright": "Test Copyright"}, "flac") as test_file:
29
+ copyright_info = get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT)
30
+ assert copyright_info == "Test Copyright"
31
+
32
+ def test_riff(self):
33
+ with temp_file_with_metadata({"title": "Test Song"}, "wav") as test_file:
34
+ copyright_info = get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT)
35
+ assert copyright_info is None
@@ -0,0 +1,41 @@
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 TestCopyrightWriting:
11
+ def test_id3v2(self):
12
+ with temp_file_with_metadata({}, "mp3") as test_file:
13
+ test_copyright = "© 2024 Test Label ID3v2"
14
+ test_metadata = {UnifiedMetadataKey.COPYRIGHT: test_copyright}
15
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.ID3V2)
16
+ copyright_info = get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT)
17
+ assert copyright_info == test_copyright
18
+
19
+ def test_riff(self):
20
+ with temp_file_with_metadata({}, "wav") as test_file:
21
+ test_copyright = "© 2024 Test Label RIFF"
22
+ test_metadata = {UnifiedMetadataKey.COPYRIGHT: test_copyright}
23
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.RIFF)
24
+ copyright_info = get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT)
25
+ assert copyright_info == test_copyright
26
+
27
+ def test_vorbis(self):
28
+ with temp_file_with_metadata({}, "flac") as test_file:
29
+ test_copyright = "© 2024 Test Label Vorbis"
30
+ test_metadata = {UnifiedMetadataKey.COPYRIGHT: test_copyright}
31
+ update_metadata(test_file, test_metadata, metadata_format=MetadataFormat.VORBIS)
32
+ copyright_info = get_unified_metadata_field(test_file, UnifiedMetadataKey.COPYRIGHT)
33
+ assert copyright_info == test_copyright
34
+
35
+ def test_invalid_type_raises(self):
36
+ from audiometa.exceptions import InvalidMetadataFieldTypeError
37
+
38
+ with temp_file_with_metadata({}, "mp3") as test_file:
39
+ bad_metadata = {UnifiedMetadataKey.COPYRIGHT: 123}
40
+ with pytest.raises(InvalidMetadataFieldTypeError):
41
+ update_metadata(test_file, bad_metadata)
@@ -0,0 +1,97 @@
1
+ import pytest
2
+
3
+ from audiometa import get_unified_metadata_field, update_metadata
4
+ from audiometa.test.helpers.temp_file_with_metadata import temp_file_with_metadata
5
+ from audiometa.utils.metadata_format import MetadataFormat
6
+ from audiometa.utils.unified_metadata_key import UnifiedMetadataKey
7
+
8
+
9
+ @pytest.mark.integration
10
+ class TestDiscNumberDeleting:
11
+ def test_delete_disc_number_id3v2(self):
12
+ with temp_file_with_metadata({}, "mp3") as test_file:
13
+ update_metadata(
14
+ test_file,
15
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
16
+ metadata_format=MetadataFormat.ID3V2,
17
+ )
18
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
19
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
20
+
21
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None}, metadata_format=MetadataFormat.ID3V2)
22
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
23
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
24
+
25
+ def test_delete_disc_total_only_id3v2(self):
26
+ with temp_file_with_metadata({}, "mp3") as test_file:
27
+ update_metadata(
28
+ test_file,
29
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
30
+ metadata_format=MetadataFormat.ID3V2,
31
+ )
32
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
33
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
34
+
35
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_TOTAL: None}, metadata_format=MetadataFormat.ID3V2)
36
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
37
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
38
+
39
+ def test_delete_disc_number_vorbis(self):
40
+ with temp_file_with_metadata({}, "flac") as test_file:
41
+ update_metadata(
42
+ test_file,
43
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
44
+ metadata_format=MetadataFormat.VORBIS,
45
+ )
46
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
47
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
48
+
49
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None}, metadata_format=MetadataFormat.VORBIS)
50
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
51
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
52
+
53
+ def test_delete_disc_total_only_vorbis(self):
54
+ with temp_file_with_metadata({}, "flac") as test_file:
55
+ update_metadata(
56
+ test_file,
57
+ {UnifiedMetadataKey.DISC_NUMBER: 1, UnifiedMetadataKey.DISC_TOTAL: 2},
58
+ metadata_format=MetadataFormat.VORBIS,
59
+ )
60
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
61
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) == 2
62
+
63
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_TOTAL: None}, metadata_format=MetadataFormat.VORBIS)
64
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 1
65
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
66
+
67
+ def test_delete_disc_number_preserves_other_fields(self):
68
+ with temp_file_with_metadata({}, "mp3") as test_file:
69
+ update_metadata(
70
+ test_file,
71
+ {
72
+ UnifiedMetadataKey.DISC_NUMBER: 1,
73
+ UnifiedMetadataKey.DISC_TOTAL: 2,
74
+ UnifiedMetadataKey.TITLE: "Test Title",
75
+ UnifiedMetadataKey.ARTISTS: ["Test Artist"],
76
+ },
77
+ )
78
+
79
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None})
80
+
81
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
82
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
83
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.TITLE) == "Test Title"
84
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.ARTISTS) == ["Test Artist"]
85
+
86
+ def test_delete_disc_number_already_none(self):
87
+ with temp_file_with_metadata({}, "mp3") as test_file:
88
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None})
89
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None
90
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_TOTAL) is None
91
+
92
+ def test_delete_disc_number_zero(self):
93
+ with temp_file_with_metadata({}, "mp3") as test_file:
94
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: 0}, metadata_format=MetadataFormat.ID3V2)
95
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) == 0
96
+ update_metadata(test_file, {UnifiedMetadataKey.DISC_NUMBER: None})
97
+ assert get_unified_metadata_field(test_file, UnifiedMetadataKey.DISC_NUMBER) is None