subliminal 2.7.0__tar.gz → 2.8.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (335) hide show
  1. {subliminal-2.7.0 → subliminal-2.8.0}/.github/actions/prepare-tests/action.yaml +4 -4
  2. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/CI.yaml +71 -29
  3. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/coverage.yaml +1 -1
  4. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/docker-build.yaml +8 -8
  5. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/prepare-release-pr.yaml +2 -2
  6. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/publish-release.yaml +6 -6
  7. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/publish.yaml +4 -4
  8. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/scheduled-tests.yaml +2 -2
  9. {subliminal-2.7.0 → subliminal-2.8.0}/.github/workflows/tag-release.yaml +3 -3
  10. {subliminal-2.7.0 → subliminal-2.8.0}/HISTORY.rst +43 -0
  11. {subliminal-2.7.0 → subliminal-2.8.0}/PKG-INFO +4 -2
  12. subliminal-2.8.0/docs/assets/demo.gif +0 -0
  13. {subliminal-2.7.0 → subliminal-2.8.0}/docs/conf.py +5 -2
  14. {subliminal-2.7.0 → subliminal-2.8.0}/pyproject.toml +2 -0
  15. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cli/commands/_format.py +20 -1
  16. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cli/commands/download_best.py +9 -5
  17. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/core.py +82 -32
  18. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/opensubtitles.py +12 -7
  19. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/opensubtitlescom.py +50 -11
  20. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/refiners/hash.py +4 -2
  21. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/refiners/metadata.py +15 -11
  22. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/refiners/omdb.py +53 -22
  23. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/refiners/tmdb.py +58 -41
  24. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/refiners/tvdb.py +70 -54
  25. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/utils.py +2 -2
  26. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/video.py +83 -129
  27. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_download_subtitle.yaml +58 -58
  28. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_download_with_bom.yaml +60 -56
  29. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_get_title_and_show_id_alternative_name.yaml +34 -36
  30. subliminal-2.8.0/tests/cassettes/gestdown/test_get_title_and_show_id_no_year.yaml +61 -0
  31. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_get_title_and_show_id_only_title.yaml +19 -19
  32. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_get_title_and_show_id_with_tvdb_id.yaml +18 -18
  33. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_list_subtitles.yaml +59 -57
  34. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_list_subtitles_episode_alternative_series.yaml +41 -41
  35. subliminal-2.8.0/tests/cassettes/gestdown/test_query.yaml +116 -0
  36. subliminal-2.8.0/tests/cassettes/gestdown/test_query_all_series.yaml +140 -0
  37. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_query_no_language.yaml +20 -20
  38. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_query_parsing.yaml +37 -39
  39. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_query_parsing_colon.yaml +35 -35
  40. subliminal-2.8.0/tests/cassettes/gestdown/test_query_parsing_dash.yaml +114 -0
  41. subliminal-2.8.0/tests/cassettes/gestdown/test_query_parsing_quote_dots_mixed_case.yaml +117 -0
  42. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_query_wrong_series.yaml +13 -13
  43. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_search_show_id.yaml +17 -17
  44. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_search_show_id_error.yaml +16 -16
  45. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_search_show_id_incomplete.yaml +17 -17
  46. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_search_show_id_no_year.yaml +19 -18
  47. subliminal-2.8.0/tests/cassettes/gestdown/test_search_show_id_quote.yaml +58 -0
  48. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_search_show_series_tvdb_id.yaml +19 -19
  49. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/gestdown/test_show_with_asterisk.yaml +56 -52
  50. subliminal-2.8.0/tests/cassettes/omdb/test_refine_episode_from_series_imdb_id.yaml +57 -0
  51. subliminal-2.8.0/tests/cassettes/omdb/test_refine_episode_from_unknown_series_imdb_id.yaml +50 -0
  52. subliminal-2.8.0/tests/cassettes/omdb/test_refine_movie_from_imdb_id.yaml +58 -0
  53. subliminal-2.8.0/tests/cassettes/omdb/test_refine_movie_from_unknown_imdb_id.yaml +50 -0
  54. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_download_subtitle.yaml +242 -234
  55. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_list_subtitles_episode.yaml +84 -103
  56. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_list_subtitles_movie.yaml +226 -213
  57. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_list_subtitles_movie_no_hash.yaml +82 -101
  58. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_login_bad_password.yaml +20 -25
  59. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_login_vip_bad_password.yaml +20 -25
  60. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_login_vip_login.yaml +21 -26
  61. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_no_operation.yaml +78 -97
  62. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_query_hash_size.yaml +103 -118
  63. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_query_imdb_id.yaml +106 -117
  64. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_query_not_enough_information.yaml +57 -71
  65. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_query_query_episode.yaml +80 -99
  66. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_query_query_movie.yaml +105 -121
  67. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_query_query_season_episode.yaml +82 -101
  68. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitles/test_query_wrong_hash_wrong_size.yaml +80 -99
  69. subliminal-2.8.0/tests/cassettes/opensubtitlescom/test_list_subtitles_episode_series_imdb_id.yaml +560 -0
  70. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/providers/test_download_best_subtitles.yaml +514 -506
  71. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/providers/test_list_subtitles_providers_download.yaml +3590 -5465
  72. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cli/test_download.py +31 -1
  73. subliminal-2.8.0/tests/cli/test_format.py +48 -0
  74. {subliminal-2.7.0 → subliminal-2.8.0}/tests/conftest.py +105 -65
  75. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_gestdown.py +1 -0
  76. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_opensubtitles.py +2 -1
  77. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_opensubtitlescom.py +83 -16
  78. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_providers.py +0 -18
  79. {subliminal-2.7.0 → subliminal-2.8.0}/tests/refiners/test_metadata.py +21 -20
  80. {subliminal-2.7.0 → subliminal-2.8.0}/tests/refiners/test_omdb.py +62 -7
  81. {subliminal-2.7.0 → subliminal-2.8.0}/tests/refiners/test_tmdb.py +10 -10
  82. {subliminal-2.7.0 → subliminal-2.8.0}/tests/refiners/test_tvdb.py +10 -40
  83. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_core.py +6 -8
  84. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_provider_pool.py +73 -19
  85. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_utils.py +1 -1
  86. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_video.py +162 -11
  87. subliminal-2.7.0/docs/assets/demo.gif +0 -0
  88. subliminal-2.7.0/tests/cassettes/gestdown/test_get_title_and_show_id_no_year.yaml +0 -57
  89. subliminal-2.7.0/tests/cassettes/gestdown/test_query.yaml +0 -116
  90. subliminal-2.7.0/tests/cassettes/gestdown/test_query_all_series.yaml +0 -140
  91. subliminal-2.7.0/tests/cassettes/gestdown/test_query_parsing_dash.yaml +0 -114
  92. subliminal-2.7.0/tests/cassettes/gestdown/test_query_parsing_quote_dots_mixed_case.yaml +0 -115
  93. subliminal-2.7.0/tests/cassettes/gestdown/test_search_show_id_quote.yaml +0 -58
  94. subliminal-2.7.0/tests/cassettes/opensubtitlescom/test_tag_match.yaml +0 -595
  95. {subliminal-2.7.0 → subliminal-2.8.0}/.dockerignore +0 -0
  96. {subliminal-2.7.0 → subliminal-2.8.0}/.github/zizmor.yml +0 -0
  97. {subliminal-2.7.0 → subliminal-2.8.0}/.gitignore +0 -0
  98. {subliminal-2.7.0 → subliminal-2.8.0}/.pre-commit-config.yaml +0 -0
  99. {subliminal-2.7.0 → subliminal-2.8.0}/.python-version-default +0 -0
  100. {subliminal-2.7.0 → subliminal-2.8.0}/.readthedocs.yaml +0 -0
  101. {subliminal-2.7.0 → subliminal-2.8.0}/CONTRIBUTING.md +0 -0
  102. {subliminal-2.7.0 → subliminal-2.8.0}/Dockerfile +0 -0
  103. {subliminal-2.7.0 → subliminal-2.8.0}/LICENSE +0 -0
  104. {subliminal-2.7.0 → subliminal-2.8.0}/MANIFEST.in +0 -0
  105. {subliminal-2.7.0 → subliminal-2.8.0}/README.rst +0 -0
  106. {subliminal-2.7.0 → subliminal-2.8.0}/RELEASING.md +0 -0
  107. {subliminal-2.7.0 → subliminal-2.8.0}/changelog.d/.gitignore +0 -0
  108. {subliminal-2.7.0 → subliminal-2.8.0}/docs/Makefile +0 -0
  109. {subliminal-2.7.0 → subliminal-2.8.0}/docs/_intersphinx/README.md +0 -0
  110. {subliminal-2.7.0 → subliminal-2.8.0}/docs/_intersphinx/importlib_metadata_objects.inv +0 -0
  111. {subliminal-2.7.0 → subliminal-2.8.0}/docs/_intersphinx/importlib_metadata_objects.txt +0 -0
  112. {subliminal-2.7.0 → subliminal-2.8.0}/docs/_static/.gitignore +0 -0
  113. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/cache.rst +0 -0
  114. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/cli.rst +0 -0
  115. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/core.rst +0 -0
  116. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/exceptions.rst +0 -0
  117. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/extensions.rst +0 -0
  118. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/providers.rst +0 -0
  119. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/refiners.rst +0 -0
  120. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/score.rst +0 -0
  121. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/subtitle.rst +0 -0
  122. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/utils.rst +0 -0
  123. {subliminal-2.7.0 → subliminal-2.8.0}/docs/api/video.rst +0 -0
  124. {subliminal-2.7.0 → subliminal-2.8.0}/docs/assets/config.toml +0 -0
  125. {subliminal-2.7.0 → subliminal-2.8.0}/docs/cassettes/test_usage.yaml +0 -0
  126. {subliminal-2.7.0 → subliminal-2.8.0}/docs/conftest.py +0 -0
  127. {subliminal-2.7.0 → subliminal-2.8.0}/docs/index.rst +0 -0
  128. {subliminal-2.7.0 → subliminal-2.8.0}/docs/make.bat +0 -0
  129. {subliminal-2.7.0 → subliminal-2.8.0}/docs/user/changelog.rst +0 -0
  130. {subliminal-2.7.0 → subliminal-2.8.0}/docs/user/cli.rst +0 -0
  131. {subliminal-2.7.0 → subliminal-2.8.0}/docs/user/configuration_file.rst +0 -0
  132. {subliminal-2.7.0 → subliminal-2.8.0}/docs/user/how_it_works.rst +0 -0
  133. {subliminal-2.7.0 → subliminal-2.8.0}/docs/user/installation.rst +0 -0
  134. {subliminal-2.7.0 → subliminal-2.8.0}/docs/user/provider_guide.rst +0 -0
  135. {subliminal-2.7.0 → subliminal-2.8.0}/docs/user/usage.rst +0 -0
  136. {subliminal-2.7.0 → subliminal-2.8.0}/hatch.toml +0 -0
  137. {subliminal-2.7.0 → subliminal-2.8.0}/scripts/.gitignore +0 -0
  138. {subliminal-2.7.0 → subliminal-2.8.0}/scripts/prepare-release-pr.py +0 -0
  139. {subliminal-2.7.0 → subliminal-2.8.0}/scripts/prepare_tests.py +0 -0
  140. {subliminal-2.7.0 → subliminal-2.8.0}/scripts/release.py +0 -0
  141. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/__init__.py +0 -0
  142. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/__main__.py +0 -0
  143. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/archives.py +0 -0
  144. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cache.py +0 -0
  145. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cli/__init__.py +0 -0
  146. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cli/cli.py +0 -0
  147. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cli/commands/__init__.py +0 -0
  148. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cli/generate_config.py +0 -0
  149. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/cli/helpers.py +0 -0
  150. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/converters/__init__.py +0 -0
  151. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/converters/addic7ed.py +0 -0
  152. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/converters/opensubtitles.py +0 -0
  153. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/converters/opensubtitlescom.py +0 -0
  154. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/converters/subtitulamos.py +0 -0
  155. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/converters/tvsubtitles.py +0 -0
  156. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/exceptions.py +0 -0
  157. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/extensions.py +0 -0
  158. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/matches.py +0 -0
  159. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/__init__.py +0 -0
  160. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/addic7ed.py +0 -0
  161. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/bsplayer.py +0 -0
  162. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/gestdown.py +0 -0
  163. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/mock.py +0 -0
  164. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/napiprojekt.py +0 -0
  165. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/podnapisi.py +0 -0
  166. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/subtis.py +0 -0
  167. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/subtitulamos.py +0 -0
  168. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/providers/tvsubtitles.py +0 -0
  169. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/py.typed +0 -0
  170. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/refiners/__init__.py +0 -0
  171. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/score.py +0 -0
  172. {subliminal-2.7.0 → subliminal-2.8.0}/src/subliminal/subtitle.py +0 -0
  173. {subliminal-2.7.0 → subliminal-2.8.0}/tests/__init__.py +0 -0
  174. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_download_subtitle.yaml +0 -0
  175. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_get_show_id.yaml +0 -0
  176. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_get_show_id_country.yaml +0 -0
  177. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_get_show_id_quote_dots_mixed_case.yaml +0 -0
  178. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_get_show_id_with_comma.yaml +0 -0
  179. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_get_show_id_year.yaml +0 -0
  180. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_get_show_ids.yaml +0 -0
  181. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_list_subtitles.yaml +0 -0
  182. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_list_subtitles_episode_alternative_series.yaml +0 -0
  183. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_list_subtitles_show_with_asterisk.yaml +0 -0
  184. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query.yaml +0 -0
  185. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query_no_year.yaml +0 -0
  186. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query_parsing.yaml +0 -0
  187. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query_parsing_colon.yaml +0 -0
  188. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query_parsing_dash.yaml +0 -0
  189. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query_parsing_quote_dots_mixed_case.yaml +0 -0
  190. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query_wrong_series.yaml +0 -0
  191. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/addic7ed/test_query_year.yaml +0 -0
  192. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/bsplayer/test_download_subtitle.yaml +0 -0
  193. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/bsplayer/test_list_subtitles_hash.yaml +0 -0
  194. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/bsplayer/test_login.yaml +0 -0
  195. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/bsplayer/test_logout.yaml +0 -0
  196. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/bsplayer/test_query_hash_size.yaml +0 -0
  197. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/cli/test_cli_download.yaml +0 -0
  198. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/napiprojekt/test_download_subtitles.yaml +0 -0
  199. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/napiprojekt/test_list_subtitles.yaml +0 -0
  200. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/napiprojekt/test_query_microdvd.yaml +0 -0
  201. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/napiprojekt/test_query_srt.yaml +0 -0
  202. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/napiprojekt/test_query_srt_reencode.yaml +0 -0
  203. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/napiprojekt/test_query_wrong_hash.yaml +0 -0
  204. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_get_id.yaml +0 -0
  205. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_get_title.yaml +0 -0
  206. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_get_wrong_id.yaml +0 -0
  207. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_get_wrong_title.yaml +0 -0
  208. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_refine_episode.yaml +0 -0
  209. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_refine_episode_original_series.yaml +0 -0
  210. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_refine_episode_with_country.yaml +0 -0
  211. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_refine_episode_with_country_hoc_us.yaml +0 -0
  212. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_refine_episode_year.yaml +0 -0
  213. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_refine_movie.yaml +0 -0
  214. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_refine_movie_guess_alternative_title.yaml +0 -0
  215. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_search.yaml +0 -0
  216. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_search_page.yaml +0 -0
  217. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_search_type.yaml +0 -0
  218. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_search_wrong_title.yaml +0 -0
  219. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/omdb/test_search_year.yaml +0 -0
  220. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_download_subtitle.yaml +0 -0
  221. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_list_subtitles_episode.yaml +0 -0
  222. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_list_subtitles_movie.yaml +0 -0
  223. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_list_subtitles_movie_no_hash.yaml +0 -0
  224. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_login.yaml +0 -0
  225. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_login_bad_password.yaml +0 -0
  226. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_logout.yaml +0 -0
  227. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_hash_size.yaml +0 -0
  228. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_imdb_id.yaml +0 -0
  229. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_max_result_pages.yaml +0 -0
  230. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_query_episode.yaml +0 -0
  231. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_query_movie.yaml +0 -0
  232. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_query_season_episode.yaml +0 -0
  233. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_tag_movie.yaml +0 -0
  234. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_query_wrong_hash_wrong_size.yaml +0 -0
  235. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/opensubtitlescom/test_user_infos.yaml +0 -0
  236. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/podnapisi/test_download_subtitle.yaml +0 -0
  237. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/podnapisi/test_download_subtitles_with_title_unicode.yaml +0 -0
  238. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/podnapisi/test_list_subtitles_episode.yaml +0 -0
  239. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/podnapisi/test_list_subtitles_episode_alternative_series.yaml +0 -0
  240. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/podnapisi/test_list_subtitles_movie.yaml +0 -0
  241. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/podnapisi/test_query_episode.yaml +0 -0
  242. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/podnapisi/test_query_movie.yaml +0 -0
  243. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/providers/test_download_best_subtitles_min_score.yaml +0 -0
  244. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/providers/test_download_best_subtitles_only_one.yaml +0 -0
  245. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtis/test_download_subtitle.yaml +0 -0
  246. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtis/test_list_subtitles_hash.yaml +0 -0
  247. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtis/test_list_subtitles_movie.yaml +0 -0
  248. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtis/test_list_subtitles_movie_alternative.yaml +0 -0
  249. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtis/test_list_subtitles_movie_with_size.yaml +0 -0
  250. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtis/test_list_subtitles_no_match.yaml +0 -0
  251. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_download_subtitle.yaml +0 -0
  252. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_download_subtitle_first_episode.yaml +0 -0
  253. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_download_subtitle_foo.yaml +0 -0
  254. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_download_subtitle_last_season.yaml +0 -0
  255. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_download_subtitle_year.yaml +0 -0
  256. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_list_subtitles_not_exist_episode.yaml +0 -0
  257. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_list_subtitles_not_exist_language.yaml +0 -0
  258. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_list_subtitles_not_exist_season.yaml +0 -0
  259. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_list_subtitles_not_exist_series.yaml +0 -0
  260. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/subtitulamos/test_list_subtitles_with_spanish_non_mx_search.yaml +0 -0
  261. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_get_movie_id.yaml +0 -0
  262. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_get_movie_id_failed.yaml +0 -0
  263. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_get_series_id.yaml +0 -0
  264. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_get_series_wrong_id.yaml +0 -0
  265. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_refine_episode.yaml +0 -0
  266. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_refine_episode_original_series.yaml +0 -0
  267. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_refine_episode_with_country.yaml +0 -0
  268. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_refine_episode_with_country_hoc_us.yaml +0 -0
  269. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_refine_episode_year.yaml +0 -0
  270. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_refine_movie.yaml +0 -0
  271. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_refine_movie_guess_alternative_title.yaml +0 -0
  272. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_search_movie.yaml +0 -0
  273. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_search_movie_page.yaml +0 -0
  274. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_search_movie_wrong_title.yaml +0 -0
  275. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_search_movie_year.yaml +0 -0
  276. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_search_series.yaml +0 -0
  277. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tmdb/test_search_series_wrong_name.yaml +0 -0
  278. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_get_series.yaml +0 -0
  279. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_get_series_actors.yaml +0 -0
  280. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_get_series_actors_wrong_id.yaml +0 -0
  281. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_get_series_wrong_id.yaml +0 -0
  282. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_login.yaml +0 -0
  283. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_login_error.yaml +0 -0
  284. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_query_series_episodes.yaml +0 -0
  285. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_query_series_episodes_wrong_season.yaml +0 -0
  286. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine.yaml +0 -0
  287. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_ambiguous.yaml +0 -0
  288. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_ambiguous_2.yaml +0 -0
  289. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_episode_alternative_series.yaml +0 -0
  290. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_episode_no_year.yaml +0 -0
  291. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_episode_partial.yaml +0 -0
  292. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_episode_with_comma.yaml +0 -0
  293. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_episode_with_country.yaml +0 -0
  294. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_episode_with_country_hoc_us.yaml +0 -0
  295. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_refine_episode_year.yaml +0 -0
  296. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_search_series.yaml +0 -0
  297. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvdb/test_search_series_wrong_name.yaml +0 -0
  298. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_download_subtitle.yaml +0 -0
  299. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_download_subtitle_with_quote.yaml +0 -0
  300. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_get_episode_ids.yaml +0 -0
  301. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_get_episode_ids_wrong_season.yaml +0 -0
  302. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_list_subtitles.yaml +0 -0
  303. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_list_subtitles_episode_alternative_series.yaml +0 -0
  304. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_query.yaml +0 -0
  305. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_query_no_year.yaml +0 -0
  306. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_query_with_quote.yaml +0 -0
  307. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_query_wrong_episode.yaml +0 -0
  308. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_query_wrong_series.yaml +0 -0
  309. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id.yaml +0 -0
  310. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id_ambiguous.yaml +0 -0
  311. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id_error.yaml +0 -0
  312. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id_incomplete.yaml +0 -0
  313. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id_no_year.yaml +0 -0
  314. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id_uk.yaml +0 -0
  315. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id_us.yaml +0 -0
  316. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cassettes/tvsubtitles/test_search_show_id_year_in_title.yaml +0 -0
  317. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cli/test_cli.py +0 -0
  318. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cli/test_generate_config.py +0 -0
  319. {subliminal-2.7.0 → subliminal-2.8.0}/tests/cli/test_helpers.py +0 -0
  320. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_addic7ed.py +0 -0
  321. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_bsplayer.py +0 -0
  322. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_napiprojekt.py +0 -0
  323. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_podnapisi.py +0 -0
  324. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_subtis.py +0 -0
  325. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_subtitulamos.py +0 -0
  326. {subliminal-2.7.0 → subliminal-2.8.0}/tests/providers/test_tvsubtitles.py +0 -0
  327. {subliminal-2.7.0 → subliminal-2.8.0}/tests/refiners/test_hash.py +0 -0
  328. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_archives.py +0 -0
  329. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_cache.py +0 -0
  330. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_extensions.py +0 -0
  331. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_matches.py +0 -0
  332. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_provider.py +0 -0
  333. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_score.py +0 -0
  334. {subliminal-2.7.0 → subliminal-2.8.0}/tests/test_subtitle.py +0 -0
  335. {subliminal-2.7.0 → subliminal-2.8.0}/tox.ini +0 -0
@@ -10,13 +10,13 @@ runs:
10
10
  run: |
11
11
  echo "::error title=⛔ error hint::Support Linux, Windows, and macOS Only"
12
12
  exit 1
13
- - uses: actions/checkout@v7
13
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
14
14
  with:
15
15
  persist-credentials: false
16
16
  fetch-depth: 0
17
17
  - name: Cache test data
18
18
  id: cache-test-data
19
- uses: actions/cache@v5
19
+ uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0
20
20
  with:
21
21
  path: tests/data/
22
22
  enableCrossOsArchive: true
@@ -30,11 +30,11 @@ runs:
30
30
  exit 1
31
31
  - name: Install other test software (on Linux only)
32
32
  if: steps.cache-test-data.outputs.cache-hit != 'true'
33
- uses: awalsh128/cache-apt-pkgs-action@v1
33
+ uses: awalsh128/cache-apt-pkgs-action@553a35bb8ebd9fcabcb1c9451aa4c98e1b4ca8a9 # v1.6.3
34
34
  with:
35
35
  packages: rar
36
36
  version: 1.0
37
- - uses: actions/setup-python@v6
37
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
38
38
  if: steps.cache-test-data.outputs.cache-hit != 'true'
39
39
  with:
40
40
  python-version-file: .python-version-default
@@ -20,7 +20,7 @@ jobs:
20
20
  check-manifest:
21
21
  runs-on: ubuntu-latest
22
22
  steps:
23
- - uses: actions/checkout@v7
23
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
24
24
  with:
25
25
  persist-credentials: false
26
26
  - run: pipx run check-manifest --ignore "_version.py"
@@ -28,23 +28,23 @@ jobs:
28
28
  pre-commit:
29
29
  runs-on: ubuntu-latest
30
30
  steps:
31
- - uses: actions/checkout@v7
31
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
32
32
  with:
33
33
  persist-credentials: false
34
- - uses: actions/setup-python@v6
34
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
35
35
  with:
36
36
  python-version-file: .python-version-default
37
- - uses: pre-commit/action@v3.0.1
37
+ - uses: pre-commit/action@2c7b3805fd2a0fd8c1884dcaebf91fc102a13ecd # v3.0.1
38
38
 
39
39
  typing:
40
40
  runs-on: ubuntu-latest
41
41
  permissions:
42
42
  contents: read
43
43
  steps:
44
- - uses: actions/checkout@v7
44
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
45
45
  with:
46
46
  persist-credentials: false
47
- - uses: actions/setup-python@v6
47
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
48
48
  with:
49
49
  python-version-file: .python-version-default
50
50
  - name: Install hatch
@@ -58,10 +58,10 @@ jobs:
58
58
  name: Build docs and run doctests
59
59
  runs-on: ubuntu-latest
60
60
  steps:
61
- - uses: actions/checkout@v7
61
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
62
62
  with:
63
63
  persist-credentials: false
64
- - uses: actions/setup-python@v6
64
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
65
65
  with:
66
66
  # Keep in sync with tox/docs, hatch.toml and .readthedocs.yaml.
67
67
  python-version-file: .python-version-default
@@ -76,7 +76,7 @@ jobs:
76
76
  - name: Check changelog
77
77
  run: hatch run changelog:run
78
78
 
79
- - uses: actions/upload-artifact@v7
79
+ - uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
80
80
  with:
81
81
  name: docs
82
82
  path: docs/_build/
@@ -86,10 +86,10 @@ jobs:
86
86
  runs-on: ubuntu-latest
87
87
 
88
88
  steps:
89
- - uses: actions/checkout@v7
89
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
90
90
  with:
91
91
  persist-credentials: false
92
- - uses: actions/setup-python@v6
92
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
93
93
  with:
94
94
  python-version-file: .python-version-default
95
95
  cache: pip
@@ -104,12 +104,12 @@ jobs:
104
104
  runs-on: ubuntu-latest
105
105
 
106
106
  steps:
107
- - uses: actions/checkout@v7
107
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
108
108
  with:
109
109
  persist-credentials: false
110
110
  fetch-depth: 0
111
111
 
112
- - uses: hynek/build-and-inspect-python-package@v2
112
+ - uses: hynek/build-and-inspect-python-package@2abe76da66d0a6a4a227101f9348ee855797cfa5 # v3.0.1
113
113
  id: baipp
114
114
 
115
115
  outputs:
@@ -122,7 +122,7 @@ jobs:
122
122
  runs-on: ubuntu-latest
123
123
 
124
124
  steps:
125
- - uses: actions/checkout@v7
125
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
126
126
  with:
127
127
  persist-credentials: false
128
128
  fetch-depth: 0
@@ -142,10 +142,10 @@ jobs:
142
142
  # Created by the build-and-inspect-python-package action above.
143
143
  py: ${{ fromJson(needs.build-package.outputs.supported-python-versions) }}
144
144
  steps:
145
- - uses: actions/checkout@v7
145
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
146
146
  with:
147
147
  persist-credentials: false
148
- - uses: actions/setup-python@v6
148
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
149
149
  with:
150
150
  python-version: ${{ matrix.py }}
151
151
  allow-prereleases: true
@@ -181,32 +181,74 @@ jobs:
181
181
  shell: bash
182
182
 
183
183
  - name: Store coverage file
184
- uses: actions/upload-artifact@v7
184
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
185
185
  with:
186
186
  name: coverage-${{ matrix.os }}-${{ matrix.py }}
187
187
  path: .coverage*
188
188
  include-hidden-files: true
189
189
  if-no-files-found: error
190
190
 
191
+ test-freebsd:
192
+ name: Test on FreeBSD
193
+ runs-on: ubuntu-latest
194
+ needs: prepare-test
195
+ timeout-minutes: 10
196
+ if: github.event_name == 'push'
197
+ steps:
198
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
199
+ with:
200
+ persist-credentials: false
201
+ fetch-depth: 0
202
+ - name: Prepare tests
203
+ uses: ./.github/actions/prepare-tests
204
+ - name: Display downloaded files
205
+ run: ls -R tests/data
206
+ - name: Test in FreeBSD
207
+ uses: vmactions/freebsd-vm@c46abacb49f09938ca4e1702d15d836285d694cc # v1.5.9
208
+ with:
209
+ release: "15.0"
210
+ usesh: true
211
+ prepare: |
212
+ pkg install -y python3 databases/py-sqlite3 devel/py-hatch git-lite
213
+ run: |
214
+ set -e
215
+ PY_VERSION=$(python3 -c 'import platform; print(".".join(platform.python_version_tuple()[:2]))')
216
+ echo "Picked Python ${PY_VERSION}"
217
+ export ENV="tests.py${PY_VERSION}"
218
+ export FORCE_COLOR="1"
219
+ export CI_RUN="yes"
220
+ export COVERAGE_FILE=".coverage.freebsd.${PY_VERSION}"
221
+ hatch -v env create "${ENV}"
222
+ hatch -v run "${ENV}:test-cov"
223
+
224
+ - name: Store coverage file
225
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
226
+ with:
227
+ name: coverage-freebsd
228
+ path: .coverage*
229
+ include-hidden-files: true
230
+ if-no-files-found: error
231
+
191
232
  coverage:
192
233
  name: Coverage
193
234
  runs-on: ubuntu-latest
194
- needs: test
235
+ needs: [test, test-freebsd]
236
+ if: ${{ !cancelled() && needs.test.result == 'success' && (needs.test-freebsd.result == 'success' || needs.test-freebsd.result == 'skipped') }}
195
237
  permissions:
196
238
  pull-requests: write
197
239
  contents: write
198
240
  steps:
199
- - uses: actions/checkout@v7
241
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
200
242
  with:
201
243
  # py-cov-action/python-coverage-comment-action needs git credentials
202
244
  persist-credentials: true
203
- - uses: actions/setup-python@v6
245
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
204
246
  with:
205
247
  python-version-file: .python-version-default
206
- - uses: hynek/setup-cached-uv@v2
248
+ - uses: hynek/setup-cached-uv@34e35d30f1ebc7421a5cc733bca38dcc62603960 # v2.6.0
207
249
 
208
250
  - name: Download coverage data
209
- uses: actions/download-artifact@v8
251
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
210
252
  with:
211
253
  pattern: coverage-*
212
254
  merge-multiple: true
@@ -222,19 +264,19 @@ jobs:
222
264
  coverage report --skip-covered --skip-empty --show-missing --format=markdown >> $GITHUB_STEP_SUMMARY
223
265
 
224
266
  - name: Upload HTML report if check failed.
225
- uses: actions/upload-artifact@v7
267
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
226
268
  with:
227
269
  name: html-report
228
270
  path: htmlcov
229
271
 
230
272
  - name: Coverage comment
231
273
  id: coverage_comment
232
- uses: py-cov-action/python-coverage-comment-action@v3
274
+ uses: py-cov-action/python-coverage-comment-action@e5fb2218463c3377f3504b0c5b5646ed53da7a2f # v4.5
233
275
  with:
234
276
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
235
277
 
236
278
  - name: Store Pull Request comment to be posted
237
- uses: actions/upload-artifact@v7
279
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
238
280
  if: steps.coverage_comment.outputs.COMMENT_FILE_WRITTEN == 'true'
239
281
  with:
240
282
  # If you use a different name, update COMMENT_ARTIFACT_NAME accordingly
@@ -247,10 +289,10 @@ jobs:
247
289
  runs-on: ubuntu-latest
248
290
  needs: [build-package, prepare-test]
249
291
  steps:
250
- - uses: actions/checkout@v7
292
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
251
293
  with:
252
294
  persist-credentials: false
253
- - uses: actions/setup-python@v6
295
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
254
296
  id: setup
255
297
  with:
256
298
  python-version-file: .python-version-default
@@ -287,7 +329,7 @@ jobs:
287
329
  shell: bash
288
330
 
289
331
  - name: Store coverage file
290
- uses: actions/upload-artifact@v7
332
+ uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
291
333
  if: ${{ failure() }}
292
334
  with:
293
335
  name: core-coverage
@@ -313,6 +355,6 @@ jobs:
313
355
 
314
356
  steps:
315
357
  - name: Decide whether the needed jobs succeeded or failed
316
- uses: re-actors/alls-green@release/v1
358
+ uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0
317
359
  with:
318
360
  jobs: ${{ toJSON(needs) }}
@@ -30,7 +30,7 @@ jobs:
30
30
  # DO NOT run actions/checkout here, for security reasons
31
31
  # For details, refer to https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
32
32
  - name: Post comment
33
- uses: py-cov-action/python-coverage-comment-action@v3
33
+ uses: py-cov-action/python-coverage-comment-action@e5fb2218463c3377f3504b0c5b5646ed53da7a2f # v4.5
34
34
  with:
35
35
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
36
36
  GITHUB_PR_RUN_ID: ${{ github.event.workflow_run.id }}
@@ -35,12 +35,12 @@ jobs:
35
35
  steps:
36
36
  - name: Checkout repository
37
37
  if: github.event_name == 'push' || github.event_name == 'pull_request'
38
- uses: actions/checkout@v7
38
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
39
39
  with:
40
40
  persist-credentials: false
41
41
  - name: Checkout repository
42
42
  if: github.event_name == 'workflow_call' || github.event_name == 'workflow_dispatch'
43
- uses: actions/checkout@v7
43
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
44
44
  with:
45
45
  ref: ${{ inputs.tag-name }}
46
46
  persist-credentials: false
@@ -50,15 +50,15 @@ jobs:
50
50
  github.event_name == 'push'
51
51
  || github.event_name == 'workflow_call'
52
52
  || github.event_name == 'workflow_dispatch'
53
- uses: docker/setup-qemu-action@v4
53
+ uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
54
54
 
55
55
  - name: Set up Docker Buildx
56
- uses: docker/setup-buildx-action@v4
56
+ uses: docker/setup-buildx-action@f87e5991a6d7451dcb8d9637bfbc97413f497069 # v4.4.1
57
57
  with:
58
58
  cache-binary: false
59
59
 
60
60
  - name: Log in to the Container registry
61
- uses: docker/login-action@v4
61
+ uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0
62
62
  with:
63
63
  registry: ${{ env.REGISTRY }}
64
64
  username: ${{ github.actor }}
@@ -66,7 +66,7 @@ jobs:
66
66
 
67
67
  - name: Extract metadata (tags, labels) for Docker
68
68
  id: meta
69
- uses: docker/metadata-action@v6
69
+ uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0
70
70
  with:
71
71
  images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
72
72
  tags: |
@@ -76,7 +76,7 @@ jobs:
76
76
  type=semver,pattern={{major}},enable=${{ !startsWith(github.ref, 'refs/tags/0.') }}
77
77
 
78
78
  - name: Test building Docker image
79
- uses: docker/build-push-action@v7
79
+ uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
80
80
  if: github.event_name == 'pull_request'
81
81
  with:
82
82
  context: .
@@ -86,7 +86,7 @@ jobs:
86
86
  cache-to: type=gha,mode=max
87
87
 
88
88
  - name: Build and push Docker image
89
- uses: docker/build-push-action@v7
89
+ uses: docker/build-push-action@c3c9e263c25d99ce0380d002d59b67737d91b0dc # v7.4.0
90
90
  if: |
91
91
  github.event_name == 'push'
92
92
  || github.event_name == 'workflow_call'
@@ -29,14 +29,14 @@ jobs:
29
29
  pull-requests: write
30
30
 
31
31
  steps:
32
- - uses: actions/checkout@v7
32
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
33
33
  with:
34
34
  fetch-depth: 0
35
35
  # persist-credentials is needed in order for us to push the release branch.
36
36
  persist-credentials: true
37
37
 
38
38
  - name: Set up Python
39
- uses: actions/setup-python@v6
39
+ uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
40
40
  with:
41
41
  python-version-file: .python-version-default
42
42
  cache: pip
@@ -31,12 +31,12 @@ jobs:
31
31
  runs-on: ubuntu-latest
32
32
  steps:
33
33
  - name: Checkout
34
- uses: actions/checkout@v7
34
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
35
35
  if: github.event_name == 'push'
36
36
  with:
37
37
  persist-credentials: false
38
38
  - name: Checkout
39
- uses: actions/checkout@v7
39
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
40
40
  if: |
41
41
  github.event_name == 'workflow_dispatch'
42
42
  || github.event_name == 'workflow_call'
@@ -44,7 +44,7 @@ jobs:
44
44
  ref: ${{ inputs.tag-name }}
45
45
  persist-credentials: false
46
46
  - name: Build dist
47
- uses: hynek/build-and-inspect-python-package@v2
47
+ uses: hynek/build-and-inspect-python-package@2abe76da66d0a6a4a227101f9348ee855797cfa5 # v3.0.1
48
48
  id: baipp
49
49
  outputs:
50
50
  tag: ${{ steps.baipp.outputs.package_version }}
@@ -63,19 +63,19 @@ jobs:
63
63
  # Publish a Github release when a tag was pushed, or it's called with a tag.
64
64
  steps:
65
65
  - name: Checkout
66
- uses: actions/checkout@v7
66
+ uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
67
67
  with:
68
68
  fetch-tags: true
69
69
  ref: ${{ needs.build-package.outputs.tag }}
70
70
  persist-credentials: false
71
71
 
72
72
  - name: Download packages built by build-and-inspect-python-package
73
- uses: actions/download-artifact@v8
73
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
74
74
  with:
75
75
  name: Packages
76
76
  path: dist
77
77
  - name: Publish GitHub Release
78
- uses: softprops/action-gh-release@v3
78
+ uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
79
79
  with:
80
80
  files: dist/*
81
81
  generate_release_notes: true
@@ -20,12 +20,12 @@ jobs:
20
20
  name: Build & verify package
21
21
  runs-on: ubuntu-latest
22
22
  steps:
23
- - uses: actions/checkout@v7
23
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
24
24
  with:
25
25
  fetch-depth: 0
26
26
  persist-credentials: false
27
27
 
28
- - uses: hynek/build-and-inspect-python-package@v2
28
+ - uses: hynek/build-and-inspect-python-package@2abe76da66d0a6a4a227101f9348ee855797cfa5 # v3.0.1
29
29
  id: baipp
30
30
 
31
31
  publish-to-pypi:
@@ -45,9 +45,9 @@ jobs:
45
45
  && github.event.action == 'published'
46
46
  steps:
47
47
  - name: Download packages built by build-and-inspect-python-package
48
- uses: actions/download-artifact@v8
48
+ uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
49
49
  with:
50
50
  name: Packages
51
51
  path: dist
52
52
  - name: Publish package distributions to PyPI
53
- uses: pypa/gh-action-pypi-publish@release/v1
53
+ uses: pypa/gh-action-pypi-publish@dc37677b2e1c63e2034f94d8a5b11f265b73ba33 # v1.14.2
@@ -24,10 +24,10 @@ jobs:
24
24
  || github.event_name == 'workflow_dispatch'
25
25
  runs-on: ubuntu-latest
26
26
  steps:
27
- - uses: actions/checkout@v7
27
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
28
28
  with:
29
29
  persist-credentials: false
30
- - uses: actions/setup-python@v6
30
+ - uses: actions/setup-python@5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
31
31
  with:
32
32
  python-version: "3.x"
33
33
  - name: Prepare tests
@@ -24,12 +24,12 @@ jobs:
24
24
  name: Build & verify package
25
25
  runs-on: ubuntu-latest
26
26
  steps:
27
- - uses: actions/checkout@v7
27
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
28
28
  with:
29
29
  fetch-depth: 0
30
30
  persist-credentials: false
31
31
 
32
- - uses: hynek/build-and-inspect-python-package@v2
32
+ - uses: hynek/build-and-inspect-python-package@2abe76da66d0a6a4a227101f9348ee855797cfa5 # v3.0.1
33
33
 
34
34
  define-tag:
35
35
  name: Define tag
@@ -72,7 +72,7 @@ jobs:
72
72
  env:
73
73
  RELEASE_VERSION: ${{ needs.define-tag.outputs.tag }}
74
74
  steps:
75
- - uses: actions/checkout@v7
75
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
76
76
  with:
77
77
  fetch-depth: 0
78
78
  # keep credentials to create a tag
@@ -2,6 +2,49 @@
2
2
 
3
3
  .. towncrier release notes start
4
4
 
5
+ 2.8.0 (2026-10-13)
6
+ ^^^^^^^^^^^^^^^^^^
7
+
8
+ Changes
9
+ -------
10
+
11
+ - Added `ProviderPool.failed_providers` - a set of providers that had an error.
12
+ Changed the user-facing error messages of the `download` command to explicitly distinguish
13
+ discarded providers, which are not used for the rest of the download, from those that errored
14
+ out but were still kept in the pool. (`#1374 <https://github.com/Diaoul/subliminal/issues/1374>`__)
15
+ - add ProviderResult class to keep track of queries to providers (`#1381 <https://github.com/Diaoul/subliminal/issues/1381>`__)
16
+
17
+
18
+ Provider Changes
19
+ ----------------
20
+
21
+ - Stop the opensubtitlescom pagination when a page fails and keep the subtitles already found (`#1373 <https://github.com/Diaoul/subliminal/issues/1373>`__)
22
+ - fix: OpenSubtitlesCom was not using hash if OpenSubtitles was not used also (`#1382 <https://github.com/Diaoul/subliminal/issues/1382>`__)
23
+ - Search episodes with OpenSubtitlesCom by the show's IMDb/TMDB id. (`#1384 <https://github.com/Diaoul/subliminal/issues/1384>`__)
24
+
25
+
26
+ Refiner Changes
27
+ ---------------
28
+
29
+ - omdb: use the IMDB id to backfill missing title and year metadata (`#1375 <https://github.com/Diaoul/subliminal/issues/1375>`__)
30
+
31
+
32
+ CLI Changes
33
+ -----------
34
+
35
+ - improve message for ignored videos (`#1387 <https://github.com/Diaoul/subliminal/issues/1387>`__)
36
+
37
+
38
+ 2.7.1 (2026-07-22)
39
+ ^^^^^^^^^^^^^^^^^^
40
+
41
+ Misc
42
+ ----
43
+
44
+ - fix test for compatibility with guessit>=4 (`#1368 <https://github.com/Diaoul/subliminal/issues/1368>`__)
45
+ - add CI tests for FreeBSD (`#1370 <https://github.com/Diaoul/subliminal/issues/1370>`__)
46
+
47
+
5
48
  2.7.0 (2026-07-21)
6
49
  ^^^^^^^^^^^^^^^^^^
7
50
 
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: subliminal
3
- Version: 2.7.0
3
+ Version: 2.8.0
4
4
  Summary: Subtitles, faster than your thoughts
5
5
  Project-URL: homepage, https://github.com/Diaoul/subliminal
6
6
  Project-URL: repository, https://github.com/Diaoul/subliminal
@@ -39,6 +39,7 @@ Requires-Dist: requests>=2.0
39
39
  Requires-Dist: srt>=3.5
40
40
  Requires-Dist: stevedore>=3.0
41
41
  Requires-Dist: tomlkit>=0.13.2
42
+ Requires-Dist: typing-extensions>=4.10
42
43
  Provides-Extra: dev
43
44
  Requires-Dist: pre-commit>=2.9.3; extra == 'dev'
44
45
  Requires-Dist: tox; extra == 'dev'
@@ -55,6 +56,7 @@ Requires-Dist: rarfile>=2.7; extra == 'rar'
55
56
  Provides-Extra: tests
56
57
  Requires-Dist: colorama; extra == 'tests'
57
58
  Requires-Dist: coverage[toml]>=7; extra == 'tests'
59
+ Requires-Dist: packaging; extra == 'tests'
58
60
  Requires-Dist: pytest-cov; extra == 'tests'
59
61
  Requires-Dist: pytest-xdist; extra == 'tests'
60
62
  Requires-Dist: pytest>=6.0; extra == 'tests'
Binary file
@@ -311,15 +311,18 @@ intersphinx_mapping = {
311
311
  }
312
312
 
313
313
 
314
- # -- Options for autodoc -----------------------------------------------------
314
+ # -- Options for autodoc -------------------------------------------------------
315
315
  autodoc_member_order = 'bysource'
316
316
 
317
317
  autodoc_default_flags = ['members']
318
318
 
319
319
 
320
- # -- Options for sphinx-autodoc-typehints ------------------------------------
320
+ # -- Options for sphinx-autodoc-typehints --------------------------------------
321
321
  # https://github.com/tox-dev/sphinx-autodoc-typehints
322
322
 
323
323
  always_use_bars_union = True
324
324
 
325
325
  set_type_checking_flag = False
326
+
327
+ # -- Options for the linkcheck builder -----------------------------------------
328
+ linkcheck_ignore = [r'https://stackoverflow.com/.*']
@@ -49,6 +49,7 @@ dependencies = [
49
49
  "srt>=3.5",
50
50
  "stevedore>=3.0",
51
51
  "tomlkit>=0.13.2",
52
+ "typing_extensions>=4.10", # TypedDict extra_items
52
53
  ]
53
54
 
54
55
  # extras
@@ -67,6 +68,7 @@ docs = [
67
68
  tests = [
68
69
  "subliminal[rar]",
69
70
  "coverage[toml]>=7",
71
+ "packaging",
70
72
  "pytest>=6.0",
71
73
  "pytest-cov",
72
74
  "pytest-xdist",
@@ -5,12 +5,15 @@ from __future__ import annotations
5
5
  import logging
6
6
  import re
7
7
  from datetime import timedelta
8
- from typing import Any
8
+ from typing import TYPE_CHECKING, Any
9
9
 
10
10
  import click
11
11
  from babelfish import Error as BabelfishError # type: ignore[import-untyped]
12
12
  from babelfish import Language
13
13
 
14
+ if TYPE_CHECKING:
15
+ from collections.abc import Set
16
+
14
17
  logger = logging.getLogger(__name__)
15
18
 
16
19
 
@@ -54,6 +57,22 @@ class AgeParamType(click.ParamType):
54
57
  return timedelta(**{k: int(v) for k, v in match.groupdict(0).items()})
55
58
 
56
59
 
60
+ def format_provider_errors(failed_providers: Set[str], discarded_providers: Set[str], *, video_count: int) -> str:
61
+ """Tell the user which providers had an error, and how the error affected the end results.
62
+
63
+ With one video both kinds of error have the same result, so one sentence covers them.
64
+ """
65
+ if video_count == 1:
66
+ return f'These providers had an error and found no subtitles: {", ".join(sorted(failed_providers))}.'
67
+
68
+ groups = (
69
+ ('These providers had an error and were skipped for the rest of the download', sorted(discarded_providers)),
70
+ ('These providers had an error on some videos', sorted(failed_providers - discarded_providers)),
71
+ )
72
+ sentences = [f'{label}: {", ".join(names)}.' for label, names in groups if names]
73
+ return ' '.join([*sentences, 'Some subtitles can be missing.'])
74
+
75
+
57
76
  def plural(quantity: int, name: str, *, bold: bool = True, **kwargs: Any) -> str:
58
77
  """Format a quantity with plural."""
59
78
  return '{} {}{}'.format(
@@ -35,7 +35,7 @@ from subliminal.exceptions import GuessingError
35
35
  from subliminal.extensions import get_default_providers, get_default_refiners
36
36
  from subliminal.utils import NameResolver, merge_extend_and_ignore_unions
37
37
 
38
- from ._format import AgeParamType, LanguageParamType, plural
38
+ from ._format import AgeParamType, LanguageParamType, format_provider_errors, plural
39
39
 
40
40
  if TYPE_CHECKING:
41
41
  from collections.abc import Sequence
@@ -530,10 +530,14 @@ def download(
530
530
  for video in ignored_videos:
531
531
  video_name = os.path.split(video.name)[1]
532
532
  msg = f'{video_name!r} ignored'
533
+ # Add information about existing subtitle languages
534
+ langs = ', '.join(str(s) for s in video.subtitle_languages) or 'none'
535
+ days = f'{video.age.days:d} day{"s" if video.age.days > 1 else ""}'
536
+ msg += f' - existing subtitles: {langs}'
537
+ # Add information about the video age
533
538
  if video.exists:
534
- langs = ', '.join(str(s) for s in video.subtitle_languages) or 'none'
535
539
  days = f'{video.age.days:d} day{"s" if video.age.days > 1 else ""}'
536
- msg += f' - subtitles: {langs} / age: {days}'
540
+ msg += f' - age: {days}'
537
541
  else:
538
542
  msg += ' - not a video file'
539
543
  click.secho(msg, fg='yellow')
@@ -591,9 +595,9 @@ def download(
591
595
  )
592
596
  downloaded_subtitles[v] = subtitles
593
597
 
594
- if pp.discarded_providers: # pragma: no cover
598
+ if pp.failed_providers:
595
599
  click.secho(
596
- f'Some providers have been discarded due to unexpected errors: {", ".join(pp.discarded_providers)}',
600
+ format_provider_errors(pp.failed_providers, pp.discarded_providers, video_count=len(videos)),
597
601
  fg='yellow',
598
602
  )
599
603