audiometa-python 1.1.2__tar.gz → 1.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (416) hide show
  1. {audiometa_python-1.1.2/audiometa_python.egg-info → audiometa_python-1.2.1}/PKG-INFO +4 -2
  2. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/README.md +3 -1
  3. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/cli.py +43 -5
  4. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/test_comprehensive.py +80 -74
  5. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/test_unified.py +20 -0
  6. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/test_formatting.py +21 -0
  7. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/test_help.py +17 -0
  8. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/os_dependencies_checker/macos.py +12 -6
  9. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/os_dependencies_checker/ubuntu.py +27 -1
  10. {audiometa_python-1.1.2 → audiometa_python-1.2.1/audiometa_python.egg-info}/PKG-INFO +4 -2
  11. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/pyproject.toml +1 -1
  12. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/LICENSE +0 -0
  13. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/__init__.py +0 -0
  14. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/__main__.py +0 -0
  15. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/_audio_file.py +0 -0
  16. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/exceptions.py +0 -0
  17. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_MetadataManager.py +0 -0
  18. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/__init__.py +0 -0
  19. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/_RatingSupportingMetadataManager.py +0 -0
  20. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/__init__.py +0 -0
  21. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/id3v2/_Id3v2Manager.py +0 -0
  22. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/id3v2/__init__.py +0 -0
  23. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/id3v2/_id3v1_preserver.py +0 -0
  24. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/id3v2/_id3v2_constants.py +0 -0
  25. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/id3v2/_id3v2_flac_handler.py +0 -0
  26. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/id3v2/_id3v2_reader.py +0 -0
  27. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/id3v2/_id3v2_writer.py +0 -0
  28. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/riff/_RiffManager.py +0 -0
  29. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/riff/__init__.py +0 -0
  30. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/riff/_riff_bext_chunk.py +0 -0
  31. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/riff/_riff_constants.py +0 -0
  32. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/riff/_riff_file_structure.py +0 -0
  33. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/riff/_riff_info_chunk.py +0 -0
  34. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/vorbis/_VorbisManager.py +0 -0
  35. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/vorbis/__init__.py +0 -0
  36. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/_rating_supporting/vorbis/_vorbis_constants.py +0 -0
  37. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/id3v1/_Id3v1Manager.py +0 -0
  38. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/id3v1/__init__.py +0 -0
  39. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/id3v1/_constants.py +0 -0
  40. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/id3v1/id3v1_raw_metadata.py +0 -0
  41. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/manager/id3v1/id3v1_raw_metadata_key.py +0 -0
  42. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/__init__.py +0 -0
  43. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/assets/create_test_files.py +0 -0
  44. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/__init__.py +0 -0
  45. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/common/__init__.py +0 -0
  46. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/common/audio_file_creator.py +0 -0
  47. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/common/external_tool_runner.py +0 -0
  48. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v1/__init__.py +0 -0
  49. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v1/id3v1_header_verifier.py +0 -0
  50. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v1/id3v1_metadata_deleter.py +0 -0
  51. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v1/id3v1_metadata_getter.py +0 -0
  52. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v1/id3v1_metadata_setter.py +0 -0
  53. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v2/__init__.py +0 -0
  54. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v2/id3v2_frame_manual_creator.py +0 -0
  55. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v2/id3v2_header_verifier.py +0 -0
  56. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v2/id3v2_metadata_deleter.py +0 -0
  57. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v2/id3v2_metadata_getter.py +0 -0
  58. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/id3v2/id3v2_metadata_setter.py +0 -0
  59. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/riff/__init__.py +0 -0
  60. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/riff/riff_header_verifier.py +0 -0
  61. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/riff/riff_manual_metadata_creator.py +0 -0
  62. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/riff/riff_metadata_deleter.py +0 -0
  63. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/riff/riff_metadata_getter.py +0 -0
  64. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/riff/riff_metadata_setter.py +0 -0
  65. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/scripts/__init__.py +0 -0
  66. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/technical_info_inspector.py +0 -0
  67. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/temp_file_with_metadata.py +0 -0
  68. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/vorbis/__init__.py +0 -0
  69. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/vorbis/vorbis_header_verifier.py +0 -0
  70. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/vorbis/vorbis_metadata_deleter.py +0 -0
  71. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/vorbis/vorbis_metadata_getter.py +0 -0
  72. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/helpers/vorbis/vorbis_metadata_setter.py +0 -0
  73. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/__init__.py +0 -0
  74. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/conftest.py +0 -0
  75. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/__init__.py +0 -0
  76. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/__init__.py +0 -0
  77. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/__init__.py +0 -0
  78. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_command_structure_errors.py +0 -0
  79. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_file_access_errors.py +0 -0
  80. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_format_output_errors.py +0 -0
  81. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_input_validation_errors.py +0 -0
  82. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_missing_fields_validation.py +0 -0
  83. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_multiple_files_errors.py +0 -0
  84. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_rating_validation.py +0 -0
  85. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/error_handling/test_year_validation.py +0 -0
  86. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/__init__.py +0 -0
  87. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/test_basic.py +0 -0
  88. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/test_formats.py +0 -0
  89. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/test_metadata_content.py +0 -0
  90. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/test_multiple_files.py +0 -0
  91. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/read/test_options.py +0 -0
  92. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/test_delete.py +0 -0
  93. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/__init__.py +0 -0
  94. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_basic.py +0 -0
  95. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_comprehensive.py +0 -0
  96. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_force_format.py +0 -0
  97. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_integer_fields.py +0 -0
  98. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_list_fields.py +0 -0
  99. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_rating.py +0 -0
  100. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_string_fields.py +0 -0
  101. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/cli/write/test_validation.py +0 -0
  102. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/scenarios/__init__.py +0 -0
  103. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/scenarios/test_user_scenarios.py +0 -0
  104. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/workflows/__init__.py +0 -0
  105. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/workflows/test_core_workflows.py +0 -0
  106. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/workflows/test_deletion_workflows.py +0 -0
  107. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/workflows/test_error_handling_workflows.py +0 -0
  108. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/workflows/test_format_specific_workflows.py +0 -0
  109. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/e2e/workflows/test_rating_workflows.py +0 -0
  110. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/__init__.py +0 -0
  111. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/__init__.py +0 -0
  112. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/flac/__init__.py +0 -0
  113. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_delete_all.py +0 -0
  114. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_all.py +0 -0
  115. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_reading_field.py +0 -0
  116. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/flac/test_flac_writing.py +0 -0
  117. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/mp3/__init__.py +0 -0
  118. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_delete_all.py +0 -0
  119. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_all.py +0 -0
  120. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_reading_field.py +0 -0
  121. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/mp3/test_mp3_writing.py +0 -0
  122. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/wav/__init__.py +0 -0
  123. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_delete_all.py +0 -0
  124. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_all.py +0 -0
  125. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_reading_field.py +0 -0
  126. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/audio_format/wav/test_wav_writing.py +0 -0
  127. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/conftest.py +0 -0
  128. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/delete_all_metadata/__init__.py +0 -0
  129. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_all.py +0 -0
  130. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/delete_all_metadata/test_audio_format_header_deletion.py +0 -0
  131. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/delete_all_metadata/test_basic_functionality.py +0 -0
  132. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/delete_all_metadata/test_error_handling.py +0 -0
  133. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/encoding/__init__.py +0 -0
  134. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/encoding/test_encoding.py +0 -0
  135. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/encoding/test_special_characters_edge_cases.py +0 -0
  136. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/__init__.py +0 -0
  137. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/options/__init__.py +0 -0
  138. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/options/test_include_headers.py +0 -0
  139. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/options/test_include_technical.py +0 -0
  140. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_audio_formats.py +0 -0
  141. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_binary_data_filtering.py +0 -0
  142. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_consistency.py +0 -0
  143. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_edge_cases.py +0 -0
  144. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_error_handling.py +0 -0
  145. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_get_full_metadata.py +0 -0
  146. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_performance.py +0 -0
  147. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_raw_metadata_includes_unsupported_tags.py +0 -0
  148. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_riff_bext.py +0 -0
  149. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/get_full_metadata/test_structure.py +0 -0
  150. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/__init__.py +0 -0
  151. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album/__init__.py +0 -0
  152. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album/test_deleting.py +0 -0
  153. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album/test_reading.py +0 -0
  154. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album/test_writing.py +0 -0
  155. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album_artists/__init__.py +0 -0
  156. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_deleting.py +0 -0
  157. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_reading.py +0 -0
  158. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/album_artists/test_writing.py +0 -0
  159. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/artists/__init__.py +0 -0
  160. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/artists/test_deleting.py +0 -0
  161. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/artists/test_reading.py +0 -0
  162. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/artists/test_writing.py +0 -0
  163. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/bpm/__init__.py +0 -0
  164. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/bpm/test_deleting.py +0 -0
  165. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/bpm/test_reading.py +0 -0
  166. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/bpm/test_writing.py +0 -0
  167. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/comment/__init__.py +0 -0
  168. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/comment/test_deleting.py +0 -0
  169. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/comment/test_reading.py +0 -0
  170. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/comment/test_writing.py +0 -0
  171. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/composer/__init__.py +0 -0
  172. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/composer/test_deleting.py +0 -0
  173. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/composer/test_reading.py +0 -0
  174. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/composer/test_writing.py +0 -0
  175. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/copyright/__init__.py +0 -0
  176. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/copyright/test_deleting.py +0 -0
  177. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/copyright/test_reading.py +0 -0
  178. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/copyright/test_writing.py +0 -0
  179. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/description/__init__.py +0 -0
  180. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/description/test_deleting.py +0 -0
  181. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/description/test_reading.py +0 -0
  182. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/description/test_writing.py +0 -0
  183. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/disc_number/__init__.py +0 -0
  184. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_deleting.py +0 -0
  185. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_reading.py +0 -0
  186. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/disc_number/test_writing.py +0 -0
  187. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/__init__.py +0 -0
  188. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_deleting.py +0 -0
  189. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_reading.py +0 -0
  190. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/field_not_supported/test_writing.py +0 -0
  191. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/__init__.py +0 -0
  192. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/reading/__init__.py +0 -0
  193. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/__init__.py +0 -0
  194. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v1_reading.py +0 -0
  195. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_id3v2_reading.py +0 -0
  196. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_riff_reading.py +0 -0
  197. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/reading/metadata_format/test_vorbis_reading.py +0 -0
  198. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/reading/test_smart_reading.py +0 -0
  199. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/test_deleting.py +0 -0
  200. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/genre/test_writing.py +0 -0
  201. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/isrc/__init__.py +0 -0
  202. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/isrc/test_deleting.py +0 -0
  203. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/isrc/test_reading.py +0 -0
  204. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/isrc/test_writing.py +0 -0
  205. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/language/__init__.py +0 -0
  206. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/language/test_deleting.py +0 -0
  207. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/language/test_reading.py +0 -0
  208. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/language/test_writing.py +0 -0
  209. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/lyrics/__init__.py +0 -0
  210. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_deleting.py +0 -0
  211. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_reading.py +0 -0
  212. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/lyrics/test_writing.py +0 -0
  213. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/__init__.py +0 -0
  214. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/test_deleting.py +0 -0
  215. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/test_reading.py +0 -0
  216. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_artistid/test_writing.py +0 -0
  217. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/__init__.py +0 -0
  218. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/test_deleting.py +0 -0
  219. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/test_reading.py +0 -0
  220. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/musicbrainz_trackid/test_writing.py +0 -0
  221. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/originator/__init__.py +0 -0
  222. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/originator/test_deleting.py +0 -0
  223. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/originator/test_reading.py +0 -0
  224. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/originator/test_writing.py +0 -0
  225. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/publisher/__init__.py +0 -0
  226. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/publisher/test_deleting.py +0 -0
  227. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/publisher/test_reading.py +0 -0
  228. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/publisher/test_writing.py +0 -0
  229. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/__init__.py +0 -0
  230. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/reading/__init__.py +0 -0
  231. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_100_proportional.py +0 -0
  232. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_non_proportional.py +0 -0
  233. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/reading/test_base_255_proportional.py +0 -0
  234. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/test_deleting.py +0 -0
  235. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/test_error_handling.py +0 -0
  236. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/writing/__init__.py +0 -0
  237. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/__init__.py +0 -0
  238. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_id3v2.py +0 -0
  239. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_riff.py +0 -0
  240. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/writing/metadata_format/test_vorbis.py +0 -0
  241. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/rating/writing/test_comprehensive.py +0 -0
  242. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/release_date/__init__.py +0 -0
  243. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/release_date/test_deleting.py +0 -0
  244. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/release_date/test_error_handling.py +0 -0
  245. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/release_date/test_reading.py +0 -0
  246. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/release_date/test_writing.py +0 -0
  247. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/test_metadata_field_validation.py +0 -0
  248. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/title/__init__.py +0 -0
  249. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/title/test_deleting.py +0 -0
  250. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/title/test_error_handling.py +0 -0
  251. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/title/test_reading.py +0 -0
  252. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/title/test_writing.py +0 -0
  253. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/track_number/__init__.py +0 -0
  254. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/track_number/reading/__init__.py +0 -0
  255. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_edge_cases.py +0 -0
  256. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/track_number/reading/test_metadata_format.py +0 -0
  257. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/track_number/test_deleting.py +0 -0
  258. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/metadata_field/track_number/test_writing.py +0 -0
  259. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/__init__.py +0 -0
  260. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/__init__.py +0 -0
  261. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/__init__.py +0 -0
  262. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v1.py +0 -0
  263. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_3.py +0 -0
  264. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_id3v2_4.py +0 -0
  265. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_riff.py +0 -0
  266. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/metadata_format/test_vorbis.py +0 -0
  267. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/test_performance_large_data.py +0 -0
  268. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/test_smart_parsing_scenarios.py +0 -0
  269. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/reading/test_unicode_handling.py +0 -0
  270. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/__init__.py +0 -0
  271. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/__init__.py +0 -0
  272. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v1.py +0 -0
  273. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_3.py +0 -0
  274. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_id3v2_4.py +0 -0
  275. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_riff.py +0 -0
  276. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/metadata_format/test_vorbis.py +0 -0
  277. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/test_error_handling.py +0 -0
  278. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/multiple_values/writing/test_large_values.py +0 -0
  279. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/reading/__init__.py +0 -0
  280. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/reading/test_read_multiple_metadata.py +0 -0
  281. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/reading/test_reading_error_handling.py +0 -0
  282. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/real_audio_files/__init__.py +0 -0
  283. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/real_audio_files/test_reading.py +0 -0
  284. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/real_audio_files/test_writing.py +0 -0
  285. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/__init__.py +0 -0
  286. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/__init__.py +0 -0
  287. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/conftest.py +0 -0
  288. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/__init__.py +0 -0
  289. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_audio_data_corruption.py +0 -0
  290. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_file.py +0 -0
  291. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_invalid_md5.py +0 -0
  292. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/__init__.py +0 -0
  293. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_invalid_with_metadata_combinations.py +0 -0
  294. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_state_precedence.py +0 -0
  295. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_unset_with_metadata_combinations.py +0 -0
  296. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_validation_fails_with_id3v1.py +0 -0
  297. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_validation_with_id3v2_only.py +0 -0
  298. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_validation_works_without_id3v1.py +0 -0
  299. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_metadata_combinations/test_md5_with_metadata_combinations.py +0 -0
  300. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_checking/test_unset_md5.py +0 -0
  301. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/__init__.py +0 -0
  302. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_delete_original.py +0 -0
  303. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/__init__.py +0 -0
  304. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/test_flipped_md5.py +0 -0
  305. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/test_partial_md5.py +0 -0
  306. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_invalid_md5/test_random_md5.py +0 -0
  307. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_md5_repair_with_metadata.py +0 -0
  308. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_non_flac_error.py +0 -0
  309. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/flac_md5/md5_repair/test_unset_md5.py +0 -0
  310. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/test_bitrate.py +0 -0
  311. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/test_channels.py +0 -0
  312. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/test_duration_in_sec.py +0 -0
  313. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/technical_info/test_sample_rate.py +0 -0
  314. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/test_audio_file.py +0 -0
  315. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/test_audio_format_readable_after_update_all_metadata_formats.py +0 -0
  316. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/__init__.py +0 -0
  317. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/test_error_handling.py +0 -0
  318. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/test_forced_format.py +0 -0
  319. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/test_multiple_format_preservation.py +0 -0
  320. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/test_partial_update.py +0 -0
  321. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/__init__.py +0 -0
  322. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/__init__.py +0 -0
  323. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/test_flac_sync.py +0 -0
  324. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/test_mp3_sync.py +0 -0
  325. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/sync_strategy/test_wav_sync.py +0 -0
  326. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/test_cleanup_strategy.py +0 -0
  327. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/test_preserve_strategy.py +0 -0
  328. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/__init__.py +0 -0
  329. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_fail_behavior.py +0 -0
  330. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_no_writing_on_failure.py +0 -0
  331. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/integration/writing/writing_strategies/unsupported_fields/test_strategy_specific.py +0 -0
  332. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/__init__.py +0 -0
  333. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/__init__.py +0 -0
  334. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/__init__.py +0 -0
  335. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/test_bitrate.py +0 -0
  336. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/test_channels.py +0 -0
  337. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/test_duration_in_sec.py +0 -0
  338. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/test_error_handling.py +0 -0
  339. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/test_file_size.py +0 -0
  340. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/test_format_name.py +0 -0
  341. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/technical_info/test_sample_rate.py +0 -0
  342. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/test_context_manager.py +0 -0
  343. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/test_file_validation.py +0 -0
  344. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/test_is_audio_file.py +0 -0
  345. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/test_operations.py +0 -0
  346. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/audio_file/test_path_handling.py +0 -0
  347. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/cli/__init__.py +0 -0
  348. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/cli/test_expand_file_patterns.py +0 -0
  349. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/__init__.py +0 -0
  350. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/conftest.py +0 -0
  351. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/header_info/__init__.py +0 -0
  352. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v1.py +0 -0
  353. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_id3v2.py +0 -0
  354. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_riff.py +0 -0
  355. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_riff_info_chunk_fourcc.py +0 -0
  356. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/header_info/test_vorbis.py +0 -0
  357. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/__init__.py +0 -0
  358. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/disc_number/__init__.py +0 -0
  359. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/disc_number/test_disc_number_validation.py +0 -0
  360. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/isrc/__init__.py +0 -0
  361. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/isrc/test_isrc_format_validation.py +0 -0
  362. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/isrc/test_isrc_type_validation.py +0 -0
  363. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/__init__.py +0 -0
  364. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/__init__.py +0 -0
  365. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/reading/test_smart_parsing.py +0 -0
  366. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/__init__.py +0 -0
  367. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_separator_selection.py +0 -0
  368. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/multiple_values/writing/test_value_filtering.py +0 -0
  369. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_artistid/__init__.py +0 -0
  370. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_artistid/test_musicbrainz_artistid_format_validation.py +0 -0
  371. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_artistid/test_musicbrainz_artistid_type_validation.py +0 -0
  372. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_trackid/__init__.py +0 -0
  373. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_trackid/test_musicbrainz_trackid_format_validation.py +0 -0
  374. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_trackid/test_musicbrainz_trackid_type_validation.py +0 -0
  375. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_uuid/__init__.py +0 -0
  376. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/musicbrainz_uuid/test_uuid_format_validation.py +0 -0
  377. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/__init__.py +0 -0
  378. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/__init__.py +0 -0
  379. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_normalization.py +0 -0
  380. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/reading/test_profiles_values.py +0 -0
  381. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/test_rating_validation.py +0 -0
  382. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/__init__.py +0 -0
  383. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_configuration_error.py +0 -0
  384. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_validation.py +0 -0
  385. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/rating/writing/test_writing_profiles.py +0 -0
  386. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/release_date/__init__.py +0 -0
  387. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/release_date/test_date_format_validation.py +0 -0
  388. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_type_validation_exception.py +0 -0
  389. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/test_validation.py +0 -0
  390. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/track_number/__init__.py +0 -0
  391. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/metadata_field/track_number/test_track_number_validation.py +0 -0
  392. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/test_metadata_format_managers_write_and_read.py +0 -0
  393. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/metadata_managers/test_riff_configuration_error.py +0 -0
  394. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/utils/__init__.py +0 -0
  395. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/test/tests/unit/utils/test_raw_metadata_sanitizer.py +0 -0
  396. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/__init__.py +0 -0
  397. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/flac_md5_state.py +0 -0
  398. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/id3v1_genre_code_map.py +0 -0
  399. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/metadata_format.py +0 -0
  400. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/metadata_writing_strategy.py +0 -0
  401. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/mutagen_exception_handler.py +0 -0
  402. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/os_dependencies_checker/__init__.py +0 -0
  403. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/os_dependencies_checker/base.py +0 -0
  404. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/os_dependencies_checker/config.py +0 -0
  405. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/os_dependencies_checker/windows.py +0 -0
  406. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/rating_profiles.py +0 -0
  407. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/raw_metadata_sanitizer.py +0 -0
  408. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/tool_path_resolver.py +0 -0
  409. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/types.py +0 -0
  410. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa/utils/unified_metadata_key.py +0 -0
  411. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa_python.egg-info/SOURCES.txt +0 -0
  412. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa_python.egg-info/dependency_links.txt +0 -0
  413. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa_python.egg-info/entry_points.txt +0 -0
  414. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa_python.egg-info/requires.txt +0 -0
  415. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/audiometa_python.egg-info/top_level.txt +0 -0
  416. {audiometa_python-1.1.2 → audiometa_python-1.2.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: audiometa-python
3
- Version: 1.1.2
3
+ Version: 1.2.1
4
4
  Summary: A comprehensive Python library for reading and writing audio metadata across multiple formats
5
5
  Author: AudioMeta Python Contributors
6
6
  Author-email: Andreas Garcia <garcia.andreas.1991@gmail.com>
@@ -1429,11 +1429,13 @@ AudioMeta provides a powerful command-line interface for quick metadata operatio
1429
1429
 
1430
1430
  ### Installation {#cli-installation}
1431
1431
 
1432
- After installing the package, the `audiometa` command will be available:
1432
+ After installing the package, the `audiometa` command will be available. Commands: `read`, `unified`, `write`, `delete`, `help`. Use `audiometa --help` or `audiometa help` for main help; `audiometa help read` (or another command) for subcommand help.
1433
1433
 
1434
1434
  ```bash
1435
1435
  pip install audiometa-python
1436
1436
  audiometa --help
1437
+ # or: audiometa help
1438
+ # or: audiometa help read
1437
1439
  ```
1438
1440
 
1439
1441
  ### Basic Usage
@@ -1387,11 +1387,13 @@ AudioMeta provides a powerful command-line interface for quick metadata operatio
1387
1387
 
1388
1388
  ### Installation {#cli-installation}
1389
1389
 
1390
- After installing the package, the `audiometa` command will be available:
1390
+ After installing the package, the `audiometa` command will be available. Commands: `read`, `unified`, `write`, `delete`, `help`. Use `audiometa --help` or `audiometa help` for main help; `audiometa help read` (or another command) for subcommand help.
1391
1391
 
1392
1392
  ```bash
1393
1393
  pip install audiometa-python
1394
1394
  audiometa --help
1395
+ # or: audiometa help
1396
+ # or: audiometa help read
1395
1397
  ```
1396
1398
 
1397
1399
  ### Basic Usage
@@ -24,19 +24,31 @@ from audiometa.utils.metadata_format import MetadataFormat
24
24
  from audiometa.utils.types import UnifiedMetadata
25
25
 
26
26
 
27
+ def _data_for_serialization(data: Any) -> Any:
28
+ """Convert data to a form suitable for YAML/JSON (UnifiedMetadataKey keys as strings)."""
29
+ if isinstance(data, dict):
30
+ return {
31
+ (k.value if isinstance(k, UnifiedMetadataKey) else k): _data_for_serialization(v) for k, v in data.items()
32
+ }
33
+ if isinstance(data, list):
34
+ return [_data_for_serialization(item) for item in data]
35
+ return data
36
+
37
+
27
38
  def format_output(data: Any, output_format: str) -> str:
28
39
  """Format output data according to specified format."""
40
+ serializable = _data_for_serialization(data)
29
41
  if output_format == "json":
30
- return json.dumps(data, indent=2)
42
+ return json.dumps(serializable, indent=2)
31
43
  if output_format == "yaml":
32
44
  try:
33
45
  import yaml # type: ignore[import-untyped]
34
46
 
35
- result = yaml.dump(data, default_flow_style=False)
47
+ result = yaml.dump(serializable, default_flow_style=False)
36
48
  return str(result) if result is not None else ""
37
49
  except ImportError:
38
50
  sys.stderr.write("Warning: PyYAML not installed, falling back to JSON\n")
39
- return json.dumps(data, indent=2)
51
+ return json.dumps(serializable, indent=2)
40
52
  elif output_format == "table":
41
53
  return format_as_table(data)
42
54
  else:
@@ -107,7 +119,8 @@ def format_as_table(data: dict[str, Any]) -> str:
107
119
  lines.append("=== UNIFIED METADATA ===")
108
120
  for key, value in data["unified_metadata"].items():
109
121
  if value is not None:
110
- lines.append(f"{key:20}: {value}")
122
+ label = key.value if isinstance(key, UnifiedMetadataKey) else str(key)
123
+ lines.append(f"{label:20}: {value}")
111
124
  lines.append("")
112
125
 
113
126
  if "technical_info" in data:
@@ -124,7 +137,8 @@ def format_as_table(data: dict[str, Any]) -> str:
124
137
  lines.append(f"\n{metadata_format_name.upper()}:")
125
138
  for key, value in format_data.items():
126
139
  if value is not None:
127
- lines.append(f" {key:18}: {value}")
140
+ label = key.value if isinstance(key, UnifiedMetadataKey) else str(key)
141
+ lines.append(f" {label:18}: {value}")
128
142
 
129
143
  return "\n".join(lines)
130
144
 
@@ -378,6 +392,14 @@ Examples:
378
392
 
379
393
  subparsers = parser.add_subparsers(dest="command", help="Available commands")
380
394
 
395
+ help_parser = subparsers.add_parser("help", help="Show help and exit")
396
+ help_parser.add_argument(
397
+ "subcommand",
398
+ nargs="?",
399
+ choices=["read", "unified", "write", "delete"],
400
+ help="Subcommand to show help for",
401
+ )
402
+
381
403
  # Read command
382
404
  read_parser = subparsers.add_parser("read", help="Read metadata from audio file(s)")
383
405
  read_parser.add_argument("files", nargs="+", help="Audio file(s) or pattern(s)")
@@ -489,6 +511,18 @@ Examples:
489
511
  return parser
490
512
 
491
513
 
514
+ def _print_cli_help(parser: argparse.ArgumentParser, subcommand: str | None) -> None:
515
+ subparsers_action = next(
516
+ (a for a in parser._actions if getattr(a, "dest", None) == "command"),
517
+ None,
518
+ )
519
+ subparsers_choices = getattr(subparsers_action, "choices", None) if subparsers_action else None
520
+ if subcommand and subparsers_choices and subcommand in subparsers_choices:
521
+ subparsers_choices[subcommand].print_help()
522
+ else:
523
+ parser.print_help()
524
+
525
+
492
526
  def main() -> None:
493
527
  """Main CLI entry point."""
494
528
  parser = _create_parser()
@@ -498,6 +532,10 @@ def main() -> None:
498
532
  parser.print_help()
499
533
  sys.exit(1)
500
534
 
535
+ if args.command == "help":
536
+ _print_cli_help(parser, getattr(args, "subcommand", None))
537
+ sys.exit(0)
538
+
501
539
  try:
502
540
  args.func(args)
503
541
  except KeyboardInterrupt:
@@ -49,26 +49,26 @@ class TestCLIReadComprehensive:
49
49
  data = json.loads(result.stdout)
50
50
  unified = data.get("unified_metadata", {})
51
51
 
52
- assert unified.get(UnifiedMetadataKey.TITLE) == "Comprehensive Test Title"
53
- assert unified.get(UnifiedMetadataKey.ARTISTS) == ["Artist One", "Artist Two"]
54
- assert unified.get(UnifiedMetadataKey.ALBUM) == "Test Album"
55
- assert unified.get(UnifiedMetadataKey.ALBUM_ARTISTS) == ["Album Artist"]
56
- assert unified.get(UnifiedMetadataKey.RELEASE_DATE) == "2024"
57
- assert unified.get(UnifiedMetadataKey.GENRES_NAMES) == ["Rock", "Blues"]
58
- assert unified.get(UnifiedMetadataKey.TRACK_NUMBER) == "5/12"
59
- assert unified.get(UnifiedMetadataKey.DISC_NUMBER) == 1
60
- assert unified.get(UnifiedMetadataKey.DISC_TOTAL) == 2
61
- assert unified.get(UnifiedMetadataKey.RATING) == 85
62
- assert unified.get(UnifiedMetadataKey.BPM) == 120
63
- assert unified.get(UnifiedMetadataKey.LANGUAGE) == "eng"
64
- assert unified.get(UnifiedMetadataKey.COMPOSERS) == ["Composer One", "Composer Two"]
65
- assert unified.get(UnifiedMetadataKey.PUBLISHER) == "Test Publisher"
66
- assert unified.get(UnifiedMetadataKey.COPYRIGHT) == "© 2024"
67
- assert unified.get(UnifiedMetadataKey.UNSYNCHRONIZED_LYRICS) == "Test lyrics"
68
- assert unified.get(UnifiedMetadataKey.COMMENT) == "Test comment"
69
- assert unified.get(UnifiedMetadataKey.ISRC) == "USRC17607839"
70
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID) == "9d6f6f7c-9d52-4c76-8f9e-01d18d8f8ec6"
71
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS) == [
52
+ assert unified.get(UnifiedMetadataKey.TITLE.value) == "Comprehensive Test Title"
53
+ assert unified.get(UnifiedMetadataKey.ARTISTS.value) == ["Artist One", "Artist Two"]
54
+ assert unified.get(UnifiedMetadataKey.ALBUM.value) == "Test Album"
55
+ assert unified.get(UnifiedMetadataKey.ALBUM_ARTISTS.value) == ["Album Artist"]
56
+ assert unified.get(UnifiedMetadataKey.RELEASE_DATE.value) == "2024"
57
+ assert unified.get(UnifiedMetadataKey.GENRES_NAMES.value) == ["Rock", "Blues"]
58
+ assert unified.get(UnifiedMetadataKey.TRACK_NUMBER.value) == "5/12"
59
+ assert unified.get(UnifiedMetadataKey.DISC_NUMBER.value) == 1
60
+ assert unified.get(UnifiedMetadataKey.DISC_TOTAL.value) == 2
61
+ assert unified.get(UnifiedMetadataKey.RATING.value) == 85
62
+ assert unified.get(UnifiedMetadataKey.BPM.value) == 120
63
+ assert unified.get(UnifiedMetadataKey.LANGUAGE.value) == "eng"
64
+ assert unified.get(UnifiedMetadataKey.COMPOSERS.value) == ["Composer One", "Composer Two"]
65
+ assert unified.get(UnifiedMetadataKey.PUBLISHER.value) == "Test Publisher"
66
+ assert unified.get(UnifiedMetadataKey.COPYRIGHT.value) == "© 2024"
67
+ assert unified.get(UnifiedMetadataKey.UNSYNCHRONIZED_LYRICS.value) == "Test lyrics"
68
+ assert unified.get(UnifiedMetadataKey.COMMENT.value) == "Test comment"
69
+ assert unified.get(UnifiedMetadataKey.ISRC.value) == "USRC17607839"
70
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID.value) == "9d6f6f7c-9d52-4c76-8f9e-01d18d8f8ec6"
71
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS.value) == [
72
72
  "9d6f6f7c-9d52-4c76-8f9e-01d18d8f8ec6",
73
73
  "aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee",
74
74
  ]
@@ -108,24 +108,26 @@ class TestCLIReadComprehensive:
108
108
  data = json.loads(result.stdout)
109
109
  unified = data.get("unified_metadata", {})
110
110
 
111
- assert unified.get(UnifiedMetadataKey.TITLE) == "FLAC Comprehensive Test"
112
- assert unified.get(UnifiedMetadataKey.ARTISTS) == ["FLAC Artist"]
113
- assert unified.get(UnifiedMetadataKey.ALBUM) == "FLAC Album"
114
- assert unified.get(UnifiedMetadataKey.TRACK_NUMBER) == "3/10"
115
- assert unified.get(UnifiedMetadataKey.DISC_NUMBER) == 1
116
- assert unified.get(UnifiedMetadataKey.DISC_TOTAL) == 2
117
- assert unified.get(UnifiedMetadataKey.BPM) == 140
118
- assert unified.get(UnifiedMetadataKey.LANGUAGE) == "eng"
119
- assert unified.get(UnifiedMetadataKey.COMPOSERS) == ["FLAC Composer"]
120
- assert unified.get(UnifiedMetadataKey.PUBLISHER) == "FLAC Publisher"
121
- assert unified.get(UnifiedMetadataKey.COPYRIGHT) == "© FLAC"
122
- assert unified.get(UnifiedMetadataKey.UNSYNCHRONIZED_LYRICS) == "FLAC lyrics"
123
- assert unified.get(UnifiedMetadataKey.COMMENT) == "FLAC comment"
124
- assert unified.get(UnifiedMetadataKey.DESCRIPTION) == "FLAC description"
125
- assert unified.get(UnifiedMetadataKey.REPLAYGAIN) == "+2.5 dB"
126
- assert unified.get(UnifiedMetadataKey.ISRC) == "FRXXX1800001"
127
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID) == "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
128
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS) == ["a1b2c3d4-e5f6-7890-abcd-ef1234567890"]
111
+ assert unified.get(UnifiedMetadataKey.TITLE.value) == "FLAC Comprehensive Test"
112
+ assert unified.get(UnifiedMetadataKey.ARTISTS.value) == ["FLAC Artist"]
113
+ assert unified.get(UnifiedMetadataKey.ALBUM.value) == "FLAC Album"
114
+ assert unified.get(UnifiedMetadataKey.TRACK_NUMBER.value) == "3/10"
115
+ assert unified.get(UnifiedMetadataKey.DISC_NUMBER.value) == 1
116
+ assert unified.get(UnifiedMetadataKey.DISC_TOTAL.value) == 2
117
+ assert unified.get(UnifiedMetadataKey.BPM.value) == 140
118
+ assert unified.get(UnifiedMetadataKey.LANGUAGE.value) == "eng"
119
+ assert unified.get(UnifiedMetadataKey.COMPOSERS.value) == ["FLAC Composer"]
120
+ assert unified.get(UnifiedMetadataKey.PUBLISHER.value) == "FLAC Publisher"
121
+ assert unified.get(UnifiedMetadataKey.COPYRIGHT.value) == "© FLAC"
122
+ assert unified.get(UnifiedMetadataKey.UNSYNCHRONIZED_LYRICS.value) == "FLAC lyrics"
123
+ assert unified.get(UnifiedMetadataKey.COMMENT.value) == "FLAC comment"
124
+ assert unified.get(UnifiedMetadataKey.DESCRIPTION.value) == "FLAC description"
125
+ assert unified.get(UnifiedMetadataKey.REPLAYGAIN.value) == "+2.5 dB"
126
+ assert unified.get(UnifiedMetadataKey.ISRC.value) == "FRXXX1800001"
127
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID.value) == "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
128
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS.value) == [
129
+ "a1b2c3d4-e5f6-7890-abcd-ef1234567890"
130
+ ]
129
131
  # ARCHIVAL_LOCATION is not supported by Vorbis format (FLAC)
130
132
 
131
133
  def test_cli_read_all_fields_comprehensive_wav(self):
@@ -160,22 +162,24 @@ class TestCLIReadComprehensive:
160
162
  data = json.loads(result.stdout)
161
163
  unified = data.get("unified_metadata", {})
162
164
 
163
- assert unified.get(UnifiedMetadataKey.TITLE) == "WAV Comprehensive Test"
164
- assert unified.get(UnifiedMetadataKey.ARTISTS) == ["WAV Artist"]
165
- assert unified.get(UnifiedMetadataKey.ALBUM) == "WAV Album"
166
- assert unified.get(UnifiedMetadataKey.RELEASE_DATE) == "2024"
167
- assert unified.get(UnifiedMetadataKey.GENRES_NAMES) == ["Rock"]
168
- assert unified.get(UnifiedMetadataKey.RATING) == 100
169
- assert unified.get(UnifiedMetadataKey.BPM) == 120
170
- assert unified.get(UnifiedMetadataKey.LANGUAGE) == "eng"
171
- assert unified.get(UnifiedMetadataKey.COMPOSERS) == ["WAV Composer"]
172
- assert unified.get(UnifiedMetadataKey.COPYRIGHT) == "© WAV"
173
- assert unified.get(UnifiedMetadataKey.COMMENT) == "WAV comment"
174
- assert unified.get(UnifiedMetadataKey.DESCRIPTION) == "WAV description"
175
- assert unified.get(UnifiedMetadataKey.ORIGINATOR) == "WAV originator"
176
- assert unified.get(UnifiedMetadataKey.ISRC) == "GBUM71505078"
177
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID) == "12345678-1234-5678-9abc-def123456789"
178
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS) == ["12345678-1234-5678-9abc-def123456789"]
165
+ assert unified.get(UnifiedMetadataKey.TITLE.value) == "WAV Comprehensive Test"
166
+ assert unified.get(UnifiedMetadataKey.ARTISTS.value) == ["WAV Artist"]
167
+ assert unified.get(UnifiedMetadataKey.ALBUM.value) == "WAV Album"
168
+ assert unified.get(UnifiedMetadataKey.RELEASE_DATE.value) == "2024"
169
+ assert unified.get(UnifiedMetadataKey.GENRES_NAMES.value) == ["Rock"]
170
+ assert unified.get(UnifiedMetadataKey.RATING.value) == 100
171
+ assert unified.get(UnifiedMetadataKey.BPM.value) == 120
172
+ assert unified.get(UnifiedMetadataKey.LANGUAGE.value) == "eng"
173
+ assert unified.get(UnifiedMetadataKey.COMPOSERS.value) == ["WAV Composer"]
174
+ assert unified.get(UnifiedMetadataKey.COPYRIGHT.value) == "© WAV"
175
+ assert unified.get(UnifiedMetadataKey.COMMENT.value) == "WAV comment"
176
+ assert unified.get(UnifiedMetadataKey.DESCRIPTION.value) == "WAV description"
177
+ assert unified.get(UnifiedMetadataKey.ORIGINATOR.value) == "WAV originator"
178
+ assert unified.get(UnifiedMetadataKey.ISRC.value) == "GBUM71505078"
179
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID.value) == "12345678-1234-5678-9abc-def123456789"
180
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS.value) == [
181
+ "12345678-1234-5678-9abc-def123456789"
182
+ ]
179
183
 
180
184
  def test_cli_read_comprehensive_roundtrip(self):
181
185
  """Test that we can write all fields via CLI and read them back correctly."""
@@ -248,23 +252,25 @@ class TestCLIReadComprehensive:
248
252
  data = json.loads(read_result.stdout)
249
253
  unified = data.get("unified_metadata", {})
250
254
 
251
- assert unified.get(UnifiedMetadataKey.TITLE) == "Roundtrip Test"
252
- assert unified.get(UnifiedMetadataKey.ARTISTS) == ["Roundtrip Artist One", "Roundtrip Artist Two"]
253
- assert unified.get(UnifiedMetadataKey.ALBUM) == "Roundtrip Album"
254
- assert unified.get(UnifiedMetadataKey.ALBUM_ARTISTS) == ["Roundtrip Album Artist"]
255
- assert unified.get(UnifiedMetadataKey.RELEASE_DATE) == "2024"
256
- assert unified.get(UnifiedMetadataKey.GENRES_NAMES) == ["Rock", "Blues"]
257
- assert unified.get(UnifiedMetadataKey.TRACK_NUMBER) == "5/12"
258
- assert unified.get(UnifiedMetadataKey.DISC_NUMBER) == 1
259
- assert unified.get(UnifiedMetadataKey.DISC_TOTAL) == 2
260
- assert unified.get(UnifiedMetadataKey.RATING) == 85
261
- assert unified.get(UnifiedMetadataKey.BPM) == 120
262
- assert unified.get(UnifiedMetadataKey.LANGUAGE) == "eng"
263
- assert unified.get(UnifiedMetadataKey.COMPOSERS) == ["Roundtrip Composer"]
264
- assert unified.get(UnifiedMetadataKey.PUBLISHER) == "Roundtrip Publisher"
265
- assert unified.get(UnifiedMetadataKey.COPYRIGHT) == "© Roundtrip"
266
- assert unified.get(UnifiedMetadataKey.UNSYNCHRONIZED_LYRICS) == "Roundtrip lyrics"
267
- assert unified.get(UnifiedMetadataKey.COMMENT) == "Roundtrip comment"
268
- assert unified.get(UnifiedMetadataKey.ISRC) == "USRC17607839"
269
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID) == "9d6f6f7c-9d52-4c76-8f9e-01d18d8f8ec6"
270
- assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS) == ["9d6f6f7c-9d52-4c76-8f9e-01d18d8f8ec6"]
255
+ assert unified.get(UnifiedMetadataKey.TITLE.value) == "Roundtrip Test"
256
+ assert unified.get(UnifiedMetadataKey.ARTISTS.value) == ["Roundtrip Artist One", "Roundtrip Artist Two"]
257
+ assert unified.get(UnifiedMetadataKey.ALBUM.value) == "Roundtrip Album"
258
+ assert unified.get(UnifiedMetadataKey.ALBUM_ARTISTS.value) == ["Roundtrip Album Artist"]
259
+ assert unified.get(UnifiedMetadataKey.RELEASE_DATE.value) == "2024"
260
+ assert unified.get(UnifiedMetadataKey.GENRES_NAMES.value) == ["Rock", "Blues"]
261
+ assert unified.get(UnifiedMetadataKey.TRACK_NUMBER.value) == "5/12"
262
+ assert unified.get(UnifiedMetadataKey.DISC_NUMBER.value) == 1
263
+ assert unified.get(UnifiedMetadataKey.DISC_TOTAL.value) == 2
264
+ assert unified.get(UnifiedMetadataKey.RATING.value) == 85
265
+ assert unified.get(UnifiedMetadataKey.BPM.value) == 120
266
+ assert unified.get(UnifiedMetadataKey.LANGUAGE.value) == "eng"
267
+ assert unified.get(UnifiedMetadataKey.COMPOSERS.value) == ["Roundtrip Composer"]
268
+ assert unified.get(UnifiedMetadataKey.PUBLISHER.value) == "Roundtrip Publisher"
269
+ assert unified.get(UnifiedMetadataKey.COPYRIGHT.value) == "© Roundtrip"
270
+ assert unified.get(UnifiedMetadataKey.UNSYNCHRONIZED_LYRICS.value) == "Roundtrip lyrics"
271
+ assert unified.get(UnifiedMetadataKey.COMMENT.value) == "Roundtrip comment"
272
+ assert unified.get(UnifiedMetadataKey.ISRC.value) == "USRC17607839"
273
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_TRACKID.value) == "9d6f6f7c-9d52-4c76-8f9e-01d18d8f8ec6"
274
+ assert unified.get(UnifiedMetadataKey.MUSICBRAINZ_ARTISTIDS.value) == [
275
+ "9d6f6f7c-9d52-4c76-8f9e-01d18d8f8ec6"
276
+ ]
@@ -37,6 +37,26 @@ class TestCLIReadUnified:
37
37
  assert data.get("title") == "Unified Test"
38
38
  assert data.get("artists") == ["Unified Artist"]
39
39
 
40
+ def test_cli_unified_yaml_uses_plain_string_keys(self):
41
+ with temp_file_with_metadata({"title": "YAML Key Test", "artist": "YAML Artist"}, "mp3") as test_file:
42
+ result = subprocess.run(
43
+ [sys.executable, "-m", "audiometa", "unified", str(test_file), "--format", "yaml"],
44
+ capture_output=True,
45
+ text=True,
46
+ check=False,
47
+ )
48
+ assert result.returncode == 0
49
+ assert "!!python" not in result.stdout
50
+ try:
51
+ import yaml
52
+
53
+ data = yaml.safe_load(result.stdout)
54
+ assert isinstance(data, dict)
55
+ assert data.get("title") == "YAML Key Test"
56
+ assert data.get("artists") == ["YAML Artist"]
57
+ except ImportError:
58
+ pass
59
+
40
60
  def test_cli_unified_table_format(self):
41
61
  with temp_file_with_metadata({"title": "Table Test", "artist": "Table Artist"}, "mp3") as test_file:
42
62
  result = subprocess.run(
@@ -2,6 +2,7 @@ import json
2
2
 
3
3
  import pytest
4
4
 
5
+ from audiometa import UnifiedMetadataKey
5
6
  from audiometa.cli import format_as_table, format_output
6
7
 
7
8
 
@@ -29,3 +30,23 @@ class TestCLIFormatting:
29
30
  assert "Test Artist" in result
30
31
  assert "180" in result
31
32
  assert "320" in result
33
+
34
+ def test_format_output_table_displays_key_labels_not_enum_repr(self):
35
+ data = {
36
+ "unified_metadata": {
37
+ UnifiedMetadataKey.TITLE: "Song Title",
38
+ UnifiedMetadataKey.ALBUM_ARTISTS: ["Album Artist"],
39
+ },
40
+ "metadata_format": {
41
+ "id3v2": {
42
+ UnifiedMetadataKey.TITLE: "Song Title",
43
+ UnifiedMetadataKey.ALBUM_ARTISTS: ["Album Artist"],
44
+ },
45
+ },
46
+ }
47
+ result = format_as_table(data)
48
+ assert "UnifiedMetadataKey." not in result
49
+ assert "title" in result
50
+ assert "album_artists" in result
51
+ assert "Song Title" in result
52
+ assert "Album Artist" in result or "['Album Artist']" in result
@@ -11,6 +11,23 @@ class TestCLIHelp:
11
11
  assert result.returncode == 1 # Should exit with error
12
12
  assert "usage:" in result.stdout.lower() or "help" in result.stdout.lower()
13
13
 
14
+ def test_cli_help_subcommand_shows_main_help(self):
15
+ result = subprocess.run(
16
+ [sys.executable, "-m", "audiometa", "help"], capture_output=True, text=True, check=False
17
+ )
18
+ assert result.returncode == 0
19
+ assert "usage:" in result.stdout.lower()
20
+ assert "read" in result.stdout.lower()
21
+ assert "write" in result.stdout.lower()
22
+
23
+ def test_cli_help_subcommand_shows_subcommand_help(self):
24
+ result = subprocess.run(
25
+ [sys.executable, "-m", "audiometa", "help", "read"], capture_output=True, text=True, check=False
26
+ )
27
+ assert result.returncode == 0
28
+ assert "read" in result.stdout.lower()
29
+ assert "--format" in result.stdout or "format" in result.stdout.lower()
30
+
14
31
  def test_cli_read_help(self):
15
32
  result = subprocess.run(
16
33
  [sys.executable, "-m", "audiometa", "read", "--help"], capture_output=True, text=True, check=False
@@ -99,16 +99,19 @@ class MacOSDependenciesChecker(OsDependenciesChecker):
99
99
 
100
100
  def _get_ffmpeg_version(self) -> str | None:
101
101
  """Get ffmpeg version (special handling for keg-only package)."""
102
- ffprobe_paths = ["ffprobe"]
102
+ candidates = ["ffprobe", "ffmpeg"]
103
103
  brew_prefix = self._get_brew_prefix()
104
- if brew_prefix:
105
- for version in ["7", "6", "5"]:
106
- ffprobe_paths.append(f"{brew_prefix}/opt/ffmpeg@{version}/bin/ffprobe")
104
+ paths_to_try: list[str] = []
105
+ for cmd in candidates:
106
+ paths_to_try.append(cmd)
107
+ if brew_prefix:
108
+ for version in ["7", "6", "5"]:
109
+ paths_to_try.append(f"{brew_prefix}/opt/ffmpeg@{version}/bin/{cmd}")
107
110
 
108
- for ffprobe_path in ffprobe_paths:
111
+ for tool_path in paths_to_try:
109
112
  try:
110
113
  result = subprocess.run(
111
- [ffprobe_path, "-version"],
114
+ [tool_path, "-version"],
112
115
  capture_output=True,
113
116
  text=True,
114
117
  check=False,
@@ -118,6 +121,9 @@ class MacOSDependenciesChecker(OsDependenciesChecker):
118
121
  match = re.search(r"version\s+(\d+(?:\.\d+)*)", output)
119
122
  if match:
120
123
  return match.group(1)
124
+ match = re.search(r"(\d+\.\d+(?:\.\d+)*)", output)
125
+ if match:
126
+ return match.group(1)
121
127
  except FileNotFoundError:
122
128
  continue
123
129
  return None
@@ -1,5 +1,6 @@
1
1
  """Ubuntu-specific dependency checker using dpkg."""
2
2
 
3
+ import re
3
4
  import subprocess
4
5
 
5
6
  from audiometa.utils.os_dependencies_checker.base import OsDependenciesChecker
@@ -15,8 +16,9 @@ class UbuntuDependenciesChecker(OsDependenciesChecker):
15
16
  def check_tool_available(self, tool_name: str) -> bool:
16
17
  """Check if tool is available in PATH."""
17
18
  try:
19
+ version_flag = "-version" if tool_name == "ffprobe" else "--version"
18
20
  result = subprocess.run(
19
- [tool_name, "--version"],
21
+ [tool_name, version_flag],
20
22
  capture_output=True,
21
23
  text=True,
22
24
  check=False,
@@ -36,6 +38,30 @@ class UbuntuDependenciesChecker(OsDependenciesChecker):
36
38
  return parts[2]
37
39
  except (subprocess.CalledProcessError, FileNotFoundError):
38
40
  pass
41
+ if package == "ffmpeg":
42
+ return self._get_ffmpeg_version_from_executable()
43
+ return None
44
+
45
+ def _get_ffmpeg_version_from_executable(self) -> str | None:
46
+ """Get ffmpeg version from ffprobe/ffmpeg when not installed via dpkg (e.g. snap, source)."""
47
+ for cmd in ["ffprobe", "ffmpeg"]:
48
+ try:
49
+ result = subprocess.run(
50
+ [cmd, "-version"],
51
+ capture_output=True,
52
+ text=True,
53
+ check=False,
54
+ )
55
+ if result.stdout or result.stderr:
56
+ output = result.stdout + result.stderr
57
+ match = re.search(r"version\s+(\d+(?:\.\d+)*)", output)
58
+ if match:
59
+ return match.group(1)
60
+ match = re.search(r"(\d+\.\d+(?:\.\d+)*)", output)
61
+ if match:
62
+ return match.group(1)
63
+ except FileNotFoundError:
64
+ continue
39
65
  return None
40
66
 
41
67
  @staticmethod
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: audiometa-python
3
- Version: 1.1.2
3
+ Version: 1.2.1
4
4
  Summary: A comprehensive Python library for reading and writing audio metadata across multiple formats
5
5
  Author: AudioMeta Python Contributors
6
6
  Author-email: Andreas Garcia <garcia.andreas.1991@gmail.com>
@@ -1429,11 +1429,13 @@ AudioMeta provides a powerful command-line interface for quick metadata operatio
1429
1429
 
1430
1430
  ### Installation {#cli-installation}
1431
1431
 
1432
- After installing the package, the `audiometa` command will be available:
1432
+ After installing the package, the `audiometa` command will be available. Commands: `read`, `unified`, `write`, `delete`, `help`. Use `audiometa --help` or `audiometa help` for main help; `audiometa help read` (or another command) for subcommand help.
1433
1433
 
1434
1434
  ```bash
1435
1435
  pip install audiometa-python
1436
1436
  audiometa --help
1437
+ # or: audiometa help
1438
+ # or: audiometa help read
1437
1439
  ```
1438
1440
 
1439
1441
  ### Basic Usage
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "audiometa-python"
7
- version = "1.1.2"
7
+ version = "1.2.1"
8
8
  description = "A comprehensive Python library for reading and writing audio metadata across multiple formats"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"