Skip to content

Commit

Permalink
Merge pull request #36 from dbatten5/tmdb
Browse files Browse the repository at this point in the history
Tmdb
  • Loading branch information
dbatten5 authored Nov 18, 2021
2 parents 57dbe6f + 27e5c0e commit 5d4fedc
Show file tree
Hide file tree
Showing 13 changed files with 430 additions and 10 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@ pip install phylm
'title': 'The Matrix',
'kind': 'movie',
'year': 1999,
'cover url': 'https://some-url.com',
'cover_photo': 'https://some-url.com',
'imdb_id': '0133093',
}, {
'title': 'The Matrix Reloaded',
'kind': 'movie',
'year': 2003,
'cover url': 'https://some-url.com',
'cover_photo': 'https://some-url.com',
'imdb_id': '0234215',
}, {
...
Expand Down
50 changes: 47 additions & 3 deletions docs/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# Search movies

For a given movie title query you can return a list of search results from `IMDb`
through `get_suggestions`:
through `search_movies`:

```python
>>> from phylm.tools import search_movies
Expand All @@ -12,13 +12,13 @@ through `get_suggestions`:
'title': 'The Matrix',
'kind': 'movie',
'year': 1999,
'cover url': 'https://some-url.com',
'cover_photo': 'https://some-url.com',
'imdb_id': '0133093',
}, {
'title': 'The Matrix Reloaded',
'kind': 'movie',
'year': 2003,
'cover url': 'https://some-url.com',
'cover_photo': 'https://some-url.com',
'imdb_id': '0234215',
}, {
...
Expand All @@ -28,3 +28,47 @@ through `get_suggestions`:
rendering:
show_signature_annotations: true
heading_level: 2

# TMDB

`phylm` also provides tools to interact with [The Movie Database](https://www.themoviedb.org/) (TMDb).

!!! info ""
To use TMDB tools you'll need to sign up for an API key, instructions [here](https://developers.themoviedb.org/3).
Once you have your key, export it as an env var called `TMDB_API_KEY` so that it's
available to use in these tools. You also have the option of passing in the key as
an argument to each function.

## Search movies

For a given movie title query you can return a list of search results from `TMDb`
through `search_tmdb_movies`. Note that this search performs a lot quicker than the
`imdb` `search_movies`.

```python
>>> from phylm.tools import search_tmdb_movies
>>> search_tmdb_movies("The Matrix", api_key="abc") # the api key can be provided as an env var instead
[{
'adult': False,
'backdrop_path': '/fNG7i7RqMErkcqhohV2a6cV1Ehy.jpg',
'genre_ids': [28, 878],
'id': 603,
'original_language': 'en',
'original_title': 'The Matrix',
'overview': 'Set in the 22nd century, The Matrix tells the story of a computer hacker...'
'popularity': 79.956,
'poster_path': '/f89U3ADr1oiB1s9GkdPOEpXUk5H.jpg',
'release_date': '1999-06-11',
'title': 'The Matrix',
'video': False,
'vote_average': 8.2,
'vote_count': 20216,
}, {
...
}
```

::: phylm.tools.search_tmdb_movies
rendering:
show_signature_annotations: true
heading_level: 3
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ plugins:
rendering:
show_root_heading: true
heading_level: 1
show_source: false
watch:
- src
- autolinks
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "phylm"
version = "4.1.0"
version = "4.2.0"
description = "Phylm"
authors = ["Dom Batten <[email protected]>"]
license = "MIT"
Expand Down
1 change: 1 addition & 0 deletions src/phylm/clients/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Clients."""
41 changes: 41 additions & 0 deletions src/phylm/clients/tmdb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""Client to interact with The Movie DB (TMDB)."""
from typing import Any
from typing import Dict
from typing import List

from requests import Session


class TmdbClient:
"""Class to abstract to the Tmdb API."""

def __init__(self, api_key: str) -> None:
"""Initialize the client.
Args:
api_key: an api_key for authentication
"""
super().__init__()
self.session = Session()
self.api_key = api_key
self._base = "https://api.themoviedb.org/3"

def search_movies(self, query: str) -> List[Dict[str, Any]]:
"""Search for movies.
Args:
query: the search query
Returns:
Any: the search results
"""
payload = {
"api_key": self.api_key,
"language": "en-GB",
"query": query,
"include_adult": False,
"region": "GB",
}
res = self.session.get(f"{self._base}/search/movie", params=payload)
results: List[Dict[str, Any]] = res.json()["results"]
return results
4 changes: 4 additions & 0 deletions src/phylm/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ class UnrecognizedSourceError(Exception):

class SourceNotLoadedError(Exception):
"""Raised when data from an unloaded source is retreived."""


class NoTMDbApiKeyError(Exception):
"""Raised when requests are made to TMDb but no api_key has be provided."""
31 changes: 31 additions & 0 deletions src/phylm/tools.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
"""Module to hold `phylm` tools."""
import os
from typing import Any
from typing import Dict
from typing import List
from typing import Optional
from typing import Union

from imdb.Movie import Movie

from phylm.clients.tmdb import TmdbClient
from phylm.errors import NoTMDbApiKeyError
from phylm.sources.imdb import ia


Expand All @@ -29,3 +34,29 @@ def search_movies(query: str) -> List[Dict[str, Union[str, int]]]:
}
for r in results
]


def search_tmdb_movies(
query: str, api_key: Optional[str] = None
) -> List[Dict[str, Any]]:
"""Search for movies on TMDb.
Args:
query: the query string
api_key: an api_key can either be provided here or through a TMDB_API_KEY env
var
Raises:
NoTMDbApiKeyError: when no api_key has been provided
Returns:
List[Dict[str, Any]]: the search results
"""
tmdb_api_key = api_key or os.environ.get("TMDB_API_KEY")

if not tmdb_api_key:
raise NoTMDbApiKeyError("An `api_key` must be provided to use this service")

client = TmdbClient(api_key=tmdb_api_key)

return client.search_movies(query=query)
55 changes: 55 additions & 0 deletions tests/fixtures/vcr_cassettes/clients/tmdb/no_results.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
interactions:
- request:
body: null
headers:
Accept:
- "*/*"
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.themoviedb.org/3/search/movie?include_adult=False&language=en-GB&query=aslkdjaskldjaslkdjaslkdjasd&region=GB
response:
body:
string: !!binary |
H4sIAAAAAAAAA6tWKkhMT1WyMtRRKkotLs0pKVayio7VUSrJL0nMiQfJAQUMYHy4EoNaALNPV645
AAAA
headers:
Access-Control-Allow-Methods:
- GET, HEAD, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:
- "*"
Access-Control-Expose-Headers:
- ETag, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After,
Content-Length, Content-Range
Cache-Control:
- public, max-age=600
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json;charset=utf-8
Date:
- Thu, 18 Nov 2021 13:36:12 GMT
Server:
- openresty
Transfer-Encoding:
- chunked
Vary:
- Accept-Encoding
Via:
- 1.1 f781469e78b7a441c6f692b1629e1519.cloudfront.net (CloudFront)
X-Amz-Cf-Id:
- ZzoH_Hbughh50zblladdE7sdS_RFUstsVkCVQHAykhgmOgpaqP1jmQ==
X-Amz-Cf-Pop:
- LHR50-C1
X-Cache:
- Miss from cloudfront
status:
code: 200
message: OK
version: 1
130 changes: 130 additions & 0 deletions tests/fixtures/vcr_cassettes/clients/tmdb/the_matrix.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
interactions:
- request:
body: null
headers:
Accept:
- "*/*"
Accept-Encoding:
- gzip, deflate
Connection:
- keep-alive
User-Agent:
- python-requests/2.26.0
method: GET
uri: https://api.themoviedb.org/3/search/movie?include_adult=False&language=en-GB&query=The+Matrix&region=GB
response:
body:
string: !!binary |
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
headers:
Access-Control-Allow-Methods:
- GET, HEAD, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin:
- "*"
Access-Control-Expose-Headers:
- ETag, X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset, Retry-After,
Content-Length, Content-Range
Age:
- "54"
Cache-Control:
- public, max-age=600
Connection:
- keep-alive
Content-Encoding:
- gzip
Content-Type:
- application/json;charset=utf-8
Date:
- Thu, 18 Nov 2021 13:32:48 GMT
Server:
- openresty
Transfer-Encoding:
- chunked
Vary:
- Accept-Encoding
Via:
- 1.1 a4ba6141247f3b441c87ee1a49ec2851.cloudfront.net (CloudFront)
X-Amz-Cf-Id:
- gF2BvyhPhl7nmCbKnW6QPgVc4yCb8q2BUsuosLPc8u1HFv3dMG1wAw==
X-Amz-Cf-Pop:
- LHR52-C1
X-Cache:
- Hit from cloudfront
status:
code: 200
message: OK
version: 1
Empty file added tests/unit/clients/__init__.py
Empty file.
Loading

0 comments on commit 5d4fedc

Please sign in to comment.