mnamer 2.7.2.dev8__py3-none-any.whl → 2.7.3.dev3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mnamer/__version__.py CHANGED
@@ -1,4 +1,4 @@
1
1
  # file generated by setuptools_scm
2
2
  # don't change, don't track in version control
3
3
 
4
- __version__ = "2.7.2.dev8"
4
+ __version__ = "2.7.3.dev3"
mnamer/endpoints.py CHANGED
@@ -26,12 +26,15 @@ MAX_RETRIES = 5
26
26
  class OmdbSearchEntry(TypedDict):
27
27
  imdb_id: str
28
28
  year: str
29
+ type: str
29
30
  title: NotRequired[str]
30
31
 
31
32
 
32
33
  class OmdbTitleResponse(TypedDict):
33
34
  title: str
34
35
  year: str
36
+ response: str
37
+ type: str
35
38
  released: NotRequired[str]
36
39
  plot: NotRequired[str]
37
40
  imdb_id: str
@@ -47,6 +50,7 @@ class OmdbSearchResponse(TypedDict):
47
50
  class TmdbSearchEntry(TypedDict):
48
51
  id: int
49
52
  title: str
53
+ original_title: str
50
54
  release_date: NotRequired[str]
51
55
  overview: NotRequired[str]
52
56
 
@@ -67,6 +71,8 @@ class TmdbSearchResponse(TypedDict):
67
71
 
68
72
  class TvdbLinks(TypedDict):
69
73
  last: int
74
+ next: int | None
75
+ prev: int | None
70
76
 
71
77
 
72
78
  class TvdbSeriesData(TypedDict):
@@ -79,6 +85,7 @@ class TvdbSeriesResponse(TypedDict):
79
85
 
80
86
 
81
87
  class TvdbEpisodeEntry(TypedDict):
88
+ id: int
82
89
  first_aired: str
83
90
  aired_episode_number: int
84
91
  aired_season: int
@@ -93,6 +100,7 @@ class TvdbEpisodesResponse(TypedDict):
93
100
 
94
101
  class TvdbSearchEntry(TypedDict):
95
102
  id: int
103
+ series_name: str
96
104
 
97
105
 
98
106
  class TvdbSearchResponse(TypedDict):
@@ -115,6 +123,7 @@ class TvMazeSearchEntry(TypedDict):
115
123
 
116
124
 
117
125
  class TvMazeEpisode(TypedDict):
126
+ id: int
118
127
  airdate: str | None
119
128
  number: int | None
120
129
  season: int
@@ -330,7 +339,7 @@ def tvdb_refresh_token(token: str) -> str:
330
339
  Online docs: api.thetvdb.com/swagger#!/Authentication/get_refresh_token.
331
340
  """
332
341
  url = "https://api.thetvdb.com/refresh_token"
333
- headers = {"Authorization": f"Bearer {token}"}
342
+ headers = _tvdb_headers(token)
334
343
  status, content = request_json(url, headers=headers, cache=False)
335
344
  if status == 401:
336
345
  raise MnamerException("invalid token")
@@ -339,6 +348,15 @@ def tvdb_refresh_token(token: str) -> str:
339
348
  return content["token"]
340
349
 
341
350
 
351
+ def _tvdb_headers(token: str, language: Language | None = None) -> dict[str, str]:
352
+ if token.count(".") != 2:
353
+ raise MnamerException("invalid token")
354
+ headers = {"Authorization": f"Bearer {token}"}
355
+ if language:
356
+ headers["Accept-Language"] = language.a2
357
+ return headers
358
+
359
+
342
360
  def tvdb_episodes_id(
343
361
  token: str,
344
362
  id_tvdb: str,
@@ -352,9 +370,7 @@ def tvdb_episodes_id(
352
370
  """
353
371
  Language.ensure_valid_for_tvdb(language)
354
372
  url = f"https://api.thetvdb.com/episodes/{id_tvdb}"
355
- headers = {"Authorization": f"Bearer {token}"}
356
- if language:
357
- headers["Accept-Language"] = language.a2
373
+ headers = _tvdb_headers(token, language)
358
374
  status, content = request_json(
359
375
  url, headers=headers, cache=cache is True and language is None
360
376
  )
@@ -384,9 +400,7 @@ def tvdb_series_id(
384
400
  """
385
401
  Language.ensure_valid_for_tvdb(language)
386
402
  url = f"https://api.thetvdb.com/series/{id_tvdb}"
387
- headers = {"Authorization": f"Bearer {token}"}
388
- if language:
389
- headers["Accept-Language"] = language.a2
403
+ headers = _tvdb_headers(token, language)
390
404
  status, content = request_json(
391
405
  url, headers=headers, cache=cache is True and language is None
392
406
  )
@@ -417,9 +431,7 @@ def tvdb_series_id_episodes(
417
431
  """
418
432
  Language.ensure_valid_for_tvdb(language)
419
433
  url = f"https://api.thetvdb.com/series/{id_tvdb}/episodes"
420
- headers = {"Authorization": f"Bearer {token}"}
421
- if language:
422
- headers["Accept-Language"] = language.a2
434
+ headers = _tvdb_headers(token, language)
423
435
  parameters: dict[str, Any] = {"page": page}
424
436
  status, content = request_json(
425
437
  url, parameters, headers=headers, cache=cache is True and language is None
@@ -452,9 +464,7 @@ def tvdb_series_id_episodes_query(
452
464
  """
453
465
  Language.ensure_valid_for_tvdb(language)
454
466
  url = f"https://api.thetvdb.com/series/{id_tvdb}/episodes/query"
455
- headers = {"Authorization": f"Bearer {token}"}
456
- if language:
457
- headers["Accept-Language"] = language.a2
467
+ headers = _tvdb_headers(token, language)
458
468
  parameters: dict[str, Any] = {
459
469
  "airedSeason": season,
460
470
  "airedEpisode": episode,
@@ -497,9 +507,7 @@ def tvdb_search_series(
497
507
  "imdbId": id_imdb,
498
508
  "zap2itId": id_zap2it,
499
509
  }
500
- headers = {"Authorization": f"Bearer {token}"}
501
- if language:
502
- headers["Accept-Language"] = language.a2
510
+ headers = _tvdb_headers(token, language)
503
511
  status, content = request_json(
504
512
  url, parameters, headers=headers, cache=cache is True and language is None
505
513
  )
mnamer/frontends.py CHANGED
@@ -2,7 +2,7 @@ from abc import ABC, abstractmethod
2
2
  from typing import override
3
3
 
4
4
  from mnamer import tty
5
- from mnamer.const import SYSTEM, USAGE, VERSION # pyright: ignore
5
+ from mnamer.const import SYSTEM, USAGE, VERSION
6
6
  from mnamer.exceptions import (
7
7
  MnamerAbortException,
8
8
  MnamerException,
mnamer/providers.py CHANGED
@@ -31,7 +31,7 @@ from mnamer.language import Language
31
31
  from mnamer.metadata import Metadata, MetadataEpisode, MetadataMovie
32
32
  from mnamer.setting_store import SettingStore
33
33
  from mnamer.types import MediaType, ProviderType
34
- from mnamer.utils import parse_date, year_range_parse
34
+ from mnamer.utils import parse_date, year_parse, year_range_parse
35
35
 
36
36
 
37
37
  class Provider[M: Metadata](ABC):
@@ -44,8 +44,7 @@ class Provider[M: Metadata](ABC):
44
44
  """Initializes the provider."""
45
45
  if api_key:
46
46
  self.api_key = api_key
47
- if cache:
48
- self.cache = cache
47
+ self.cache = cache
49
48
 
50
49
  @classmethod
51
50
  def from_settings(cls, settings: SettingStore) -> Self:
@@ -141,7 +140,7 @@ class Omdb(Provider[MetadataMovie]):
141
140
  synopsis=response.get("plot"),
142
141
  id_imdb=response["imdb_id"],
143
142
  )
144
- if meta.synopsis == "N/A":
143
+ if meta.synopsis and meta.synopsis.upper() == "N/A":
145
144
  meta.synopsis = None
146
145
  yield meta
147
146
 
@@ -212,6 +211,7 @@ class Tmdb(Provider[MetadataMovie]):
212
211
  self, name: str, year: str | None, language: Language | None
213
212
  ) -> Iterator[MetadataMovie]:
214
213
  assert self.api_key
214
+ requested_year = year_parse(year) if year else None
215
215
  page = 1
216
216
  page_max = 5 # each page yields a maximum of 20 results
217
217
  found = False
@@ -226,17 +226,19 @@ class Tmdb(Provider[MetadataMovie]):
226
226
  )
227
227
  for entry in response["results"]:
228
228
  try:
229
- meta = MetadataMovie(
229
+ result_year = year_parse(entry.get("release_date", ""))
230
+ if result_year is None:
231
+ continue
232
+ if requested_year and result_year != requested_year:
233
+ continue
234
+ found = True
235
+ yield MetadataMovie(
230
236
  id_tmdb=str(entry["id"]),
231
237
  name=entry["title"],
232
238
  language=language,
233
239
  synopsis=entry.get("overview"),
234
240
  year=entry.get("release_date"),
235
241
  )
236
- if not meta.year:
237
- continue
238
- yield meta
239
- found = True
240
242
  except (AttributeError, KeyError, TypeError, ValueError):
241
243
  continue
242
244
  if page == response["total_pages"]:
mnamer/utils.py CHANGED
@@ -3,7 +3,7 @@
3
3
  import datetime as dt
4
4
  import json
5
5
  import re
6
- from collections.abc import Callable, Iterable, Iterator
6
+ from collections.abc import Callable, Iterable, Iterator, Mapping
7
7
  from contextlib import nullcontext
8
8
  from os import walk
9
9
  from os.path import exists, expanduser, expandvars, getsize, splitdrive, splitext
@@ -18,7 +18,7 @@ from mnamer.const import CACHE_PATH, CURRENT_YEAR, SUBTITLE_CONTAINERS
18
18
 
19
19
 
20
20
  def clean_dict(
21
- target_dict: dict[str, Any], whitelist: Iterable[str] | None = None
21
+ target_dict: Mapping[Any, Any], whitelist: Iterable[Any] | None = None
22
22
  ) -> dict[str, str]:
23
23
  """Convenience function that removes a dicts keys that have falsy values."""
24
24
  return {
@@ -121,7 +121,7 @@ def fn_pipe[T](*fn_list: Callable[[T], T]) -> Callable[[T], T]:
121
121
  return resolver
122
122
 
123
123
 
124
- def format_dict(body: dict[str, Any]) -> str:
124
+ def format_dict(body: Mapping[Any, Any]) -> str:
125
125
  """
126
126
  Formats a dictionary into a multi-line bulleted string of key-value pairs.
127
127
  """
@@ -248,7 +248,7 @@ def request_json(
248
248
  url: str,
249
249
  parameters: dict[str, Any] | list[tuple[str, Any]] | None = None,
250
250
  body: dict[str, Any] | None = None,
251
- headers: dict[str, str] | None = None,
251
+ headers: dict[str, Any] | None = None,
252
252
  cache: bool = True,
253
253
  ) -> tuple[int, Any]:
254
254
  """
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: mnamer
3
- Version: 2.7.2.dev8
3
+ Version: 2.7.3.dev3
4
4
  Summary: A command-line utility for organizing media files.
5
5
  Author-email: Jessy Williams <jessy@jessywilliams.com>
6
6
  Maintainer-email: Jessy Williams <jessy@jessywilliams.com>
@@ -34,7 +34,7 @@ Requires-Dist: appdirs~=1.4.4
34
34
  Requires-Dist: babelfish~=0.6.1
35
35
  Requires-Dist: guessit~=3.8.0
36
36
  Requires-Dist: requests<2.35.0,>=2.33.1
37
- Requires-Dist: requests-cache~=1.3.1
37
+ Requires-Dist: requests-cache~=1.3.2
38
38
  Requires-Dist: setuptools-scm>=10.0.0
39
39
  Requires-Dist: teletype~=1.3.4
40
40
  Dynamic: license-file
@@ -1,24 +1,24 @@
1
1
  mnamer/__init__.py,sha256=ZjNNbifQHIhjmUekOwc_VZQQdR289XCqqSIdjDSF5pw,344
2
2
  mnamer/__main__.py,sha256=8AEEyLkBtfYQKOvrbg-XlLxEu9_0G-1-Rd657EBlnI8,913
3
- mnamer/__version__.py,sha256=RBCcQ_PgBZmTWJZcxA5Qyyto_6zqxd8dAOveMBFcIck,110
3
+ mnamer/__version__.py,sha256=8md2jnIUU7jY401PJIcnxnIZ5zjtEiuV6iwwW-nxtQw,110
4
4
  mnamer/argument.py,sha256=PicJzTRGmamHeSKCWwhNMuf5WBSso8AbuPoZ3yOwcI4,3293
5
5
  mnamer/const.py,sha256=__YSxzRc8qDJqp4mlJncjiaRnKoi3wMLtGT1AVAm2mc,2035
6
- mnamer/endpoints.py,sha256=QAC1Vb-T_rDYOr-Fu92THffK9Dc48nJ3Jn12nC5yA_0,22778
6
+ mnamer/endpoints.py,sha256=Lt5LUT-wFd2bpa-zPt_7_g5okKe4B9dR9hlwrdkzWyk,22857
7
7
  mnamer/exceptions.py,sha256=dyTHFfJmkntafSg4glTxGAOsBgjlY3IGKWo5KUFgFp8,629
8
- mnamer/frontends.py,sha256=x67vmtCbylxMQK5uKeKg190srhAbIY4OEjuYElZsjeM,6984
8
+ mnamer/frontends.py,sha256=XGo5FcVCy338zxwrXyTtp-pPpmeeilNrVbBYLuCojA0,6965
9
9
  mnamer/language.py,sha256=5pdZGmfw1Zv2DfZCK64LPFThOE1iIcmrhaJGIDVgByo,2707
10
10
  mnamer/metadata.py,sha256=Z3BhX-oKpwoStMkH62Zh9WCRcFTl7S3TJTPpsT-IQaw,5839
11
- mnamer/providers.py,sha256=XYIvMLAKIbAl19RmB19pkSabnkEpqZk5liz2Q4pYasI,19042
11
+ mnamer/providers.py,sha256=VJYfDWf4iDYjSXs-eINfIJ6tZGhEpNSCl9wHmLi0pLE,19274
12
12
  mnamer/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
13
  mnamer/setting_spec.py,sha256=37V7iT0_6XJdeqD6rItqQmYG-fQYQSglPX01KRls0KQ,1279
14
14
  mnamer/setting_store.py,sha256=BcnUuNn823RHpOLpWvr7gVlrHZJWfxDaNfDDNqYjcqI,15977
15
15
  mnamer/target.py,sha256=RzvtzDabkRjw2Ygzi94FwwKrjAW22RmcYJRkrPpT7c4,11091
16
16
  mnamer/tty.py,sha256=v66fiv_rq_NPayUt9QfsEx5mxPJWAF28RSKiHe6op_Q,4146
17
17
  mnamer/types.py,sha256=aYMfEcBmPhrkA9PNrtr8JrDuBXeUNN8dbmd4T5rvRjg,638
18
- mnamer/utils.py,sha256=dB_DOKlXlHwF0KGk9hF5dB9eGbyzXLajOSBc_YQevqY,15639
19
- mnamer-2.7.2.dev8.dist-info/licenses/LICENSE.txt,sha256=WxN2vPlY96aW3C_CRs4q0xOK4CxO5RTVTzf2W25hGmM,1071
20
- mnamer-2.7.2.dev8.dist-info/METADATA,sha256=4IUiAElfqQIHcR2UbU1Gh5gb21AbyDGw2M5Zlwo_1aY,8038
21
- mnamer-2.7.2.dev8.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
22
- mnamer-2.7.2.dev8.dist-info/entry_points.txt,sha256=STyNAl6d-ueccO1C_WdDfjq5GlYwi788H4AENG040fI,48
23
- mnamer-2.7.2.dev8.dist-info/top_level.txt,sha256=RER9MaloDml8ZAsXHlm6oKwvv2KgH_YWJLlOfKC1zAY,7
24
- mnamer-2.7.2.dev8.dist-info/RECORD,,
18
+ mnamer/utils.py,sha256=eBOl_Q8GhnX7gJJfWLpuDY93jt0VKW_d0MwMyeyD5FQ,15654
19
+ mnamer-2.7.3.dev3.dist-info/licenses/LICENSE.txt,sha256=WxN2vPlY96aW3C_CRs4q0xOK4CxO5RTVTzf2W25hGmM,1071
20
+ mnamer-2.7.3.dev3.dist-info/METADATA,sha256=wLtMUyh2cRSZxg0Qxqb8-mtwfhH2QkGNY0tsxOQRwFc,8038
21
+ mnamer-2.7.3.dev3.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
22
+ mnamer-2.7.3.dev3.dist-info/entry_points.txt,sha256=STyNAl6d-ueccO1C_WdDfjq5GlYwi788H4AENG040fI,48
23
+ mnamer-2.7.3.dev3.dist-info/top_level.txt,sha256=RER9MaloDml8ZAsXHlm6oKwvv2KgH_YWJLlOfKC1zAY,7
24
+ mnamer-2.7.3.dev3.dist-info/RECORD,,