├── .github ├── dependabot.yml └── workflows │ └── python-publish.yml ├── .gitignore ├── .travis.yml ├── README.rst ├── examples ├── account_info.py ├── certification.py ├── collection.py ├── company.py ├── configuration.py ├── discover.py ├── find.py ├── lists.py ├── movie_details.py ├── movie_genres.py ├── popular.py ├── recommender.py ├── search_movies.py ├── search_multi.py ├── search_tv.py └── trending.py ├── requirements.txt ├── setup.py ├── tests ├── test_account.py ├── test_as_obj.py ├── test_certification.py ├── test_change.py ├── test_collection.py ├── test_company.py ├── test_configuration.py ├── test_credit.py ├── test_discover.py ├── test_episode.py ├── test_find.py ├── test_genre.py ├── test_group.py ├── test_keyword.py ├── test_list.py ├── test_movie.py ├── test_network.py ├── test_person.py ├── test_provider.py ├── test_review.py ├── test_search.py ├── test_season.py ├── test_trending.py ├── test_tv.py └── util.py └── tmdbv3api ├── __init__.py ├── as_obj.py ├── exceptions.py ├── objs ├── __init__.py ├── account.py ├── auth.py ├── certification.py ├── change.py ├── collection.py ├── company.py ├── configuration.py ├── credit.py ├── discover.py ├── episode.py ├── find.py ├── genre.py ├── group.py ├── keyword.py ├── list.py ├── movie.py ├── network.py ├── person.py ├── provider.py ├── review.py ├── search.py ├── season.py ├── trending.py └── tv.py └── tmdb.py /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "pip" 9 | directory: "/" 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/python-publish.yml: -------------------------------------------------------------------------------- 1 | # This workflow will upload a Python Package using Twine when a release is created 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python#publishing-to-package-registries 3 | 4 | # This workflow uses actions that are not certified by GitHub. 5 | # They are provided by a third-party and are governed by 6 | # separate terms of service, privacy policy, and support 7 | # documentation. 8 | 9 | name: Upload Python Package 10 | 11 | on: 12 | release: 13 | types: [published] 14 | 15 | permissions: 16 | contents: read 17 | 18 | jobs: 19 | deploy: 20 | 21 | runs-on: ubuntu-latest 22 | 23 | steps: 24 | - uses: actions/checkout@v3 25 | - name: Set up Python 26 | uses: actions/setup-python@v3 27 | with: 28 | python-version: '3.x' 29 | - name: Install dependencies 30 | run: | 31 | python -m pip install --upgrade pip 32 | pip install build 33 | - name: Build package 34 | run: python -m build 35 | - name: Publish package 36 | uses: pypa/gh-action-pypi-publish@27b31702a0e7fc50959f5ad993c78deac1bdfc29 37 | with: 38 | user: __token__ 39 | password: ${{ secrets.PYPI_API_TOKEN }} 40 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .idea 11 | .Python 12 | test.py 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | pip-wheel-metadata/ 26 | share/python-wheels/ 27 | *.egg-info/ 28 | .installed.cfg 29 | *.egg 30 | MANIFEST 31 | 32 | # PyInstaller 33 | # Usually these files are written by a python script from a template 34 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 35 | *.manifest 36 | *.spec 37 | 38 | # Installer logs 39 | pip-log.txt 40 | pip-delete-this-directory.txt 41 | 42 | # Unit test / coverage reports 43 | htmlcov/ 44 | .tox/ 45 | .nox/ 46 | .coverage 47 | .coverage.* 48 | .cache 49 | nosetests.xml 50 | coverage.xml 51 | *.cover 52 | *.py,cover 53 | .hypothesis/ 54 | .pytest_cache/ 55 | 56 | # Translations 57 | *.mo 58 | *.pot 59 | 60 | # Django stuff: 61 | *.log 62 | local_settings.py 63 | db.sqlite3 64 | db.sqlite3-journal 65 | 66 | # Flask stuff: 67 | instance/ 68 | .webassets-cache 69 | 70 | # Scrapy stuff: 71 | .scrapy 72 | 73 | # Sphinx documentation 74 | docs/_build/ 75 | 76 | # PyBuilder 77 | target/ 78 | 79 | # Jupyter Notebook 80 | .ipynb_checkpoints 81 | 82 | # IPython 83 | profile_default/ 84 | ipython_config.py 85 | 86 | # pyenv 87 | .python-version 88 | 89 | # pipenv 90 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 91 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 92 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 93 | # install all needed dependencies. 94 | #Pipfile.lock 95 | 96 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 97 | __pypackages__/ 98 | 99 | # Celery stuff 100 | celerybeat-schedule 101 | celerybeat.pid 102 | 103 | # SageMath parsed files 104 | *.sage.py 105 | 106 | # Environments 107 | .env 108 | .venv 109 | env/ 110 | venv/ 111 | ENV/ 112 | env.bak/ 113 | venv.bak/ 114 | 115 | # Spyder project settings 116 | .spyderproject 117 | .spyproject 118 | 119 | # Rope project settings 120 | .ropeproject 121 | 122 | # mkdocs documentation 123 | /site 124 | 125 | # mypy 126 | .mypy_cache/ 127 | .dmypy.json 128 | dmypy.json 129 | 130 | # Pyre type checker 131 | .pyre/ 132 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - '2.7' 4 | - '3.4' 5 | - '3.5' 6 | - '3.6' 7 | - '3.7' 8 | - '3.8' 9 | install: 10 | - pip install -r requirements.txt 11 | - pip install codecov 12 | script: 13 | - coverage run -m unittest discover -s tests/ 14 | after_success: 15 | - codecov 16 | env: 17 | global: 18 | secure: spALfwMzii1J0fQPFqL+S4A1FKXY5KmUA4mOiZJBMpP9nlRfSYM7/W/dQaxmVctBQ3frB7o+oA9h7NkX88M0/fQDtuFBT+rkwLyfQ2KYbfeKt5aDgua3ImtaBD+LrcHSe79hbJmDohn8yBeNAL3XRIlyLr+jbFq0ELfSGWKWZeZKlIZ30O25MOG0q5IaWd5xlgLbfbvQp72e3S1bnonv8LuuW2EdAr29f/cCXNyRP54FamEYKwPeN0IzQzNgXK4UVwNfePzMNRf6kB3CG/a3/f8FL26YeFpwCBgwTaNChrjcNL7FnJ6xWCpgVAwVzqj3rjUTZ5JVm4Sf73o9qU12b0AZ/x0oJZRs/SYNjZZcEXS7/7O2J5LY/fhayz09RY/9n//Rad4L4GvdP7sAG0HbNsQVSrkdWoR4jjR59LExyHrp3kmuLrIi6HmNCxD97o6mxYa1WLvaZ6uxCgK20lca2cvFrCSpR9fWR5gmFFqCIjEYLUAccNMO+cu2MHP61h+Opl4KP88TanLiez+RlWzfNZsVCkjrqHodgWON78cw4Jt9WeYxTOe8ET7XPg5YB+cRYMKRbZWUl9DAzCQMhAlu5RUEaQdI2hTQesd5rHuLV405feHu9LKorg5Pqyx9KYAMUVtekJ3+uOkOCrq+Und9tqneHQOl9m+IHUY8QR2TQfA= 19 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | tmdbv3api 2 | ========= 3 | 4 | .. image:: https://travis-ci.org/AnthonyBloomer/tmdbv3api.svg?branch=master 5 | :target: https://travis-ci.org/AnthonyBloomer/tmdbv3api 6 | :alt: Build Status 7 | 8 | .. image:: https://codecov.io/gh/AnthonyBloomer/tmdbv3api/branch/master/graph/badge.svg 9 | :target: https://codecov.io/gh/AnthonyBloomer/tmdbv3api 10 | :alt: codecov 11 | 12 | .. image:: https://img.shields.io/github/v/release/AnthonyBloomer/tmdbv3api 13 | :target: https://github.com/AnthonyBloomer/tmdbv3api/releases 14 | :alt: GitHub release (latest by date) 15 | 16 | .. image:: https://img.shields.io/pypi/v/tmdbv3api 17 | :target: https://pypi.org/project/tmdbv3api/ 18 | :alt: PyPI 19 | 20 | .. image:: https://img.shields.io/pypi/dm/tmdbv3api.svg 21 | :target: https://pypi.org/project/tmdbv3api/ 22 | :alt: Downloads 23 | 24 | .. image:: https://img.shields.io/github/commits-since/AnthonyBloomer/tmdbv3api/latest 25 | :target: https://github.com/AnthonyBloomer/tmdbv3api/commits/master 26 | :alt: GitHub commits since latest release (by date) for a branch 27 | 28 | A lightweight Python library for The Movie Database (TMDb) API. The TMDb API is a resource for developers to integrate movie, TV show and cast data along with posters or movie fan art. themoviedb.org is a free and community edited database. 29 | 30 | Register an account: https://www.themoviedb.org/account/signup 31 | 32 | Check out the API documentation: https://developers.themoviedb.org/3/getting-started/introduction 33 | 34 | Install 35 | ~~~~~~~ 36 | 37 | tmdbv3api is available on the Python Package Index (PyPI) at 38 | https://pypi.python.org/pypi/tmdbv3api 39 | 40 | You can install tmdbv3api using pip. 41 | 42 | :: 43 | 44 | $ pip install tmdbv3api 45 | 46 | Usage 47 | ~~~~~ 48 | 49 | The first step is to initialize a TMDb object and set your API Key. 50 | 51 | .. code:: python 52 | 53 | from tmdbv3api import TMDb 54 | tmdb = TMDb() 55 | tmdb.api_key = 'YOUR_API_KEY' 56 | 57 | Alternatively, you can export your API key as an environment variable. 58 | 59 | .. code:: bash 60 | 61 | $ export TMDB_API_KEY='YOUR_API_KEY' 62 | 63 | Other configuration settings include defining your ``language`` and enabling ``debug`` mode, for example: 64 | 65 | .. code:: python 66 | 67 | tmdb.language = 'en' 68 | tmdb.debug = True 69 | 70 | Then to communicate with TMDb, create an instance of one of the objects 71 | and call that instances methods. For example, to retrieve movie 72 | recommendations for a given movie id: 73 | 74 | .. code:: python 75 | 76 | from tmdbv3api import Movie 77 | 78 | movie = Movie() 79 | 80 | recommendations = movie.recommendations(movie_id=111) 81 | 82 | for recommendation in recommendations: 83 | print(recommendation.title) 84 | print(recommendation.overview) 85 | 86 | Examples 87 | ~~~~~~~~ 88 | 89 | Get the list of popular movies on The Movie Database. This list 90 | refreshes every day. 91 | 92 | .. code:: python 93 | 94 | 95 | movie = Movie() 96 | popular = movie.popular() 97 | 98 | for p in popular: 99 | print(p.id) 100 | print(p.title) 101 | print(p.overview) 102 | print(p.poster_path) 103 | 104 | 105 | Get the primary information about a movie. 106 | 107 | .. code:: python 108 | 109 | m = movie.details(343611) 110 | 111 | print(m.title) 112 | print(m.overview) 113 | print(m.popularity) 114 | 115 | Search for movies by title. 116 | 117 | .. code:: python 118 | 119 | search = movie.search('Mad Max') 120 | 121 | for res in search: 122 | print(res.id) 123 | print(res.title) 124 | print(res.overview) 125 | print(res.poster_path) 126 | print(res.vote_average) 127 | 128 | Get the similar movies for a specific movie id. 129 | 130 | .. code:: python 131 | 132 | similar = movie.similar(777) 133 | 134 | for result in similar: 135 | print(result.title) 136 | print(result.overview) 137 | 138 | Search for TV shows by title. 139 | 140 | .. code:: python 141 | 142 | tv = TV() 143 | show = tv.search('Breaking Bad') 144 | 145 | for result in show: 146 | print(result.name) 147 | print(result.overview) 148 | 149 | Get the similar TV shows for a specific tv id. 150 | 151 | .. code:: python 152 | 153 | similar = tv.similar(1396) 154 | 155 | for show in similar: 156 | print(show.name) 157 | print(show.overview) 158 | 159 | Get the details of TV season for a specific tv id. 160 | 161 | .. code:: python 162 | 163 | season = Season() 164 | show_season = season.details(1396, 1) 165 | print(show_season.air_date) 166 | print(len(show_season.episodes)) 167 | 168 | Get the general person information for a specific id. 169 | 170 | .. code:: python 171 | 172 | person = Person() 173 | p = person.details(12) 174 | 175 | print(p.name) 176 | print(p.biography) 177 | 178 | Discover movies by different types of data like average rating, number 179 | of votes, genres and certifications. 180 | 181 | .. code:: python 182 | 183 | 184 | # What movies are in theatres? 185 | 186 | discover = Discover() 187 | movie = discover.discover_movies({ 188 | 'primary_release_date.gte': '2017-01-20', 189 | 'primary_release_date.lte': '2017-01-25' 190 | }) 191 | 192 | # What are the most popular movies? 193 | 194 | movie = discover.discover_movies({ 195 | 'sort_by': 'popularity.desc' 196 | }) 197 | 198 | # What are the most popular kids movies? 199 | 200 | movie = discover.discover_movies({ 201 | 'certification_country': 'US', 202 | 'certification.lte': 'G', 203 | 'sort_by': 'popularity.desc' 204 | }) 205 | 206 | Discover TV shows by different types of data like average rating, number 207 | of votes, genres, the network they aired on and air dates. 208 | 209 | .. code:: python 210 | 211 | # What are the most popular TV shows? 212 | 213 | show = discover.discover_tv_shows({ 214 | 'sort_by': 'popularity.desc' 215 | }) 216 | 217 | # What are the best dramas? 218 | 219 | show = discover.discover_tv_shows({ 220 | 'with_genres': 18, 221 | 'sort_by': 'vote_average.desc', 222 | 'vote_count.gte': 10 223 | }) 224 | 225 | Login to your account and add some movie recommendations to your TMDb watchlist. 226 | 227 | .. code:: python 228 | 229 | from tmdbv3api import Account 230 | from tmdbv3api import Authentication 231 | from tmdbv3api import TMDb, Movie 232 | 233 | USERNAME = "YOUR_USERNAME" 234 | PASSWORD = "YOUR_PASSWORD" 235 | 236 | tmdb = TMDb() 237 | tmdb.api_key = "YOUR_API_KEY" 238 | 239 | auth = Authentication(username=USERNAME, password=PASSWORD) 240 | 241 | account = Account() 242 | details = account.details() 243 | 244 | print("You are logged in as %s. Your account ID is %s." % (details.username, details.id)) 245 | print("This session expires at: %s" % auth.expires_at) 246 | 247 | movie = Movie() 248 | 249 | s = movie.search("Gangs of New York") 250 | first_result = s[0] 251 | recommendations = movie.recommendations(first_result.id) 252 | 253 | for recommendation in recommendations: 254 | print("Adding %s (%s) to watchlist." % (recommendation.title, recommendation.release_date)) 255 | account.add_to_watchlist(details.id, recommendation.id, "movie") 256 | 257 | 258 | Running Tests 259 | ~~~~~~~~~~~~~ 260 | 261 | You can run the tests via the command line. You must export your TMDb API key and Session ID as an environment variables. 262 | 263 | Your Session ID can be obtained by running ``Authentication(username, password).session_id`` 264 | 265 | Mac 266 | ++++++++++++++++++++++++ 267 | 268 | .. code:: bash 269 | 270 | $ export TMDB_API_KEY='YOUR_API_KEY' 271 | $ export TMDB_SESSION_ID='YOUR_SESSION_ID' 272 | 273 | Windows (Command Prompt) 274 | ++++++++++++++++++++++++ 275 | 276 | .. code:: bash 277 | 278 | $ setx TMDB_API_KEY "YOUR_API_KEY" 279 | $ setx TMDB_SESSION_ID "YOUR_SESSION_ID" 280 | 281 | Windows (PowerShell) 282 | ++++++++++++++++++++++++ 283 | 284 | .. code:: bash 285 | 286 | $ $Env:TMDB_API_KEY="YOUR_API_KEY" 287 | $ $Env:TMDB_SESSION_ID="YOUR_SESSION_ID" 288 | 289 | After you've set up your environmental variables then run: 290 | 291 | .. code:: bash 292 | 293 | $ python -m unittest discover tests/ 294 | -------------------------------------------------------------------------------- /examples/account_info.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import Account 2 | from tmdbv3api import Authentication 3 | from tmdbv3api import TMDb, Search, Movie 4 | 5 | USERNAME = "YOUR_USERNAME" 6 | PASSWORD = "YOUR_PASSWORD" 7 | 8 | tmdb = TMDb() 9 | tmdb.api_key = "YOUR_API_KEY" 10 | 11 | auth = Authentication(username=USERNAME, password=PASSWORD) 12 | 13 | account = Account() 14 | details = account.details() 15 | 16 | print( 17 | "You are logged in as %s. Your account ID is %s." % (details.username, details.id) 18 | ) 19 | print("This session expires at: %s" % auth.expires_at) 20 | 21 | search = Search() 22 | movie = Movie() 23 | 24 | s = search.movies("Gangs of New York") 25 | first_result = s[0] 26 | recommendations = movie.recommendations(first_result.id) 27 | 28 | for recommendation in recommendations: 29 | print( 30 | "Adding %s (%s) to watchlist." 31 | % (recommendation.title, recommendation.release_date) 32 | ) 33 | 34 | w = account.add_to_watchlist(details.id, recommendation.id, "movie") 35 | 36 | print(w) 37 | -------------------------------------------------------------------------------- /examples/certification.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Certification 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | certification = Certification() 8 | 9 | # Get movie certifications for USA 10 | 11 | movie_certifications = certification.movie_list().certifications 12 | 13 | for usa_certification in movie_certifications["US"]: 14 | print(usa_certification["certification"]) 15 | print(usa_certification["meaning"]) 16 | 17 | 18 | # Get tv show certifications for Spain 19 | 20 | tv_certifications = certification.tv_list().certifications 21 | 22 | for usa_certification in tv_certifications["ES"]: 23 | print(usa_certification["certification"]) 24 | print(usa_certification["meaning"]) 25 | 26 | # Get countries avaiable 27 | 28 | for country in movie_certifications: 29 | print(country) 30 | 31 | for country in tv_certifications: 32 | print(country) -------------------------------------------------------------------------------- /examples/collection.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Collection 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | tmdb.language = "en" 7 | 8 | collection = Collection() 9 | 10 | # Get collection details 11 | 12 | details = collection.details(10) 13 | print(details.id) 14 | print(details.name) 15 | print(details.overview) 16 | print(details.poster_path) 17 | for item in details: 18 | print(item["id"]) 19 | print(item["title"]) 20 | 21 | # Get collection images 22 | # If tmdb.language is 'en-US' will not work. Set tmdb.language to 'en' 23 | 24 | images = collection.images(10) 25 | print(images.id) 26 | for image in images.backdrops: 27 | print(image["file_path"]) 28 | print(image["height"]) 29 | print(image["width"]) 30 | for image in images.posters: 31 | print(image["file_path"]) 32 | print(image["height"]) 33 | print(image["width"]) 34 | 35 | # Get collection translations 36 | 37 | translations = collection.translations(10) 38 | for translation in translations: 39 | print(translation.iso_3166_1) 40 | print(translation.iso_639_1) 41 | print(translation.name) 42 | print(translation.english_name) 43 | print(translation.data["title"]) 44 | print(translation.data["overview"]) 45 | print(translation.data["homepage"]) -------------------------------------------------------------------------------- /examples/company.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Company 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | company = Company() 8 | 9 | # Company details 10 | 11 | details = company.details(1) 12 | print(details.description) 13 | print(details.headquarters) 14 | print(details.homepage) 15 | print(details.id) 16 | print(details.logo_path) 17 | print(details.name) 18 | print(details.origin_country) 19 | print(details.parent_company) 20 | 21 | # Company alternative names 22 | 23 | alternative_names = company.alternative_names(1) 24 | for alternative_name in alternative_names: 25 | print(alternative_name.name) 26 | print(alternative_name.type) 27 | 28 | # Company images 29 | 30 | images = company.images(1) 31 | for image in images: 32 | print(image.aspect_ratio) 33 | print(image.file_path) 34 | print(image.height) 35 | print(image.id) 36 | print(image.file_type) 37 | print(image.vote_average) 38 | print(image.vote_count) 39 | print(image.width) 40 | 41 | # Company movies 42 | 43 | movies = company.movies(1) 44 | for movie in movies: 45 | print(movie.id) 46 | print(movie.title) 47 | print(movie.overview) 48 | -------------------------------------------------------------------------------- /examples/configuration.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Configuration 2 | 3 | tmdb = TMDb() 4 | tmdb.api_key = "" 5 | 6 | configuration = Configuration() 7 | 8 | info = configuration.api_configuration() 9 | 10 | print('Change keys: ' + ', '.join(info.change_keys)) 11 | print('Base url: ' + info.images["base_url"]) 12 | print('Secure base url: ' + info.images["secure_base_url"]) 13 | print('Backdrop sizes: ' + ', '.join(info.images["backdrop_sizes"])) 14 | print('Logo sizes: ' + ', '.join(info.images["logo_sizes"])) 15 | print('Poster sizes: ' + ', '.join(info.images["poster_sizes"])) 16 | print('Profile sizes: ' + ', '.join(info.images["profile_sizes"])) 17 | print('Still sizes: ' + ', '.join(info.images["still_sizes"])) 18 | 19 | countries = configuration.countries() 20 | 21 | for country in countries: 22 | print('English name: ' + country['english_name']) 23 | print('iso_3166_1: ' + country['iso_3166_1']) 24 | 25 | jobs = configuration.jobs() 26 | 27 | for job in jobs: 28 | print(job['department'] + ': ' + ', '.join(job['jobs'])) 29 | 30 | languages = configuration.languages() 31 | 32 | for language in languages: 33 | print('English name: ' + language['english_name']) 34 | print('Name: ' + language['name']) 35 | print('iso_639_1: ' + language['iso_639_1']) 36 | 37 | primary_translations = configuration.primary_translations() 38 | 39 | print('Primary translations: ' + ', '.join(primary_translations)) 40 | 41 | timezones = configuration.timezones() 42 | 43 | for timezone in timezones: 44 | print(timezone['iso_3166_1'] + ': ' + ', '.join(timezone['zones'])) 45 | -------------------------------------------------------------------------------- /examples/discover.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Discover 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | discover = Discover() 8 | 9 | # What are the most popular TV shows? 10 | 11 | show = discover.discover_tv_shows({"sort_by": "popularity.desc"}) 12 | 13 | for p in show: 14 | print(p.name) 15 | print(p.overview) 16 | print("") 17 | -------------------------------------------------------------------------------- /examples/find.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Find 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | find = Find() 8 | 9 | results = find.find_by_imdb_id("tt0076759") 10 | 11 | for r in results["movie_results"]: 12 | print(r.title) 13 | print(r.id) 14 | 15 | results = find.find_by_tvdb_id("83268") 16 | 17 | for r in results["tv_results"]: 18 | print(r.title) 19 | print(r.id) 20 | 21 | results = find.find("tt0076759", "imdb_id") 22 | 23 | for r in results["movie_results"]: 24 | print(r.title) 25 | print(r.id) 26 | -------------------------------------------------------------------------------- /examples/lists.py: -------------------------------------------------------------------------------- 1 | import random 2 | 3 | from tmdbv3api import TMDb, List 4 | 5 | tmdb = TMDb() 6 | tmdb.api_key = "" 7 | 8 | lists = List() 9 | the_list = lists.details(3673) 10 | 11 | random_movie = random.choice(the_list) 12 | 13 | print("Title: %s (%s)" % (random_movie.title, random_movie.release_date)) 14 | print("Rating: %s" % random_movie.vote_average) 15 | print("Overview: %s" % random_movie.overview) 16 | -------------------------------------------------------------------------------- /examples/movie_details.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Movie 2 | 3 | tmdb = TMDb() 4 | tmdb.api_key = "" 5 | 6 | movie = Movie() 7 | 8 | m = movie.details(111) 9 | 10 | print(m.title) 11 | print(m.overview) 12 | print(m.popularity) 13 | -------------------------------------------------------------------------------- /examples/movie_genres.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Genre 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | tmdb.debug = True 7 | 8 | genre = Genre() 9 | 10 | genres = genre.movie_list() 11 | 12 | for g in genres: 13 | print(g.id) 14 | print(g.name) 15 | -------------------------------------------------------------------------------- /examples/popular.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Movie 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | movie = Movie() 8 | 9 | popular = movie.popular() 10 | 11 | for p in popular: 12 | print(p.title) 13 | print(p.overview) 14 | -------------------------------------------------------------------------------- /examples/recommender.py: -------------------------------------------------------------------------------- 1 | # Simple program that takes a movie name as an argument and finds movie recommendations for the user. 2 | 3 | from tmdbv3api import TMDb, Movie, Search 4 | from argparse import ArgumentParser 5 | 6 | tmdb = TMDb() 7 | tmdb.api_key = "" 8 | 9 | 10 | def search(query, limit): 11 | movie = Movie() 12 | search = Search() 13 | s = search.movies(query) 14 | first_result = s[0] 15 | recommendations = movie.recommendations(first_result.id) 16 | recommendations = ( 17 | recommendations[: int(limit)] if recommendations >= limit else recommendations 18 | ) 19 | for recommendation in recommendations: 20 | print("%s (%s)" % (recommendation.title, recommendation.release_date)) 21 | 22 | 23 | if __name__ == "__main__": 24 | parser = ArgumentParser() 25 | parser.add_argument("movie") 26 | parser.add_argument("--limit", nargs="?", default=1) 27 | args = parser.parse_args() 28 | search(args.movie, args.limit) 29 | -------------------------------------------------------------------------------- /examples/search_movies.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Search 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | search = Search() 8 | 9 | results = search.movies("Matrix", year=1999) 10 | 11 | for result in results: 12 | print(result.title) 13 | print(result.overview) 14 | -------------------------------------------------------------------------------- /examples/search_multi.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Search 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | search = Search() 8 | 9 | results = search.multi("Will") 10 | 11 | for result in results: 12 | print(result.media_type) 13 | -------------------------------------------------------------------------------- /examples/search_tv.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, TV 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | search = Search() 8 | 9 | show = search.tv_shows("Breaking Bad") 10 | 11 | for result in show: 12 | print(result.name) 13 | print(result.overview) 14 | -------------------------------------------------------------------------------- /examples/trending.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api import TMDb, Trending 2 | 3 | tmdb = TMDb() 4 | 5 | tmdb.api_key = "" 6 | 7 | trending = Trending() 8 | 9 | # What are the TV shows trending today? 10 | shows= trending.tv_day() 11 | 12 | for p in shows: 13 | print(p.name) 14 | print(p.overview) 15 | 16 | # What are the Movies trending this week? 17 | movies = trending.movie_week() 18 | 19 | for p in movies: 20 | print(p.name) 21 | print(p.overview) 22 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | backports.functools-lru-cache 2 | requests 3 | urllib3 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import os 4 | import sys 5 | from shutil import rmtree 6 | 7 | from setuptools import setup, Command 8 | 9 | with open("README.rst", "rb") as f: 10 | long_descr = f.read().decode("utf-8") 11 | 12 | here = os.path.abspath(os.path.dirname(__file__)) 13 | 14 | 15 | class PublishCommand(Command): 16 | """Support setup.py publish.""" 17 | 18 | description = 'Build and publish the package.' 19 | user_options = [] 20 | 21 | @staticmethod 22 | def status(s): 23 | """Prints things in bold.""" 24 | print('\033[1m{0}\033[0m'.format(s)) 25 | 26 | def initialize_options(self): 27 | pass 28 | 29 | def finalize_options(self): 30 | pass 31 | 32 | def run(self): 33 | try: 34 | self.status('Removing previous builds…') 35 | rmtree(os.path.join(here, 'dist')) 36 | except: 37 | pass 38 | 39 | self.status('Building Source and Wheel (universal) distribution…') 40 | os.system('{0} setup.py sdist bdist_wheel --universal'.format(sys.executable)) 41 | 42 | self.status('Uploading the package to PyPi via Twine…') 43 | os.system('twine upload dist/*') 44 | 45 | sys.exit() 46 | 47 | 48 | setup(name='tmdbv3api', 49 | version='1.9.0', 50 | description='A lightweight Python library for The Movie Database (TMDb) API.', 51 | long_description=long_descr, 52 | url='https://github.com/AnthonyBloomer/tmdbv3api', 53 | author='Anthony Bloomer', 54 | author_email='ant0@protonmail.ch', 55 | license='MIT', 56 | packages=['tmdbv3api', 'tmdbv3api.objs'], 57 | keywords=['movie', 'tv' 'movie database', 'tmdb', 'wrapper', 'database', 'themoviedb', 'moviedb', 'api'], 58 | install_requires=[ 59 | 'requests' 60 | ], 61 | classifiers=[ 62 | 'Development Status :: 5 - Production/Stable', 63 | 'Intended Audience :: Developers', 64 | "Topic :: Software Development :: Libraries", 65 | 'Programming Language :: Python', 66 | 'Programming Language :: Python :: 2.7', 67 | 'Programming Language :: Python :: 3', 68 | 'Programming Language :: Python :: 3.3', 69 | 'Programming Language :: Python :: 3.4', 70 | 'Programming Language :: Python :: 3.5', 71 | 'Programming Language :: Python :: 3.6', 72 | 'Programming Language :: Python :: 3.7', 73 | 'Programming Language :: Python :: 3.8', 74 | ], 75 | cmdclass={ 76 | 'publish': PublishCommand, 77 | }, 78 | zip_safe=False) 79 | -------------------------------------------------------------------------------- /tests/test_account.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import time 4 | import unittest 5 | import util 6 | 7 | from tmdbv3api import Account, Movie, TV, Episode 8 | 9 | 10 | class CertificationTests(unittest.TestCase): 11 | def setUp(self): 12 | self.tmdb = util.setup() 13 | self.account = Account() 14 | self.movie = Movie() 15 | self.tv = TV() 16 | self.episode = Episode() 17 | self.test_movie_id = 843906 18 | self.test_tv_id = 69050 19 | self.test_season = 5 20 | self.test_episode = 1 21 | self.test_rating = 8.5 22 | 23 | def test_get_account_details(self): 24 | util.assertAttrs(self, self.account.details(), [ 25 | "avatar", "id", "iso_639_1", "iso_3166_1", "include_adult", "username", "name" 26 | ]) 27 | 28 | def test_get_account_created_lists(self): 29 | lists = self.account.created_lists() 30 | util.assertAttrs(self, lists, util.pagination_attributes) 31 | util.assertListAttrs(self, lists, "results", util.list_attributes + ["list_type"]) 32 | 33 | def test_get_account_favorite_movies(self): 34 | self.account.mark_as_favorite(self.test_movie_id, "movie") 35 | states = self.movie.account_states(self.test_movie_id) 36 | self.assertTrue(states.favorite) 37 | 38 | movies = self.account.favorite_movies() 39 | util.assertAttrs(self, movies, util.pagination_attributes) 40 | util.assertListAttrs(self, movies, "results", util.movie_attributes + ["genre_ids"]) 41 | 42 | self.account.unmark_as_favorite(self.test_movie_id, "movie") 43 | states = self.movie.account_states(self.test_movie_id) 44 | self.assertFalse(states.favorite) 45 | 46 | def test_get_account_favorite_tv_shows(self): 47 | self.account.mark_as_favorite(self.test_tv_id, "tv") 48 | states = self.tv.account_states(self.test_tv_id) 49 | self.assertTrue(states.favorite) 50 | 51 | shows = self.account.favorite_tv_shows() 52 | util.assertAttrs(self, shows, util.pagination_attributes) 53 | util.assertListAttrs(self, shows, "results", util.tv_attributes + ["genre_ids"]) 54 | 55 | self.account.unmark_as_favorite(self.test_tv_id, "tv") 56 | states = self.tv.account_states(self.test_tv_id) 57 | self.assertFalse(states.favorite) 58 | 59 | def test_get_account_rated_movies(self): 60 | self.movie.rate_movie(self.test_movie_id, self.test_rating) 61 | time.sleep(2) 62 | states = self.movie.account_states(self.test_movie_id) 63 | self.assertFalse(isinstance(states.rated, bool)) 64 | self.assertEqual(states.rated.value, self.test_rating) 65 | 66 | rated = self.account.rated_movies() 67 | util.assertAttrs(self, rated, util.pagination_attributes) 68 | util.assertListAttrs(self, rated, "results", util.movie_attributes + ["rating", "genre_ids"]) 69 | 70 | self.movie.delete_rating(self.test_movie_id) 71 | time.sleep(2) 72 | states = self.movie.account_states(self.test_movie_id) 73 | self.assertFalse(states.rated) 74 | 75 | def test_get_account_rated_tv_shows(self): 76 | self.tv.rate_tv_show(self.test_tv_id, self.test_rating) 77 | time.sleep(2) 78 | states = self.tv.account_states(self.test_tv_id) 79 | self.assertFalse(isinstance(states.rated, bool)) 80 | self.assertEqual(states.rated.value, self.test_rating) 81 | 82 | rated = self.account.rated_tv_shows() 83 | util.assertAttrs(self, rated, util.pagination_attributes) 84 | util.assertListAttrs(self, rated, "results", util.tv_attributes + ["rating", "genre_ids"]) 85 | 86 | self.tv.delete_rating(self.test_tv_id) 87 | time.sleep(2) 88 | states = self.tv.account_states(self.test_tv_id) 89 | self.assertFalse(states.rated) 90 | 91 | def test_get_account_rated_episodes(self): 92 | self.episode.rate_tv_episode(self.test_tv_id, self.test_season, self.test_episode, self.test_rating) 93 | time.sleep(2) 94 | states = self.episode.account_states(self.test_tv_id, self.test_season, self.test_episode) 95 | self.assertFalse(isinstance(states.rated, bool)) 96 | self.assertEqual(states.rated.value, self.test_rating) 97 | 98 | rated = self.account.rated_episodes() 99 | util.assertAttrs(self, rated, util.pagination_attributes) 100 | util.assertListAttrs(self, rated, "results", util.episode_attributes + ["show_id", "rating"]) 101 | 102 | self.episode.delete_rating(self.test_tv_id, self.test_season, self.test_episode) 103 | time.sleep(2) 104 | states = self.episode.account_states(self.test_tv_id, self.test_season, self.test_episode) 105 | self.assertFalse(states.rated) 106 | 107 | def test_get_account_movie_watchlist(self): 108 | self.account.add_to_watchlist(self.test_movie_id, "movie") 109 | states = self.movie.account_states(self.test_movie_id) 110 | self.assertTrue(states.watchlist) 111 | 112 | watchlist = self.account.movie_watchlist() 113 | util.assertAttrs(self, watchlist, util.pagination_attributes) 114 | util.assertListAttrs(self, watchlist, "results", util.movie_attributes + ["genre_ids"]) 115 | 116 | self.account.remove_from_watchlist(self.test_movie_id, "movie") 117 | states = self.movie.account_states(self.test_movie_id) 118 | self.assertFalse(states.watchlist) 119 | 120 | def test_get_account_show_watchlist(self): 121 | self.account.add_to_watchlist(self.test_tv_id, "tv") 122 | states = self.tv.account_states(self.test_tv_id) 123 | self.assertTrue(states.watchlist) 124 | 125 | watchlist = self.account.tv_show_watchlist() 126 | util.assertAttrs(self, watchlist, util.pagination_attributes) 127 | util.assertListAttrs(self, watchlist, "results", util.tv_attributes + ["genre_ids"]) 128 | 129 | self.account.remove_from_watchlist(self.test_tv_id, "tv") 130 | states = self.tv.account_states(self.test_tv_id) 131 | self.assertFalse(states.watchlist) 132 | -------------------------------------------------------------------------------- /tests/test_as_obj.py: -------------------------------------------------------------------------------- 1 | import sys 2 | from unittest import TestCase 3 | from tmdbv3api.as_obj import AsObj 4 | 5 | 6 | class AsObjTests(TestCase): 7 | def setUp(self): 8 | self.entries = { 9 | 'title': 'images', 10 | 'results': [ 11 | { 12 | 'path': 'img/', 13 | 'title': 'img1' 14 | }, 15 | { 16 | 'path': 'img/', 17 | 'title': 'img2' 18 | } 19 | ], 20 | 'formats': ['.jpg', '.png'], 21 | 'languages': { 22 | 'ES': 'es-ES', 23 | 'FR': 'fr-FR' 24 | } 25 | } 26 | 27 | def assert_attr(self, dict_obj): 28 | self.assertIsNotNone(dict_obj) 29 | 30 | self.assertTrue(hasattr(dict_obj, 'title')) 31 | self.assertTrue(isinstance(dict_obj.title, str)) 32 | self.assertEqual(dict_obj.title, 'images') 33 | 34 | self.assertTrue(hasattr(dict_obj, 'results')) 35 | self.assertTrue(isinstance(dict_obj.results, AsObj)) 36 | self.assertTrue(dict_obj.results._list_only) 37 | for result in dict_obj.results: 38 | self.assertTrue(isinstance(result, AsObj)) 39 | self.assertTrue(hasattr(result, 'path')) 40 | self.assertTrue(hasattr(result, 'title')) 41 | self.assertTrue(isinstance(result.path, str)) 42 | self.assertTrue(isinstance(result.title, str)) 43 | 44 | self.assertTrue(hasattr(dict_obj, 'formats')) 45 | self.assertTrue(isinstance(dict_obj.formats, AsObj)) 46 | self.assertTrue(dict_obj.formats._list_only) 47 | self.assertIn('.jpg', dict_obj.formats) 48 | self.assertIn('.png', dict_obj.formats) 49 | 50 | self.assertTrue(hasattr(dict_obj, 'languages')) 51 | self.assertTrue(isinstance(dict_obj.languages, AsObj)) 52 | self.assertTrue(hasattr(dict_obj.languages, 'ES')) 53 | self.assertTrue(hasattr(dict_obj.languages, 'FR')) 54 | self.assertTrue(isinstance(dict_obj.languages.ES, str)) 55 | self.assertTrue(isinstance(dict_obj.languages.FR, str)) 56 | self.assertEqual(dict_obj.languages.ES, 'es-ES') 57 | self.assertEqual(dict_obj.languages.FR, 'fr-FR') 58 | 59 | def assert_dict(self, dict_obj): 60 | self.assertIsNotNone(dict_obj) 61 | 62 | self.assertIn('title', dict_obj) 63 | self.assertTrue(isinstance(dict_obj['title'], str)) 64 | self.assertEqual(dict_obj['title'], 'images') 65 | 66 | self.assertIn('results', dict_obj) 67 | self.assertTrue(isinstance(dict_obj['results'], AsObj)) 68 | self.assertTrue(dict_obj['results']._list_only) 69 | for result in dict_obj['results']: 70 | self.assertTrue(isinstance(result, AsObj)) 71 | self.assertIn('path', result) 72 | self.assertIn('title', result) 73 | self.assertTrue(isinstance(result['path'], str)) 74 | self.assertTrue(isinstance(result['title'], str)) 75 | 76 | self.assertIn('formats', dict_obj) 77 | self.assertTrue(isinstance(dict_obj['formats'], AsObj)) 78 | self.assertTrue(dict_obj['formats']._list_only) 79 | self.assertIn('.jpg', dict_obj['formats']) 80 | self.assertIn('.png', dict_obj['formats']) 81 | 82 | self.assertIn('languages', dict_obj) 83 | self.assertTrue(isinstance(dict_obj['languages'], AsObj)) 84 | self.assertIn('ES', dict_obj['languages']) 85 | self.assertIn('FR', dict_obj['languages']) 86 | self.assertTrue(isinstance(dict_obj['languages']['ES'], str)) 87 | self.assertTrue(isinstance(dict_obj['languages']['FR'], str)) 88 | self.assertEqual(dict_obj['languages']['ES'], 'es-ES') 89 | self.assertEqual(dict_obj['languages']['FR'], 'fr-FR') 90 | 91 | def test_dict_obj__init__(self): 92 | dict_obj = AsObj(self.entries) 93 | self.assert_attr(dict_obj) 94 | self.assert_dict(dict_obj) 95 | self.assert_dict(dict_obj.__dict__) 96 | 97 | def test_dict_obj__len__(self): 98 | self.assertEqual(len(AsObj({'a': 1, 'b': 2})), 2) 99 | self.assertEqual(len(AsObj()), 0) 100 | 101 | def test_dict_obj__getitem__(self): 102 | dict_obj = AsObj(self.entries) 103 | self.assertEqual(dict_obj['title'], 'images') 104 | self.assertEqual(dict_obj['results'][0]['path'], 'img/') 105 | self.assertEqual(dict_obj['formats'][0], '.jpg') 106 | self.assertEqual(dict_obj['languages']['ES'], 'es-ES') 107 | 108 | def test_dict_obj__setitem__(self): 109 | dict_obj = AsObj() 110 | dict_obj['title'] = 'images' 111 | dict_obj['results'] = [{'path': 'img/'}] 112 | dict_obj['formats'] = ['.jpg'] 113 | dict_obj['languages'] = {'ES': 'es-ES'} 114 | self.assertEqual(dict_obj['title'], 'images') 115 | self.assertEqual(dict_obj['results'][0]['path'], 'img/') 116 | self.assertEqual(dict_obj['formats'][0], '.jpg') 117 | self.assertEqual(dict_obj['languages']['ES'], 'es-ES') 118 | 119 | def test_dict_obj__delitem__(self): 120 | dict_obj = AsObj(self.entries) 121 | self.assertIn('title', dict_obj) 122 | del dict_obj['title'] 123 | self.assertNotIn('title', dict_obj) 124 | 125 | def test_dict_obj__iter__(self): 126 | try: 127 | iter(AsObj(self.entries)) 128 | except TypeError: 129 | self.fail('Not iterable') 130 | 131 | def test_dict_obj__reversed__(self): 132 | if sys.version_info >= (3, 8): 133 | try: 134 | reversed(AsObj(self.entries)) 135 | except TypeError: 136 | self.fail('Not reverse iterable') 137 | 138 | def test_dict_obj_copy(self): 139 | dict_obj = AsObj(self.entries) 140 | dict_obj_copy = dict_obj.copy() 141 | self.assertTrue(hasattr(dict_obj_copy, 'title')) 142 | 143 | def test_dict_obj_get(self): 144 | get = AsObj(self.entries).get('title') 145 | self.assertEqual(get, 'images') 146 | 147 | def test_dict_obj_items(self): 148 | items = AsObj(self.entries).items() 149 | self.assertEqual(len(items), 4) 150 | self.assertIn(('title', 'images'), items) 151 | 152 | def test_dict_obj_keys(self): 153 | keys = AsObj(self.entries).keys() 154 | self.assertEqual(len(keys), 4) 155 | self.assertIn('title', keys) 156 | 157 | def test_dict_obj_pop(self): 158 | dict_obj = AsObj(self.entries) 159 | pop = dict_obj.pop('title') 160 | self.assertNotIn('title', dict_obj) 161 | self.assertEqual(pop, 'images') 162 | pop = dict_obj.pop('random', 'not_exists') 163 | self.assertEqual(pop, 'not_exists') 164 | 165 | def test_dict_obj_popitem(self): 166 | popitem = AsObj(self.entries).popitem() 167 | self.assertIsNotNone(popitem) 168 | 169 | def test_dict_obj_setdefault(self): 170 | dict_obj = AsObj(self.entries) 171 | self.assertEqual(dict_obj.setdefault('title'), 'images') 172 | self.assertEqual(dict_obj.setdefault('random', 'modern'), 'modern') 173 | 174 | def test_dict_obj_update(self): 175 | dict_obj = AsObj() 176 | dict_obj.update(self.entries) 177 | self.assertTrue(hasattr(dict_obj, 'title')) 178 | 179 | def test_dict_obj_values(self): 180 | values = AsObj(self.entries).values() 181 | self.assertEqual(len(values), 4) 182 | self.assertIn('images', values) 183 | -------------------------------------------------------------------------------- /tests/test_certification.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import util 4 | import unittest 5 | 6 | from tmdbv3api import Certification 7 | 8 | 9 | class CertificationTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.certification = Certification() 13 | 14 | def assert_cert(self, cert): 15 | util.assertListAttrs(self, cert, "certifications", ["certifications"]) 16 | 17 | def test_get_certification_movie_list(self): 18 | self.assert_cert(self.certification.movie_list()) 19 | 20 | def test_get_certification_tv_list(self): 21 | self.assert_cert(self.certification.tv_list()) 22 | -------------------------------------------------------------------------------- /tests/test_change.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Change 7 | 8 | 9 | class ChangesTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.change = Change() 13 | 14 | def assert_changes(self, changes): 15 | util.assertAttrs(self, changes, util.pagination_attributes) 16 | util.assertAttrs(self, changes[0], ["id", "adult"]) 17 | 18 | def test_get_changes_movie_changes(self): 19 | self.assert_changes(self.change.movie_change_list()) 20 | 21 | def test_get_changes_tv_changes(self): 22 | self.assert_changes(self.change.tv_change_list()) 23 | 24 | def test_get_changes_person_changes(self): 25 | self.assert_changes(self.change.person_change_list()) 26 | -------------------------------------------------------------------------------- /tests/test_collection.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Collection 7 | 8 | 9 | class CollectionTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.collection = Collection() 13 | self.test_collection_id = 10 14 | 15 | def test_get_collection_details(self): 16 | details = self.collection.details(self.test_collection_id) 17 | util.assertAttrs(self, details, ["id", "name", "overview", "poster_path", "backdrop_path", "parts"]) 18 | self.assertEqual(details.id, self.test_collection_id) 19 | util.assertListAttrs(self, details, "parts", util.movie_attributes + ["genre_ids"]) 20 | 21 | def test_get_collection_images(self): 22 | images = self.collection.images(self.test_collection_id) 23 | util.assertAttrs(self, images, ["id", "backdrops", "posters"]) 24 | self.assertEqual(images.id, self.test_collection_id) 25 | util.assertListAttrs(self, images, "backdrops", util.image_attributes + ["iso_639_1"]) 26 | util.assertListAttrs(self, images, "posters", util.image_attributes + ["iso_639_1"]) 27 | 28 | def test_get_collection_translations(self): 29 | translations = self.collection.translations(self.test_collection_id) 30 | util.assertAttrs(self, translations, ["id", "translations"]) 31 | self.assertEqual(translations.id, self.test_collection_id) 32 | util.assertListAttrs(self, translations, "translations", util.translation_attributes) 33 | -------------------------------------------------------------------------------- /tests/test_company.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Company 7 | 8 | 9 | class CompanyTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.company = Company() 13 | self.test_company_id = 1 14 | 15 | def test_get_company_details(self): 16 | details = self.company.details(self.test_company_id) 17 | util.assertAttrs(self, details, [ 18 | "description", "headquarters", "homepage", "id", "logo_path", "name", "origin_country", "parent_company" 19 | ]) 20 | self.assertEqual(details.id, self.test_company_id) 21 | 22 | def test_get_company_alternative_names(self): 23 | alternative_names = self.company.alternative_names(self.test_company_id) 24 | self.assertEqual(alternative_names.id, self.test_company_id) 25 | util.assertListAttrs(self, alternative_names, "results", ["name", "type"]) 26 | 27 | def test_get_company_images(self): 28 | images = self.company.images(self.test_company_id) 29 | util.assertAttrs(self, images, ["id", "logos"]) 30 | self.assertEqual(images.id, self.test_company_id) 31 | util.assertListAttrs(self, images, "logos", util.image_attributes + ["id", "file_type"]) 32 | 33 | def test_get_company_movies(self): 34 | movies = self.company.movies(self.test_company_id) 35 | util.assertAttrs(self, movies, util.pagination_attributes) 36 | util.assertListAttrs(self, movies, "results", util.movie_attributes + ["genre_ids"]) 37 | -------------------------------------------------------------------------------- /tests/test_configuration.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Configuration 7 | 8 | 9 | class ConfigurationTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.configuration = Configuration() 13 | 14 | def test_api_configuration(self): 15 | info = self.configuration.api_configuration() 16 | util.assertAttrs(self, info, ["images", "change_keys"]) 17 | util.assertAttrs(self, info.images, [ 18 | "base_url", "secure_base_url", "backdrop_sizes", "logo_sizes", 19 | "poster_sizes", "profile_sizes", "still_sizes" 20 | ]) 21 | 22 | def test_configuration_countries(self): 23 | countries = self.configuration.countries() 24 | util.assertListAttrs(self, countries, None, ["iso_3166_1", "english_name"]) 25 | 26 | def test_configuration_jobs(self): 27 | jobs = self.configuration.jobs() 28 | util.assertListAttrs(self, jobs, None, ["department", "jobs"]) 29 | 30 | def test_configuration_languages(self): 31 | languages = self.configuration.languages() 32 | util.assertListAttrs(self, languages, None, ["iso_639_1", "english_name", "name"]) 33 | 34 | def test_configuration_primary_translations(self): 35 | primary_translations = self.configuration.primary_translations() 36 | self.assertGreater(len(primary_translations), 0) 37 | self.assertIn("en-US", primary_translations) 38 | 39 | def test_configuration_timezones(self): 40 | timezones = self.configuration.timezones() 41 | util.assertListAttrs(self, timezones, None, ["iso_3166_1", "zones"]) 42 | -------------------------------------------------------------------------------- /tests/test_credit.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Credit 7 | 8 | 9 | class CreditsTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.credit = Credit() 13 | self.test_credit_id = "52542282760ee313280017f9" 14 | 15 | def test_get_credit_details(self): 16 | credit = self.credit.details(self.test_credit_id) 17 | util.assertAttrs(self, credit, ["credit_type", "department", "job", "media", "media_type", "id", "person"]) 18 | self.assertEqual(credit.id, self.test_credit_id) 19 | util.assertAttrs(self, credit.media, ["id", "name"]) 20 | util.assertAttrs(self, credit.person, ["id", "name"]) 21 | -------------------------------------------------------------------------------- /tests/test_discover.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Discover 7 | 8 | 9 | class DiscoverTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.discover = Discover() 13 | 14 | def test_get_discover_movies(self): 15 | discover = self.discover.discover_movies({ 16 | "primary_release_year": "2015", 17 | "with_genres": "28", 18 | "vote_average.gte": "8", 19 | "page": "1" 20 | }) 21 | util.assertAttrs(self, discover, util.pagination_attributes) 22 | self.assertGreater(len(discover.results), 0) 23 | util.assertAttrs(self, discover[0], util.movie_attributes + ["genre_ids"]) 24 | self.assertGreaterEqual(discover[0].vote_average, 8) 25 | self.assertIn(28, discover[0].genre_ids) 26 | 27 | def test_get_discover_tv_shows(self): 28 | discover = self.discover.discover_tv_shows({ 29 | "with_genres": "16", 30 | "vote_average.gte": "8", 31 | "page": "1" 32 | }) 33 | util.assertAttrs(self, discover, util.pagination_attributes) 34 | self.assertGreater(len(discover.results), 0) 35 | util.assertAttrs(self, discover[0], util.tv_attributes + ["genre_ids"]) 36 | self.assertGreaterEqual(discover[0].vote_average, 8) 37 | self.assertIn(16, discover[0].genre_ids) 38 | -------------------------------------------------------------------------------- /tests/test_episode.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Episode 7 | 8 | 9 | class EpisodeTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.episode = Episode() 13 | self.test_tv_id = 69050 14 | self.test_episode_id = 2482624 15 | self.test_season = 5 16 | self.test_episode = 1 17 | 18 | def test_get_episode_details(self): 19 | details = self.episode.details(self.test_tv_id, self.test_season, self.test_episode) 20 | util.assertAttrs(self, details, util.episode_attributes + ["crew", "guest_stars"]) 21 | self.assertEqual(details.id, self.test_episode_id) 22 | self.assertEqual(details.season_number, self.test_season) 23 | self.assertEqual(details.episode_number, self.test_episode) 24 | 25 | def test_get_episode_changes(self): 26 | changes = self.episode.changes(self.test_episode_id, start_date="2021-09-01", end_date="2021-09-14") 27 | util.assertListAttrs(self, changes, "changes", ["key", "items"]) 28 | 29 | def test_get_episode_credits(self): 30 | credits = self.episode.credits(self.test_tv_id, self.test_season, self.test_episode) 31 | util.assertAttrs(self, credits, ["id", "cast", "crew", "guest_stars"]) 32 | self.assertEqual(credits.id, self.test_episode_id) 33 | 34 | def test_get_episode_external_id(self): 35 | external = self.episode.external_ids(self.test_tv_id, self.test_season, self.test_episode) 36 | util.assertAttrs(self, external, ["id", "imdb_id", "tvdb_id", "tvrage_id", "freebase_mid", "freebase_id"]) 37 | self.assertEqual(external.id, self.test_episode_id) 38 | self.assertEqual(external.imdb_id, "tt11568508") 39 | self.assertEqual(external.tvdb_id, 8020104) 40 | 41 | def test_get_episode_images(self): 42 | images = self.episode.images(self.test_tv_id, self.test_season, self.test_episode) 43 | util.assertAttrs(self, images, ["id", "stills"]) 44 | self.assertEqual(images.id, self.test_episode_id) 45 | util.assertListAttrs(self, images, "stills", util.image_attributes + ["iso_639_1"]) 46 | 47 | def test_get_episode_translations(self): 48 | translations = self.episode.translations(self.test_tv_id, self.test_season, self.test_episode) 49 | util.assertAttrs(self, translations, ["id", "translations"]) 50 | self.assertEqual(translations.id, self.test_episode_id) 51 | util.assertListAttrs(self, translations, "translations", util.translation_attributes) 52 | 53 | def test_get_episode_videos(self): 54 | videos = self.episode.videos(self.test_tv_id, self.test_season, self.test_episode) 55 | util.assertAttrs(self, videos, ["id", "results"]) 56 | self.assertEqual(videos.id, self.test_episode_id) 57 | -------------------------------------------------------------------------------- /tests/test_find.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Find 7 | 8 | 9 | class FindTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.find = Find() 13 | 14 | def test_find_by_imdb_id(self): 15 | results = self.find.find_by_imdb_id("tt0364845") 16 | self.assertGreater(len(results.tv_results), 0) 17 | 18 | def test_find_by_tvdb_id(self): 19 | results = self.find.find_by_tvdb_id("72108") 20 | self.assertGreater(len(results.tv_results), 0) 21 | 22 | def test_find_by_freebase_mid(self): 23 | results = self.find.find_by_freebase_mid("/m/03m8sg") 24 | self.assertGreater(len(results.tv_results), 0) 25 | 26 | def test_find_by_freebase_id(self): 27 | results = self.find.find_by_freebase_id("/en/ncis") 28 | self.assertGreater(len(results.tv_results), 0) 29 | 30 | def test_find_by_tvrage_id(self): 31 | results = self.find.find_by_tvrage_id("4628") 32 | self.assertGreater(len(results.tv_results), 0) 33 | 34 | def test_find_by_facebook_id(self): 35 | results = self.find.find_by_facebook_id("NCIS") 36 | self.assertGreater(len(results.tv_results), 0) 37 | 38 | def test_find_by_instagram_id(self): 39 | results = self.find.find_by_instagram_id("ncis_cbs") 40 | self.assertGreater(len(results.tv_results), 0) 41 | 42 | def test_find_by_twitter_id(self): 43 | results = self.find.find_by_twitter_id("NCIS_CBS") 44 | self.assertGreater(len(results.tv_results), 0) 45 | -------------------------------------------------------------------------------- /tests/test_genre.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Genre 7 | 8 | 9 | class GenreTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.genre = Genre() 13 | 14 | def test_get_genre_movie_list(self): 15 | movie_genres = self.genre.movie_list() 16 | util.assertListAttrs(self, movie_genres, "genres", ["id", "name"]) 17 | 18 | def test_get_genre_tv_list(self): 19 | tv_genres = self.genre.tv_list() 20 | util.assertListAttrs(self, tv_genres, "genres", ["id", "name"]) 21 | -------------------------------------------------------------------------------- /tests/test_group.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Group 7 | 8 | 9 | class GroupTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.group = Group() 13 | self.test_group_id = "5b11ba820e0a265847002c6e" 14 | 15 | def test_get_group_details(self): 16 | details = self.group.details(self.test_group_id) 17 | util.assertAttrs(self, details, util.episode_group_attributes) 18 | self.assertEqual(details.id, self.test_group_id) 19 | util.assertAttrs(self, details.network, ["id", "logo_path", "name", "origin_country"]) 20 | util.assertListAttrs(self, details, "groups", ["id", "name", "order", "episodes", "locked"]) 21 | -------------------------------------------------------------------------------- /tests/test_keyword.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Keyword 7 | 8 | 9 | class KeywordTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.keyword = Keyword() 13 | self.test_keyword_id = 180547 14 | 15 | def test_get_keyword_details(self): 16 | details = self.keyword.details(self.test_keyword_id) 17 | util.assertAttrs(self, details, ["id", "name"]) 18 | self.assertEqual(details.id, self.test_keyword_id) 19 | 20 | def test_get_keyword_movies(self): 21 | movies = self.keyword.movies(self.test_keyword_id) 22 | util.assertAttrs(self, movies, util.pagination_attributes) 23 | self.assertEqual(movies.id, self.test_keyword_id) 24 | util.assertListAttrs(self, movies, "results", util.movie_attributes + ["genre_ids"]) 25 | -------------------------------------------------------------------------------- /tests/test_list.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import List 7 | from tmdbv3api.exceptions import TMDbException 8 | 9 | 10 | class ListTests(unittest.TestCase): 11 | def setUp(self): 12 | self.tmdb = util.setup() 13 | self.list = List() 14 | self.test_list_id = 112870 15 | self.test_movie_id = 540111 16 | self.test_movie_id_fail = 111 17 | 18 | def test_get_list_details(self): 19 | details = self.list.details(self.test_list_id) 20 | util.assertAttrs(self, details, util.list_attributes + ["created_by", "items"]) 21 | self.assertEqual(details.id, str(self.test_list_id)) 22 | util.assertListAttrs(self, details, "items", util.movie_attributes + ["genre_ids"]) 23 | 24 | def test_get_list_check_item_status(self): 25 | self.list.check_item_status(self.test_list_id, self.test_movie_id) 26 | self.assertTrue(self.list.check_item_status(self.test_list_id, self.test_movie_id)) 27 | self.assertFalse(self.list.check_item_status(self.test_list_id, self.test_movie_id_fail)) 28 | 29 | def test_post_list_methods(self): 30 | # create_list 31 | list_id = self.list.create_list("Test List", "Test Description") 32 | self.assertGreater(int(list_id), 10) 33 | 34 | # add_movie 35 | self.list.add_movie(list_id, self.test_movie_id) 36 | details = self.list.details(list_id) 37 | self.assertEqual(details.id, str(list_id)) 38 | self.assertEqual(details[0].id, self.test_movie_id) 39 | 40 | # remove_movie 41 | self.list.remove_movie(list_id, self.test_movie_id) 42 | details = self.list.details(list_id) 43 | self.assertEqual(len(details.items), 0) 44 | 45 | # clear_list 46 | self.list.add_movie(list_id, self.test_movie_id) 47 | details = self.list.details(list_id) 48 | self.assertEqual(details[0].id, self.test_movie_id) 49 | self.list.clear_list(list_id) 50 | details = self.list.details(list_id) 51 | self.assertEqual(len(details.items), 0) 52 | 53 | # delete_list 54 | try: 55 | self.list.delete_list(list_id) 56 | except TMDbException: 57 | pass 58 | self.assertRaises(TMDbException, self.list.details, list_id) 59 | -------------------------------------------------------------------------------- /tests/test_movie.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Movie 7 | 8 | 9 | class MovieTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.movie = Movie() 13 | self.test_movie_id = 111 14 | 15 | def test_get_movie_details(self): 16 | details = self.movie.details(self.test_movie_id) 17 | util.assertAttrs(self, details, util.movie_attributes + ["genres"]) 18 | self.assertEqual(details.id, self.test_movie_id) 19 | 20 | def test_get_movie_alternative_titles(self): 21 | alternative_titles = self.movie.alternative_titles(self.test_movie_id) 22 | util.assertAttrs(self, alternative_titles, ["id"]) 23 | self.assertEqual(alternative_titles.id, self.test_movie_id) 24 | util.assertListAttrs(self, alternative_titles, "titles", util.alt_titles_attributes) 25 | 26 | def asset_changes(self, changes): 27 | util.assertAttrs(self, changes, ["changes"]) 28 | util.assertListAttrs(self, changes, "changes", ["key", "items"]) 29 | 30 | def test_get_movie_changes(self): 31 | self.asset_changes(self.movie.changes(self.test_movie_id, start_date="2016-08-29", end_date="2016-09-10")) 32 | self.asset_changes(self.movie.changes(self.test_movie_id, start_date="2016-08-29")) 33 | self.asset_changes(self.movie.changes(self.test_movie_id, end_date="2016-09-10")) 34 | 35 | def test_get_movie_credits(self): 36 | credits = self.movie.credits(self.test_movie_id) 37 | util.assertAttrs(self, credits, ["id", "cast", "crew"]) 38 | self.assertEqual(credits.id, self.test_movie_id) 39 | 40 | def test_get_movie_external_ids(self): 41 | external = self.movie.external_ids(self.test_movie_id) 42 | util.assertAttrs(self, external, ["id", "imdb_id", "facebook_id", "instagram_id", "twitter_id"]) 43 | self.assertEqual(external.id, self.test_movie_id) 44 | self.assertEqual(external.imdb_id, "tt0086250") 45 | 46 | def test_get_movie_images(self): 47 | images = self.movie.images(self.test_movie_id) 48 | util.assertAttrs(self, images, ["id"]) 49 | self.assertEqual(images.id, self.test_movie_id) 50 | util.assertListAttrs(self, images, "backdrops", util.image_attributes + ["iso_639_1"]) 51 | util.assertListAttrs(self, images, "posters", util.image_attributes + ["iso_639_1"]) 52 | util.assertListAttrs(self, images, "logos", util.image_attributes + ["iso_639_1"]) 53 | 54 | def test_get_movie_keywords(self): 55 | keywords = self.movie.keywords(self.test_movie_id) 56 | util.assertAttrs(self, keywords, ["id", "keywords"]) 57 | self.assertEqual(keywords.id, self.test_movie_id) 58 | util.assertListAttrs(self, keywords, "keywords", ["id", "name"]) 59 | 60 | def test_get_movie_lists(self): 61 | lists = self.movie.lists(self.test_movie_id) 62 | util.assertAttrs(self, lists, util.pagination_attributes) 63 | util.assertListAttrs(self, lists, "results", util.list_attributes + ["list_type"]) 64 | 65 | def test_get_movie_recommendations(self): 66 | recommendations = self.movie.recommendations(self.test_movie_id) 67 | util.assertAttrs(self, recommendations, util.pagination_attributes) 68 | util.assertListAttrs(self, recommendations, "results", util.movie_attributes + ["genre_ids"]) 69 | 70 | def test_get_movie_release_dates(self): 71 | release_dates = self.movie.release_dates(self.test_movie_id) 72 | util.assertAttrs(self, release_dates, ["id", "results"]) 73 | self.assertEqual(release_dates.id, self.test_movie_id) 74 | util.assertListAttrs(self, release_dates, "results", ["iso_3166_1", "release_dates"]) 75 | 76 | def test_get_movie_reviews(self): 77 | reviews = self.movie.reviews(self.test_movie_id) 78 | util.assertAttrs(self, reviews, util.pagination_attributes) 79 | util.assertListAttrs(self, reviews, "results", util.review_attributes) 80 | 81 | def test_get_movie_similar(self): 82 | similar = self.movie.similar(self.test_movie_id) 83 | util.assertAttrs(self, similar, util.pagination_attributes) 84 | util.assertListAttrs(self, similar, "results", util.movie_attributes) 85 | 86 | def test_get_movie_translations(self): 87 | translations = self.movie.translations(self.test_movie_id) 88 | util.assertAttrs(self, translations, ["id", "translations"]) 89 | self.assertEqual(translations.id, self.test_movie_id) 90 | util.assertListAttrs(self, translations, "translations", util.translation_attributes) 91 | 92 | def test_get_movie_videos(self): 93 | videos = self.movie.videos(self.test_movie_id) 94 | util.assertAttrs(self, videos, ["id", "results"]) 95 | self.assertEqual(videos.id, self.test_movie_id) 96 | util.assertListAttrs(self, videos, "results", util.video_attributes) 97 | 98 | def test_get_movie_providers(self): 99 | providers = self.movie.watch_providers(self.test_movie_id) 100 | util.assertAttrs(self, providers, ["id", "results"]) 101 | self.assertEqual(providers.id, self.test_movie_id) 102 | self.assertGreater(len(providers.results), 0) 103 | 104 | def test_get_movie_latest(self): 105 | latest = self.movie.latest() 106 | util.assertAttrs(self, latest, util.movie_attributes) 107 | 108 | def test_get_movie_now_playing(self): 109 | now_playing = self.movie.now_playing() 110 | util.assertAttrs(self, now_playing, util.pagination_attributes + ["dates"]) 111 | util.assertListAttrs(self, now_playing, "results", util.movie_attributes) 112 | 113 | def test_get_movie_popular(self): 114 | popular = self.movie.popular() 115 | util.assertAttrs(self, popular, util.pagination_attributes) 116 | util.assertListAttrs(self, popular, "results", util.movie_attributes) 117 | 118 | def test_get_movie_top_rated(self): 119 | top_rated = self.movie.top_rated() 120 | util.assertAttrs(self, top_rated, util.pagination_attributes) 121 | util.assertListAttrs(self, top_rated, "results", util.movie_attributes) 122 | 123 | def test_get_movie_upcoming(self): 124 | upcoming = self.movie.upcoming() 125 | util.assertAttrs(self, upcoming, util.pagination_attributes) 126 | util.assertListAttrs(self, upcoming, "results", util.movie_attributes) 127 | -------------------------------------------------------------------------------- /tests/test_network.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Network 7 | 8 | 9 | class NetworkTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.network = Network() 13 | self.test_network_id = 1 14 | 15 | def test_get_network_details(self): 16 | network = self.network.details(self.test_network_id) 17 | util.assertAttrs(self, network, ["headquarters", "homepage", "id", "logo_path", "name", "origin_country"]) 18 | self.assertEqual(network.name, "Fuji TV") 19 | 20 | def test_get_network_alternative_names(self): 21 | alternative_names = self.network.alternative_names(self.test_network_id) 22 | util.assertAttrs(self, alternative_names, ["id", "results"]) 23 | self.assertEqual(alternative_names.id, self.test_network_id) 24 | util.assertListAttrs(self, alternative_names, "results", ["name", "type"]) 25 | 26 | def test_get_network_images(self): 27 | images = self.network.images(self.test_network_id) 28 | util.assertAttrs(self, images, ["id"]) 29 | self.assertEqual(images.id, self.test_network_id) 30 | util.assertListAttrs(self, images, "logos", util.image_attributes + ["file_type"]) -------------------------------------------------------------------------------- /tests/test_person.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Person 7 | 8 | 9 | class PersonTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.person = Person() 13 | self.test_person_id = 2888 14 | 15 | def test_get_person_details(self): 16 | details = self.person.details(self.test_person_id) 17 | util.assertAttrs(self, details, util.all_person_attributes + ["known_for_department"]) 18 | self.assertEqual(details.id, self.test_person_id) 19 | 20 | def asset_changes(self, changes): 21 | util.assertAttrs(self, changes, ["changes"]) 22 | util.assertListAttrs(self, changes, "changes", ["key", "items"]) 23 | 24 | def test_get_person_changes(self): 25 | self.asset_changes(self.person.changes(self.test_person_id, start_date="2021-03-10", end_date="2021-03-15")) 26 | self.asset_changes(self.person.changes(self.test_person_id, start_date="2021-03-10")) 27 | self.asset_changes(self.person.changes(self.test_person_id, end_date="2021-03-15")) 28 | 29 | def assert_credits(self, credits): 30 | util.assertAttrs(self, credits, ["id", "cast", "crew"]) 31 | self.assertEqual(credits.id, self.test_person_id) 32 | 33 | def test_get_person_movie_credits(self): 34 | self.assert_credits(self.person.movie_credits(self.test_person_id)) 35 | 36 | def test_get_person_tv_credits(self): 37 | self.assert_credits(self.person.tv_credits(self.test_person_id)) 38 | 39 | def test_get_person_combined_credits(self): 40 | self.assert_credits(self.person.combined_credits(self.test_person_id)) 41 | 42 | def test_get_person_external_ids(self): 43 | external = self.person.external_ids(self.test_person_id) 44 | util.assertAttrs(self, external, ["id", "freebase_mid", "freebase_id", "imdb_id", "tvrage_id", "facebook_id", "instagram_id", "twitter_id"]) 45 | self.assertEqual(external.id, self.test_person_id) 46 | self.assertEqual(external.imdb_id, "nm0000226") 47 | 48 | def test_get_person_images(self): 49 | images = self.person.images(self.test_person_id) 50 | util.assertAttrs(self, images, ["id"]) 51 | self.assertEqual(images.id, self.test_person_id) 52 | util.assertListAttrs(self, images, "profiles", util.image_attributes + ["iso_639_1"]) 53 | 54 | def test_get_person_tagged_images(self): 55 | images = self.person.tagged_images(self.test_person_id) 56 | util.assertAttrs(self, images, util.pagination_attributes) 57 | util.assertListAttrs(self, images, "results", util.image_attributes + ["iso_639_1"]) 58 | 59 | def test_get_person_translations(self): 60 | translations = self.person.translations(self.test_person_id) 61 | util.assertAttrs(self, translations, ["id", "translations"]) 62 | self.assertEqual(translations.id, self.test_person_id) 63 | util.assertListAttrs(self, translations, "translations", util.translation_attributes) 64 | 65 | def test_get_person_latest(self): 66 | latest = self.person.latest() 67 | util.assertAttrs(self, latest, util.all_person_attributes) 68 | 69 | def test_get_person_popular(self): 70 | popular = self.person.popular() 71 | util.assertAttrs(self, popular, util.pagination_attributes) 72 | self.assertTrue(len(popular.results) > 0) 73 | util.assertAttrs(self, popular.results[0], util.person_attributes + ["known_for", "known_for_department"]) 74 | 75 | -------------------------------------------------------------------------------- /tests/test_provider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Provider 7 | 8 | 9 | class ProviderTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.provider = Provider() 13 | 14 | def test_get_provider_available_regions(self): 15 | provider = self.provider.available_regions() 16 | util.assertListAttrs(self, provider, "results", ["iso_3166_1", "english_name", "native_name"]) 17 | 18 | def test_get_provider_movie_providers(self): 19 | provider = self.provider.movie_providers() 20 | util.assertListAttrs(self, provider, "results", [ 21 | "display_priority", "logo_path", "provider_name", "provider_id" 22 | ]) 23 | 24 | def test_get_provider_tv_providers(self): 25 | provider = self.provider.tv_providers() 26 | util.assertListAttrs(self, provider, "results", [ 27 | "display_priority", "logo_path", "provider_name", "provider_id" 28 | ]) 29 | -------------------------------------------------------------------------------- /tests/test_review.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Review 7 | 8 | 9 | class ReviewTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.review = Review() 13 | self.test_review_id = "5db0d60bcb30840013aba0d4" 14 | 15 | def test_get_review_details(self): 16 | review = self.review.details(self.test_review_id) 17 | util.assertAttrs(self, review, util.review_attributes + ["iso_639_1", "media_id", "media_title", "media_type"]) 18 | self.assertEqual(review.id, self.test_review_id) 19 | self.assertEqual(review.media_id, 111) 20 | -------------------------------------------------------------------------------- /tests/test_search.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Search 7 | 8 | 9 | class SearchTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.search = Search() 13 | 14 | def assert_search(self, search): 15 | util.assertAttrs(self, search, util.pagination_attributes) 16 | self.assertGreater(len(search.results), 0) 17 | self.assertTrue(hasattr(search.results[0], "id")) 18 | 19 | def test_get_search_companies(self): 20 | self.assert_search(self.search.companies("Sony")) 21 | 22 | def test_get_search_collections(self): 23 | self.assert_search(self.search.collections("Matrix")) 24 | 25 | def test_get_search_keywords(self): 26 | self.assert_search(self.search.keywords("alien")) 27 | 28 | def test_get_search_movies(self): 29 | self.assert_search(self.search.movies("Matrix", year=1999)) 30 | 31 | def test_get_search_multi(self): 32 | self.assert_search(self.search.multi("Will")) 33 | 34 | def test_get_search_people(self): 35 | self.assert_search(self.search.people("Will Smith")) 36 | 37 | def test_get_search_tv_shows(self): 38 | self.assert_search(self.search.tv_shows("Breaking Bad")) -------------------------------------------------------------------------------- /tests/test_season.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Season 7 | 8 | 9 | class SeasonTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.season = Season() 13 | self.test_tv_id = 1418 14 | self.test_season_id = 3738 15 | self.test_season = 1 16 | 17 | def test_get_season_details(self): 18 | details = self.season.details(self.test_tv_id, self.test_season) 19 | util.assertAttrs(self, details, [ 20 | "_id", "air_date", "episodes", "name", "overview", "id", "poster_path", "season_number" 21 | ]) 22 | self.assertEqual(details.name, "Season 1") 23 | self.assertEqual(details.id, self.test_season_id) 24 | self.assertEqual(details.season_number, self.test_season) 25 | util.assertListAttrs(self, details, "episodes", util.episode_attributes + ["crew", "guest_stars"]) 26 | 27 | def test_get_season_aggregate_credits(self): 28 | credits = self.season.aggregate_credits(self.test_tv_id, self.test_season) 29 | util.assertListAttrs(self, credits, "cast", util.cast_attributes + ["total_episode_count", "roles"]) 30 | util.assertListAttrs(self, credits, "crew", util.crew_attributes + ["total_episode_count", "jobs"]) 31 | 32 | def test_get_season_changes(self): 33 | changes = self.season.changes(self.test_season_id, start_date="2021-09-01", end_date="2021-09-14") 34 | util.assertListAttrs(self, changes, "changes", ["key", "items"]) 35 | 36 | def test_get_season_credits(self): 37 | credits = self.season.credits(self.test_tv_id, self.test_season) 38 | util.assertAttrs(self, credits, ["id"]) 39 | self.assertEqual(credits.id, self.test_season_id) 40 | util.assertListAttrs(self, credits, "cast", util.cast_attributes + ["character"]) 41 | util.assertListAttrs(self, credits, "crew", util.crew_attributes + ["job"]) 42 | 43 | def test_get_season_external_ids(self): 44 | external = self.season.external_ids(self.test_tv_id, self.test_season) 45 | util.assertAttrs(self, external, ["id", "tvdb_id", "tvrage_id", "freebase_mid", "freebase_id"]) 46 | self.assertEqual(external.id, self.test_season_id) 47 | self.assertEqual(external.tvdb_id, 28047) 48 | 49 | def test_get_season_images(self): 50 | images = self.season.images(self.test_tv_id, self.test_season) 51 | util.assertAttrs(self, images, ["id", "posters"]) 52 | self.assertEqual(images.id, self.test_season_id) 53 | util.assertListAttrs(self, images, "posters", util.image_attributes + ["iso_639_1"]) 54 | 55 | def test_get_season_translations(self): 56 | translations = self.season.translations(self.test_tv_id, self.test_season) 57 | util.assertAttrs(self, translations, ["id", "translations"]) 58 | self.assertEqual(translations.id, self.test_season_id) 59 | util.assertListAttrs(self, translations, "translations", util.translation_attributes) 60 | 61 | def test_get_season_videos(self): 62 | videos = self.season.videos(self.test_tv_id, self.test_season) 63 | util.assertAttrs(self, videos, ["id", "results"]) 64 | self.assertEqual(videos.id, self.test_season_id) 65 | -------------------------------------------------------------------------------- /tests/test_trending.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import Trending 7 | 8 | 9 | class TrendingTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.trending = Trending() 13 | 14 | def test_get_trending_all_day(self): 15 | trending = self.trending.all_day() 16 | self.assertGreater(len(trending), 0) 17 | 18 | def test_get_trending_all_week(self): 19 | trending = self.trending.all_week() 20 | self.assertGreater(len(trending), 0) 21 | 22 | def test_get_trending_movie_day(self): 23 | trending = self.trending.movie_day() 24 | self.assertGreater(len(trending), 0) 25 | 26 | def test_get_trending_movie_week(self): 27 | trending = self.trending.movie_week() 28 | self.assertGreater(len(trending), 0) 29 | 30 | def test_get_trending_tv_day(self): 31 | trending = self.trending.tv_day() 32 | self.assertGreater(len(trending), 0) 33 | 34 | def test_get_trending_tv_week(self): 35 | trending = self.trending.tv_week() 36 | self.assertGreater(len(trending), 0) 37 | 38 | def test_get_trending_person_day(self): 39 | trending = self.trending.person_day() 40 | self.assertGreater(len(trending), 0) 41 | 42 | def test_get_trending_person_week(self): 43 | trending = self.trending.person_week() 44 | self.assertGreater(len(trending), 0) -------------------------------------------------------------------------------- /tests/test_tv.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import unittest 4 | import util 5 | 6 | from tmdbv3api import TV 7 | 8 | 9 | class TvTests(unittest.TestCase): 10 | def setUp(self): 11 | self.tmdb = util.setup() 12 | self.tv = TV() 13 | self.test_tv_id = 1396 14 | self.test2_tv_id = 46638 15 | self.test3_tv_id = 4194 16 | 17 | def test_get_tv_details(self): 18 | details = self.tv.details(self.test_tv_id) 19 | util.assertAttrs(self, details, util.tv_attributes + ["genres"]) 20 | self.assertEqual(details.id, self.test_tv_id) 21 | 22 | def test_get_tv_aggregate_credits(self): 23 | credits = self.tv.aggregate_credits(self.test_tv_id) 24 | util.assertListAttrs(self, credits, "cast", util.cast_attributes + ["total_episode_count", "roles"]) 25 | util.assertListAttrs(self, credits, "crew", util.crew_attributes + ["total_episode_count", "jobs"]) 26 | 27 | def test_get_tv_alternative_titles(self): 28 | alternative_titles = self.tv.alternative_titles(self.test_tv_id) 29 | util.assertAttrs(self, alternative_titles, ["id"]) 30 | self.assertEqual(alternative_titles.id, self.test_tv_id) 31 | util.assertListAttrs(self, alternative_titles, "results", util.alt_titles_attributes) 32 | 33 | def asset_changes(self, changes): 34 | util.assertAttrs(self, changes, ["changes"]) 35 | util.assertListAttrs(self, changes, "changes", ["key", "items"]) 36 | 37 | def test_get_tv_changes(self): 38 | self.asset_changes(self.tv.changes(self.test_tv_id, start_date="2021-09-01", end_date="2021-09-14")) 39 | self.asset_changes(self.tv.changes(self.test_tv_id, start_date="2021-09-01")) 40 | self.asset_changes(self.tv.changes(self.test_tv_id, end_date="2021-09-14")) 41 | 42 | def test_get_tv_content_ratings(self): 43 | content_ratings = self.tv.content_ratings(self.test_tv_id) 44 | util.assertAttrs(self, content_ratings, ["id"]) 45 | self.assertEqual(content_ratings.id, self.test_tv_id) 46 | util.assertListAttrs(self, content_ratings, "results", ["iso_3166_1", "rating"]) 47 | 48 | def test_get_tv_credits(self): 49 | credits = self.tv.credits(self.test_tv_id) 50 | util.assertAttrs(self, credits, ["id"]) 51 | self.assertEqual(credits.id, self.test_tv_id) 52 | util.assertListAttrs(self, credits, "cast", util.cast_attributes + ["character"]) 53 | util.assertListAttrs(self, credits, "crew", util.crew_attributes + ["job"]) 54 | 55 | def test_get_tv_episode_groups(self): 56 | groups = self.tv.episode_groups(self.test3_tv_id) 57 | util.assertAttrs(self, groups, ["id"]) 58 | self.assertEqual(groups.id, self.test3_tv_id) 59 | util.assertListAttrs(self, groups, "results", util.episode_group_attributes) 60 | 61 | def test_get_tv_external_ids(self): 62 | external = self.tv.external_ids(self.test_tv_id) 63 | util.assertAttrs(self, external, [ 64 | "id", "imdb_id", "tvdb_id", "tvrage_id", "freebase_mid", 65 | "freebase_id", "facebook_id", "instagram_id", "twitter_id" 66 | ]) 67 | self.assertEqual(external.id, self.test_tv_id) 68 | self.assertEqual(external.tvdb_id, 81189) 69 | self.assertEqual(external.imdb_id, "tt0903747") 70 | 71 | def test_get_tv_images(self): 72 | images = self.tv.images(self.test_tv_id) 73 | util.assertAttrs(self, images, ["id"]) 74 | self.assertEqual(images.id, self.test_tv_id) 75 | util.assertListAttrs(self, images, "backdrops", util.image_attributes + ["iso_639_1"]) 76 | util.assertListAttrs(self, images, "posters", util.image_attributes + ["iso_639_1"]) 77 | 78 | def test_get_tv_keywords(self): 79 | keywords = self.tv.keywords(self.test_tv_id) 80 | util.assertAttrs(self, keywords, ["id", "results"]) 81 | self.assertEqual(keywords.id, self.test_tv_id) 82 | util.assertListAttrs(self, keywords, "results", ["id", "name"]) 83 | 84 | def test_get_tv_recommendations(self): 85 | recommendations = self.tv.recommendations(self.test_tv_id) 86 | util.assertAttrs(self, recommendations, util.pagination_attributes) 87 | util.assertListAttrs(self, recommendations, "results", util.tv_attributes + ["genre_ids"]) 88 | 89 | def test_get_tv_reviews(self): 90 | reviews = self.tv.reviews(self.test_tv_id) 91 | util.assertAttrs(self, reviews, util.pagination_attributes) 92 | util.assertListAttrs(self, reviews, "results", util.review_attributes) 93 | 94 | def test_get_tv_screened_theatrically(self): 95 | screened_theatrically = self.tv.screened_theatrically(self.test2_tv_id) 96 | util.assertAttrs(self, screened_theatrically, ["id"]) 97 | self.assertEqual(screened_theatrically.id, self.test2_tv_id) 98 | util.assertListAttrs(self, screened_theatrically, "results", ["id", "season_number"]) 99 | 100 | def test_get_tv_similar(self): 101 | similar = self.tv.similar(self.test_tv_id) 102 | util.assertAttrs(self, similar, util.pagination_attributes) 103 | util.assertListAttrs(self, similar, "results", util.tv_attributes) 104 | 105 | def test_get_tv_translations(self): 106 | translations = self.tv.translations(self.test_tv_id) 107 | util.assertAttrs(self, translations, ["id", "translations"]) 108 | self.assertEqual(translations.id, self.test_tv_id) 109 | util.assertListAttrs(self, translations, "translations", util.translation_attributes) 110 | 111 | def test_get_tv_videos(self): 112 | videos = self.tv.videos(self.test_tv_id) 113 | util.assertAttrs(self, videos, ["id", "results"]) 114 | self.assertEqual(videos.id, self.test_tv_id) 115 | util.assertListAttrs(self, videos, "results", util.video_attributes) 116 | 117 | def test_get_tv_providers(self): 118 | providers = self.tv.watch_providers(self.test_tv_id) 119 | util.assertAttrs(self, providers, ["id", "results"]) 120 | self.assertEqual(providers.id, self.test_tv_id) 121 | self.assertGreater(len(providers.results), 0) 122 | 123 | def test_get_tv_latest(self): 124 | latest = self.tv.latest() 125 | util.assertAttrs(self, latest, util.tv_attributes) 126 | 127 | def test_get_tv_airing_today(self): 128 | airing_today = self.tv.airing_today() 129 | util.assertAttrs(self, airing_today, util.pagination_attributes) 130 | util.assertListAttrs(self, airing_today, "results", util.tv_attributes) 131 | 132 | def test_get_tv_on_the_air(self): 133 | on_the_air = self.tv.on_the_air() 134 | util.assertAttrs(self, on_the_air, util.pagination_attributes) 135 | util.assertListAttrs(self, on_the_air, "results", util.tv_attributes) 136 | 137 | def test_get_tv_popular(self): 138 | popular = self.tv.popular() 139 | util.assertAttrs(self, popular, util.pagination_attributes) 140 | util.assertListAttrs(self, popular, "results", util.tv_attributes) 141 | 142 | def test_get_tv_top_rated(self): 143 | top_rated = self.tv.top_rated() 144 | util.assertAttrs(self, top_rated, util.pagination_attributes) 145 | util.assertListAttrs(self, top_rated, "results", util.tv_attributes) 146 | -------------------------------------------------------------------------------- /tests/util.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from tmdbv3api import TMDb 4 | 5 | movie_attributes = [ 6 | "adult", "backdrop_path", "id", "original_language", "original_title", "overview", 7 | "release_date", "poster_path", "popularity", "title", "video", "vote_average", "vote_count" 8 | ] 9 | tv_attributes = [ 10 | "backdrop_path", "id", "original_language", "original_name", "overview", "first_air_date", 11 | "poster_path", "popularity", "name", "origin_country", "vote_average", "vote_count" 12 | ] 13 | episode_attributes = [ 14 | "air_date", "episode_number", "id", "name", "overview", "production_code", 15 | "season_number", "still_path", "vote_average", "vote_count" 16 | ] 17 | person_attributes = ["id", "name", "gender", "popularity", "profile_path", "adult"] 18 | cast_attributes = ["known_for_department", "order", "original_name"] + person_attributes 19 | crew_attributes = ["known_for_department", "original_name", "department"] + person_attributes 20 | all_person_attributes = [ 21 | "birthday", "deathday", "also_known_as", "biography", "place_of_birth", "imdb_id", "homepage" 22 | ] + person_attributes 23 | pagination_attributes = ["page", "total_pages", "total_results", "results"] 24 | image_attributes = ["aspect_ratio", "file_path", "height", "vote_average", "vote_count", "width"] 25 | translation_attributes = ["iso_3166_1", "iso_639_1", "name", "english_name", "data"] 26 | list_attributes = ["description", "favorite_count", "id", "item_count", "iso_639_1", "name", "poster_path"] 27 | alt_titles_attributes = ["iso_3166_1", "title", "type"] 28 | review_attributes = ["author", "author_details", "content", "created_at", "id", "updated_at", "url"] 29 | video_attributes = ["iso_639_1", "iso_3166_1", "name", "key", "published_at", "site", "size", "type", "official", "id"] 30 | episode_group_attributes = ["id", "description", "episode_count", "group_count", "name", "type", "network"] 31 | 32 | def setup(): 33 | tmdb = TMDb() 34 | tmdb.api_key = os.environ["TMDB_API_KEY"] 35 | tmdb.language = "en" 36 | tmdb.debug = True 37 | tmdb.wait_on_rate_limit = True 38 | tmdb.cache = False 39 | return tmdb 40 | 41 | 42 | def assertAttrs(test, items, attributes): 43 | for attribute in attributes: 44 | try: 45 | test.assertTrue(hasattr(items, attribute)) 46 | except AssertionError as e: 47 | e.args = ("(%s) %s" % (attribute, e.args[0]),) 48 | raise 49 | 50 | 51 | def assertListAttrs(test, items, list_attribute, attributes): 52 | try: 53 | if list_attribute: 54 | test.assertTrue(hasattr(items, list_attribute)) 55 | items_list = getattr(items, list_attribute) 56 | else: 57 | items_list = items 58 | test.assertGreater(len(items_list), 0) 59 | except AssertionError as e: 60 | e.args = ("(%s) %s" % (list_attribute, e.args[0]),) 61 | raise 62 | else: 63 | for item in items_list: 64 | assertAttrs(test, item, attributes) -------------------------------------------------------------------------------- /tmdbv3api/__init__.py: -------------------------------------------------------------------------------- 1 | from .objs.account import Account 2 | from .objs.auth import Authentication 3 | from .objs.certification import Certification 4 | from .objs.change import Change 5 | from .objs.collection import Collection 6 | from .objs.company import Company 7 | from .objs.configuration import Configuration 8 | from .objs.credit import Credit 9 | from .objs.discover import Discover 10 | from .objs.episode import Episode 11 | from .objs.find import Find 12 | from .objs.genre import Genre 13 | from .objs.group import Group 14 | from .objs.keyword import Keyword 15 | from .objs.list import List 16 | from .objs.movie import Movie 17 | from .objs.network import Network 18 | from .objs.person import Person 19 | from .objs.provider import Provider 20 | from .objs.review import Review 21 | from .objs.search import Search 22 | from .objs.season import Season 23 | from .objs.trending import Trending 24 | from .objs.tv import TV 25 | from .tmdb import TMDb 26 | -------------------------------------------------------------------------------- /tmdbv3api/as_obj.py: -------------------------------------------------------------------------------- 1 | # encoding: utf-8 2 | import sys 3 | from .exceptions import TMDbException 4 | 5 | 6 | class AsObj: 7 | def __init__(self, json=None, key=None, dict_key=False, dict_key_name=None): 8 | self._json = json if json else {} 9 | self._key = key 10 | self._dict_key = dict_key 11 | self._dict_key_name = dict_key_name 12 | self._obj_list = [] 13 | self._list_only = False 14 | if isinstance(self._json, list): 15 | self._obj_list = [AsObj(o) if isinstance(o, (dict, list)) else o for o in self._json] 16 | self._list_only = True 17 | elif dict_key: 18 | self._obj_list = [ 19 | AsObj({k: v}, key=k, dict_key_name=dict_key_name) if isinstance(v, (dict, list)) else v 20 | for k, v in self._json.items() 21 | ] 22 | self._list_only = True 23 | else: 24 | for key, value in self._json.items(): 25 | if isinstance(value, (dict, list)): 26 | if self._key and key == self._key: 27 | final = AsObj(value, dict_key=isinstance(value, dict), dict_key_name=key) 28 | self._obj_list = final 29 | else: 30 | final = AsObj(value) 31 | else: 32 | final = value 33 | if dict_key_name: 34 | setattr(self, dict_key_name, key) 35 | setattr(self, key, final) 36 | 37 | def _dict(self): 38 | return {k: v for k, v in self.__dict__.items() if not k.startswith("_")} 39 | 40 | def __delitem__(self, key): 41 | return delattr(self, key) 42 | 43 | def __getitem__(self, key): 44 | if isinstance(key, int) and self._obj_list: 45 | return self._obj_list[key] 46 | else: 47 | return getattr(self, key) 48 | 49 | def __iter__(self): 50 | return (o for o in self._obj_list) if self._obj_list else iter(self._dict()) 51 | 52 | def __len__(self): 53 | return len(self._obj_list) if self._obj_list else len(self._dict()) 54 | 55 | def __repr__(self): 56 | return str(self._obj_list) if self._list_only else str(self._dict()) 57 | 58 | def __setitem__(self, key, value): 59 | return setattr(self, key, value) 60 | 61 | def __str__(self): 62 | return str(self._obj_list) if self._list_only else str(self._dict()) 63 | 64 | if sys.version_info >= (3, 8): 65 | def __reversed__(self): 66 | return reversed(self._dict()) 67 | 68 | if sys.version_info >= (3, 9): 69 | def __class_getitem__(self, key): 70 | return self.__dict__.__class_getitem__(key) 71 | 72 | def __ior__(self, value): 73 | return self._dict().__ior__(value) 74 | 75 | def __or__(self, value): 76 | return self._dict().__or__(value) 77 | 78 | def copy(self): 79 | return AsObj(self._json.copy(), key=self._key, dict_key=self._dict_key, dict_key_name=self._dict_key_name) 80 | 81 | def get(self, key, value=None): 82 | return self._dict().get(key, value) 83 | 84 | def items(self): 85 | return self._dict().items() 86 | 87 | def keys(self): 88 | return self._dict().keys() 89 | 90 | def pop(self, key, value=None): 91 | return self.__dict__.pop(key, value) 92 | 93 | def popitem(self): 94 | return self.__dict__.popitem() 95 | 96 | def setdefault(self, key, value=None): 97 | return self.__dict__.setdefault(key, value) 98 | 99 | def update(self, entries): 100 | return self.__dict__.update(entries) 101 | 102 | def values(self): 103 | return self._dict().values() 104 | -------------------------------------------------------------------------------- /tmdbv3api/exceptions.py: -------------------------------------------------------------------------------- 1 | class TMDbException(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /tmdbv3api/objs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AnthonyBloomer/tmdbv3api/8b16a6681f14217ca102a7695dc01ab77ac23af7/tmdbv3api/objs/__init__.py -------------------------------------------------------------------------------- /tmdbv3api/objs/account.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from tmdbv3api.exceptions import TMDbException 4 | from tmdbv3api.tmdb import TMDb 5 | 6 | 7 | class Account(TMDb): 8 | _urls = { 9 | "details": "/account", 10 | "created_lists": "/account/%s/lists", 11 | "favorite_movies": "/account/%s/favorite/movies", 12 | "favorite_tv": "/account/%s/favorite/tv", 13 | "favorite": "/account/%s/favorite", 14 | "rated_movies": "/account/%s/rated/movies", 15 | "rated_tv": "/account/%s/rated/tv", 16 | "rated_episodes": "/account/%s/rated/tv/episodes", 17 | "movie_watchlist": "/account/%s/watchlist/movies", 18 | "tv_watchlist": "/account/%s/watchlist/tv", 19 | "watchlist": "/account/%s/watchlist", 20 | } 21 | 22 | @property 23 | def account_id(self): 24 | if not os.environ.get("TMDB_ACCOUNT_ID"): 25 | os.environ["TMDB_ACCOUNT_ID"] = str(self.details()["id"]) 26 | return os.environ.get("TMDB_ACCOUNT_ID") 27 | 28 | def details(self): 29 | """ 30 | Get your account details. 31 | :return: 32 | """ 33 | return self._request_obj( 34 | self._urls["details"], 35 | params="session_id=%s" % self.session_id 36 | ) 37 | 38 | def created_lists(self, page=1): 39 | """ 40 | Get all of the lists created by an account. Will include private lists if you are the owner. 41 | :param page: int 42 | :return: 43 | """ 44 | return self._request_obj( 45 | self._urls["created_lists"] % self.account_id, 46 | params="session_id=%s&page=%s" % (self.session_id, page), 47 | key="results" 48 | ) 49 | 50 | def _get_list(self, url, asc_sort=True, page=1): 51 | params = "session_id=%s&page=%s" % (self.session_id, page) 52 | if asc_sort is False: 53 | params += "&sort_by=created_at.desc" 54 | return self._request_obj( 55 | self._urls[url] % self.account_id, 56 | params=params, 57 | key="results" 58 | ) 59 | 60 | def favorite_movies(self, asc_sort=True, page=1): 61 | """ 62 | Get the list of your favorite movies. 63 | :param asc_sort: bool 64 | :param page: int 65 | :return: 66 | """ 67 | return self._get_list("favorite_movies", asc_sort=asc_sort, page=page) 68 | 69 | def favorite_tv_shows(self, asc_sort=True, page=1): 70 | """ 71 | Get the list of your favorite TV shows. 72 | :param asc_sort: bool 73 | :param page: int 74 | :return: 75 | """ 76 | return self._get_list("favorite_tv", asc_sort=asc_sort, page=page) 77 | 78 | def mark_as_favorite(self, media_id, media_type, favorite=True): 79 | """ 80 | This method allows you to mark a movie or TV show as a favorite item. 81 | :param media_id: int 82 | :param media_type: str 83 | :param favorite:bool 84 | """ 85 | if media_type not in ["tv", "movie"]: 86 | raise TMDbException("Media Type should be tv or movie.") 87 | self._request_obj( 88 | self._urls["favorite"] % self.account_id, 89 | params="session_id=%s" % self.session_id, 90 | method="POST", 91 | json={ 92 | "media_type": media_type, 93 | "media_id": media_id, 94 | "favorite": favorite, 95 | } 96 | ) 97 | 98 | def unmark_as_favorite(self, media_id, media_type): 99 | """ 100 | This method allows you to unmark a movie or TV show as a favorite item. 101 | :param media_id: int 102 | :param media_type: str 103 | """ 104 | self.mark_as_favorite(media_id, media_type, favorite=False) 105 | 106 | def rated_movies(self, asc_sort=True, page=1): 107 | """ 108 | Get a list of all the movies you have rated. 109 | :param asc_sort: bool 110 | :param page: int 111 | :return: 112 | """ 113 | return self._get_list("rated_movies", asc_sort=asc_sort, page=page) 114 | 115 | def rated_tv_shows(self, asc_sort=True, page=1): 116 | """ 117 | Get a list of all the TV shows you have rated. 118 | :param asc_sort: bool 119 | :param page: int 120 | :return: 121 | """ 122 | return self._get_list("rated_tv", asc_sort=asc_sort, page=page) 123 | 124 | def rated_episodes(self, asc_sort=True, page=1): 125 | """ 126 | Get a list of all the TV episodes you have rated. 127 | :param asc_sort: bool 128 | :param page: int 129 | :return: 130 | """ 131 | return self._get_list("rated_episodes", asc_sort=asc_sort, page=page) 132 | 133 | def movie_watchlist(self, asc_sort=True, page=1): 134 | """ 135 | Get a list of all the movies you have added to your watchlist. 136 | :param asc_sort: bool 137 | :param page: int 138 | :return: 139 | """ 140 | return self._get_list("movie_watchlist", asc_sort=asc_sort, page=page) 141 | 142 | def tv_show_watchlist(self, asc_sort=True, page=1): 143 | """ 144 | Get a list of all the TV shows you have added to your watchlist. 145 | :param asc_sort: bool 146 | :param page: int 147 | :return: 148 | """ 149 | return self._get_list("tv_watchlist", asc_sort=asc_sort, page=page) 150 | 151 | def add_to_watchlist(self, media_id, media_type, watchlist=True): 152 | """ 153 | Add a movie or TV show to your watchlist. 154 | :param media_id: int 155 | :param media_type: str 156 | :param watchlist: bool 157 | """ 158 | if media_type not in ["tv", "movie"]: 159 | raise TMDbException("Media Type should be tv or movie.") 160 | self._request_obj( 161 | self._urls["watchlist"] % self.account_id, 162 | "session_id=%s" % self.session_id, 163 | method="POST", 164 | json={ 165 | "media_type": media_type, 166 | "media_id": media_id, 167 | "watchlist": watchlist, 168 | } 169 | ) 170 | 171 | def remove_from_watchlist(self, media_id, media_type): 172 | """ 173 | Remove a movie or TV show from your watchlist. 174 | :param media_id: int 175 | :param media_type: str 176 | """ 177 | self.add_to_watchlist(media_id, media_type, watchlist=False) 178 | -------------------------------------------------------------------------------- /tmdbv3api/objs/auth.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Authentication(TMDb): 5 | _urls = { 6 | "create_request_token": "/authentication/token/new", 7 | "validate_with_login": "/authentication/token/validate_with_login", 8 | "create_session": "/authentication/session/new", 9 | "delete_session": "/authentication/session", 10 | } 11 | 12 | def __init__(self, username, password): 13 | super().__init__() 14 | self.username = username 15 | self.password = password 16 | self.expires_at = None 17 | self.request_token = self._create_request_token() 18 | self._authorise_request_token_with_login() 19 | self._create_session() 20 | 21 | def _create_request_token(self): 22 | """ 23 | Create a temporary request token that can be used to validate a TMDb user login. 24 | """ 25 | response = self._request_obj(self._urls["create_request_token"]) 26 | self.expires_at = response.expires_at 27 | return response.request_token 28 | 29 | def _create_session(self): 30 | """ 31 | You can use this method to create a fully valid session ID once a user has validated the request token. 32 | """ 33 | response = self._request_obj( 34 | self._urls["create_session"], 35 | method="POST", 36 | json={"request_token": self.request_token} 37 | ) 38 | self.session_id = response.session_id 39 | 40 | def _authorise_request_token_with_login(self): 41 | """ 42 | This method allows an application to validate a request token by entering a username and password. 43 | """ 44 | self._request_obj( 45 | self._urls["validate_with_login"], 46 | method="POST", 47 | json={ 48 | "username": self.username, 49 | "password": self.password, 50 | "request_token": self.request_token, 51 | } 52 | ) 53 | 54 | def delete_session(self): 55 | """ 56 | If you would like to delete (or "logout") from a session, call this method with a valid session ID. 57 | """ 58 | if self.has_session: 59 | self._request_obj( 60 | self._urls["delete_session"], 61 | method="DELETE", 62 | json={"session_id": self.session_id} 63 | ) 64 | self.session_id = "" 65 | -------------------------------------------------------------------------------- /tmdbv3api/objs/certification.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Certification(TMDb): 5 | _urls = { 6 | "movie_list": "/certification/movie/list", 7 | "tv_list": "/certification/tv/list", 8 | } 9 | 10 | def movie_list(self): 11 | """ 12 | Get an up to date list of the officially supported movie certifications on TMDB. 13 | :return: 14 | """ 15 | return self._request_obj(self._urls["movie_list"], key="certifications") 16 | 17 | def tv_list(self): 18 | """ 19 | Get an up to date list of the officially supported TV show certifications on TMDB. 20 | :return: 21 | """ 22 | return self._request_obj(self._urls["tv_list"], key="certifications") 23 | -------------------------------------------------------------------------------- /tmdbv3api/objs/change.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Change(TMDb): 5 | _urls = { 6 | "movie": "/movie/changes", 7 | "tv": "/tv/changes", 8 | "person": "/person/changes" 9 | } 10 | 11 | def _change_list(self, change_type, start_date="", end_date="", page=1): 12 | params = "page=%s" % page 13 | if start_date: 14 | params += "&start_date=%s" % start_date 15 | if end_date: 16 | params += "&end_date=%s" % end_date 17 | return self._request_obj( 18 | self._urls[change_type], 19 | params=params, 20 | key="results" 21 | ) 22 | 23 | def movie_change_list(self, start_date="", end_date="", page=1): 24 | """ 25 | Get the changes for a movie. By default only the last 24 hours are returned. 26 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 27 | :param start_date: str 28 | :param end_date: str 29 | :param page: int 30 | :return: 31 | """ 32 | return self._change_list("movie", start_date=start_date, end_date=end_date, page=page) 33 | 34 | def tv_change_list(self, start_date="", end_date="", page=1): 35 | """ 36 | Get a list of all of the TV show ids that have been changed in the past 24 hours. 37 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 38 | :param start_date: str 39 | :param end_date: str 40 | :param page: int 41 | :return: 42 | """ 43 | return self._change_list("tv", start_date=start_date, end_date=end_date, page=page) 44 | 45 | def person_change_list(self, start_date="", end_date="", page=1): 46 | """ 47 | Get a list of all of the person ids that have been changed in the past 24 hours. 48 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 49 | :param start_date: str 50 | :param end_date: str 51 | :param page: int 52 | :return: 53 | """ 54 | return self._change_list("person", start_date=start_date, end_date=end_date, page=page) 55 | -------------------------------------------------------------------------------- /tmdbv3api/objs/collection.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Collection(TMDb): 5 | _urls = { 6 | "details": "/collection/%s", 7 | "images": "/collection/%s/images", 8 | "translations": "/collection/%s/translations" 9 | } 10 | 11 | def details(self, collection_id): 12 | """ 13 | Get collection details by id. 14 | :param collection_id: int 15 | :return: 16 | """ 17 | return self._request_obj(self._urls["details"] % collection_id, key="parts") 18 | 19 | def images(self, collection_id): 20 | """ 21 | Get the images for a collection by id. 22 | :param collection_id: int 23 | :return: 24 | """ 25 | return self._request_obj(self._urls["images"] % collection_id) 26 | 27 | def translations(self, collection_id): 28 | """ 29 | Get the list translations for a collection by id. 30 | :param collection_id: int 31 | :return: 32 | """ 33 | return self._request_obj(self._urls["translations"] % collection_id, key="translations") 34 | -------------------------------------------------------------------------------- /tmdbv3api/objs/company.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Company(TMDb): 5 | _urls = { 6 | "details": "/company/%s", 7 | "alternative_names": "/company/%s/alternative_names", 8 | "images": "/company/%s/images", 9 | "movies": "/company/%s/movies" 10 | } 11 | 12 | def details(self, company_id): 13 | """ 14 | Get a companies details by id. 15 | :param company_id: int 16 | :return: 17 | """ 18 | return self._request_obj(self._urls["details"] % company_id) 19 | 20 | def alternative_names(self, company_id): 21 | """ 22 | Get the alternative names of a company. 23 | :param company_id: int 24 | :return: 25 | """ 26 | return self._request_obj(self._urls["alternative_names"] % company_id, key="results") 27 | 28 | def images(self, company_id): 29 | """ 30 | Get the alternative names of a company. 31 | :param company_id: int 32 | :return: 33 | """ 34 | return self._request_obj(self._urls["images"] % company_id, key="logos") 35 | 36 | def movies(self, company_id, page=1): 37 | """ 38 | Get the movies of a company by id. 39 | :param company_id: int 40 | :param page: int 41 | :return: 42 | """ 43 | return self._request_obj( 44 | self._urls["movies"] % company_id, 45 | params="page=%s" % page, 46 | key="results" 47 | ) 48 | -------------------------------------------------------------------------------- /tmdbv3api/objs/configuration.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from tmdbv3api.tmdb import TMDb 3 | 4 | 5 | class Configuration(TMDb): 6 | _urls = { 7 | "api_configuration": "/configuration", 8 | "countries": "/configuration/countries", 9 | "jobs": "/configuration/jobs", 10 | "languages": "/configuration/languages", 11 | "primary_translations": "/configuration/primary_translations", 12 | "timezones": "/configuration/timezones" 13 | } 14 | 15 | def info(self): 16 | warnings.warn("info method is deprecated use tmdbv3api.Configuration().api_configuration()", 17 | DeprecationWarning) 18 | return self.api_configuration() 19 | 20 | def api_configuration(self): 21 | """ 22 | Get the system wide configuration info. 23 | """ 24 | return self._request_obj(self._urls["api_configuration"]) 25 | 26 | def countries(self): 27 | """ 28 | Get the list of countries (ISO 3166-1 tags) used throughout TMDb. 29 | """ 30 | return self._request_obj(self._urls["countries"]) 31 | 32 | def jobs(self): 33 | """ 34 | Get a list of the jobs and departments we use on TMDb. 35 | """ 36 | return self._request_obj(self._urls["jobs"]) 37 | 38 | def languages(self): 39 | """ 40 | Get the list of languages (ISO 639-1 tags) used throughout TMDb. 41 | """ 42 | return self._request_obj(self._urls["languages"]) 43 | 44 | def primary_translations(self): 45 | """ 46 | Get a list of the officially supported translations on TMDb. 47 | """ 48 | return self._request_obj(self._urls["primary_translations"]) 49 | 50 | def timezones(self): 51 | """ 52 | Get the list of timezones used throughout TMDb. 53 | """ 54 | return self._request_obj(self._urls["timezones"]) 55 | -------------------------------------------------------------------------------- /tmdbv3api/objs/credit.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Credit(TMDb): 5 | _urls = { 6 | "details": "/credit/%s" 7 | } 8 | 9 | def details(self, credit_id): 10 | """ 11 | Get a movie or TV credit details by id. 12 | :param credit_id: int 13 | :return: 14 | """ 15 | return self._request_obj(self._urls["details"] % credit_id) 16 | -------------------------------------------------------------------------------- /tmdbv3api/objs/discover.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | try: 4 | from urllib import urlencode 5 | except ImportError: 6 | from urllib.parse import urlencode 7 | 8 | 9 | class Discover(TMDb): 10 | _urls = { 11 | "movies": "/discover/movie", 12 | "tv": "/discover/tv" 13 | } 14 | 15 | def discover_movies(self, params): 16 | """ 17 | Discover movies by different types of data like average rating, number of votes, genres and certifications. 18 | :param params: dict 19 | :return: 20 | """ 21 | return self._request_obj(self._urls["movies"], urlencode(params), key="results") 22 | 23 | def discover_tv_shows(self, params): 24 | """ 25 | Discover TV shows by different types of data like average rating, number of votes, genres, 26 | the network they aired on and air dates. 27 | :param params: dict 28 | :return: 29 | """ 30 | return self._request_obj(self._urls["tv"], urlencode(params), key="results") 31 | -------------------------------------------------------------------------------- /tmdbv3api/objs/episode.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Episode(TMDb): 5 | _urls = { 6 | "details": "/tv/%s/season/%s/episode/%s", 7 | "account_states": "/tv/%s/season/%s/episode/%s/account_states", 8 | "changes": "/tv/episode/%s/changes", 9 | "credits": "/tv/%s/season/%s/episode/%s/credits", 10 | "external_ids": "/tv/%s/season/%s/episode/%s/external_ids", 11 | "images": "/tv/%s/season/%s/episode/%s/images", 12 | "translations": "/tv/%s/season/%s/episode/%s/translations", 13 | "rate_tv_episode": "/tv/%s/season/%s/episode/%s/rating", 14 | "delete_rating": "/tv/%s/season/%s/episode/%s/rating", 15 | "videos": "/tv/%s/season/%s/episode/%s/videos", 16 | } 17 | 18 | def details(self, tv_id, season_num, episode_num, append_to_response="trailers,images,casts,translations"): 19 | """ 20 | Get the TV episode details by id. 21 | :param tv_id: int 22 | :param season_num: int 23 | :param episode_num: int 24 | :param append_to_response: str 25 | :return: 26 | """ 27 | return self._request_obj( 28 | self._urls["details"] % (tv_id, season_num, episode_num), 29 | params="append_to_response=%s" % append_to_response 30 | ) 31 | 32 | def account_states(self, tv_id, season_num, episode_num): 33 | """ 34 | Get your rating for a episode. 35 | :param tv_id: int 36 | :param season_num: int 37 | :param episode_num: int 38 | :return: 39 | """ 40 | return self._request_obj( 41 | self._urls["account_states"] % (tv_id, season_num, episode_num), 42 | params="session_id=%s" % self.session_id 43 | ) 44 | 45 | def changes(self, episode_id, start_date=None, end_date=None, page=1): 46 | """ 47 | Get the changes for a TV episode. By default only the last 24 hours are returned. 48 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 49 | :param episode_id: int 50 | :param start_date: str 51 | :param end_date: str 52 | :param page: int 53 | :return: 54 | """ 55 | params = "page=%s" % page 56 | if start_date: 57 | params += "&start_date=%s" % start_date 58 | if end_date: 59 | params += "&end_date=%s" % end_date 60 | return self._request_obj( 61 | self._urls["changes"] % episode_id, 62 | params=params, 63 | key="changes" 64 | ) 65 | 66 | def credits(self, tv_id, season_num, episode_num): 67 | """ 68 | Get the credits for TV season. 69 | :param tv_id: int 70 | :param season_num: int 71 | :param episode_num: int 72 | :return: 73 | """ 74 | return self._request_obj(self._urls["credits"] % (tv_id, season_num, episode_num)) 75 | 76 | def external_ids(self, tv_id, season_num, episode_num): 77 | """ 78 | Get the external ids for a TV episode. 79 | :param tv_id: int 80 | :param season_num: int 81 | :param episode_num: int 82 | :return: 83 | """ 84 | return self._request_obj(self._urls["external_ids"] % (tv_id, season_num, episode_num)) 85 | 86 | def images(self, tv_id, season_num, episode_num, include_image_language=None): 87 | """ 88 | Get the images that belong to a TV episode. 89 | :param tv_id: int 90 | :param season_num: int 91 | :param episode_num: int 92 | :param include_image_language: str 93 | :return: 94 | """ 95 | return self._request_obj( 96 | self._urls["images"] % (tv_id, season_num, episode_num), 97 | params="include_image_language=%s" % include_image_language if include_image_language else "", 98 | key="stills" 99 | ) 100 | 101 | def translations(self, tv_id, season_num, episode_num): 102 | """ 103 | Get the translation data for an episode. 104 | :param tv_id: int 105 | :param season_num: int 106 | :param episode_num: int 107 | :return: 108 | """ 109 | return self._request_obj( 110 | self._urls["translations"] % (tv_id, season_num, episode_num), 111 | key="translations" 112 | ) 113 | 114 | def rate_tv_episode(self, tv_id, season_num, episode_num, rating): 115 | """ 116 | Rate a TV episode. 117 | :param tv_id: int 118 | :param season_num: int 119 | :param episode_num: int 120 | :param rating: float 121 | """ 122 | self._request_obj( 123 | self._urls["rate_tv_episode"] % (tv_id, season_num, episode_num), 124 | params="session_id=%s" % self.session_id, 125 | method="POST", 126 | json={"value": rating} 127 | ) 128 | 129 | def delete_rating(self, tv_id, season_num, episode_num): 130 | """ 131 | Remove your rating for a TV episode. 132 | :param tv_id: int 133 | :param season_num: int 134 | :param episode_num: int 135 | """ 136 | self._request_obj( 137 | self._urls["delete_rating"] % (tv_id, season_num, episode_num), 138 | params="session_id=%s" % self.session_id, 139 | method="DELETE" 140 | ) 141 | 142 | def videos(self, tv_id, season_num, episode_num, include_video_language=None): 143 | """ 144 | Get the videos that have been added to a TV episode. 145 | :param tv_id: int 146 | :param season_num: int 147 | :param episode_num: int 148 | :param include_video_language: str 149 | :return: 150 | """ 151 | params = "" 152 | if include_video_language: 153 | params += "&include_video_language=%s" % include_video_language 154 | return self._request_obj( 155 | self._urls["videos"] % (tv_id, season_num, episode_num), 156 | params=params 157 | ) 158 | -------------------------------------------------------------------------------- /tmdbv3api/objs/find.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Find(TMDb): 5 | _urls = { 6 | "find": "/find/%s" 7 | } 8 | 9 | def find(self, external_id, external_source): 10 | """ 11 | The find method makes it easy to search for objects in our database by an external id. For example, an IMDB ID. 12 | :param external_id: str 13 | :param external_source str 14 | :return: 15 | """ 16 | return self._request_obj( 17 | self._urls["find"] % external_id.replace("/", "%2F"), 18 | params="external_source=" + external_source 19 | ) 20 | 21 | def find_by_imdb_id(self, imdb_id): 22 | """ 23 | The find method makes it easy to search for objects in our database by an IMDB ID. 24 | :param imdb_id: str 25 | :return: 26 | """ 27 | return self.find(imdb_id, "imdb_id") 28 | 29 | def find_by_tvdb_id(self, tvdb_id): 30 | """ 31 | The find method makes it easy to search for objects in our database by a TVDB ID. 32 | :param tvdb_id: str 33 | :return: 34 | """ 35 | return self.find(tvdb_id, "tvdb_id") 36 | 37 | def find_by_freebase_mid(self, freebase_mid): 38 | """ 39 | The find method makes it easy to search for objects in our database by a Freebase MID. 40 | :param freebase_mid: str 41 | :return: 42 | """ 43 | return self.find(freebase_mid, "freebase_mid") 44 | 45 | def find_by_freebase_id(self, freebase_id): 46 | """ 47 | The find method makes it easy to search for objects in our database by a Freebase ID. 48 | :param freebase_id: str 49 | :return: 50 | """ 51 | return self.find(freebase_id, "freebase_id") 52 | 53 | def find_by_tvrage_id(self, tvrage_id): 54 | """ 55 | The find method makes it easy to search for objects in our database by a TVRage ID. 56 | :param tvrage_id: str 57 | :return: 58 | """ 59 | return self.find(tvrage_id, "tvrage_id") 60 | 61 | def find_by_facebook_id(self, facebook_id): 62 | """ 63 | The find method makes it easy to search for objects in our database by a Facebook ID. 64 | :param facebook_id: str 65 | :return: 66 | """ 67 | return self.find(facebook_id, "facebook_id") 68 | 69 | def find_by_instagram_id(self, instagram_id): 70 | """ 71 | The find method makes it easy to search for objects in our database by a Instagram ID. 72 | :param instagram_id: str 73 | :return: 74 | """ 75 | return self.find(instagram_id, "instagram_id") 76 | 77 | def find_by_twitter_id(self, twitter_id): 78 | """ 79 | The find method makes it easy to search for objects in our database by a Twitter ID. 80 | :param twitter_id: str 81 | :return: 82 | """ 83 | return self.find(twitter_id, "twitter_id") 84 | -------------------------------------------------------------------------------- /tmdbv3api/objs/genre.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Genre(TMDb): 5 | _urls = { 6 | "movie_list": "/genre/movie/list", 7 | "tv_list": "/genre/tv/list" 8 | } 9 | 10 | def movie_list(self): 11 | """ 12 | Get the list of official genres for movies. 13 | :return: 14 | """ 15 | return self._request_obj(self._urls["movie_list"], key="genres") 16 | 17 | def tv_list(self): 18 | """ 19 | Get the list of official genres for TV shows. 20 | :return: 21 | """ 22 | return self._request_obj(self._urls["tv_list"], key="genres") 23 | -------------------------------------------------------------------------------- /tmdbv3api/objs/group.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Group(TMDb): 5 | _urls = { 6 | "details": "/tv/episode_group/%s" 7 | } 8 | 9 | def details(self, group_id): 10 | """ 11 | Get the details of a TV episode group. 12 | :param group_id: int 13 | :return: 14 | """ 15 | return self._request_obj(self._urls["details"] % group_id, key="groups") 16 | -------------------------------------------------------------------------------- /tmdbv3api/objs/keyword.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Keyword(TMDb): 5 | _urls = { 6 | "details": "/keyword/%s", 7 | "movies": "/keyword/%s/movies" 8 | } 9 | 10 | def details(self, keyword_id): 11 | """ 12 | Get a keywords details by id. 13 | :param keyword_id: int 14 | :return: 15 | """ 16 | return self._request_obj(self._urls["details"] % keyword_id) 17 | 18 | def movies(self, keyword_id): 19 | """ 20 | Get the movies of a keyword by id. 21 | :param keyword_id: int 22 | :return: 23 | """ 24 | return self._request_obj(self._urls["movies"] % keyword_id, key="results") 25 | -------------------------------------------------------------------------------- /tmdbv3api/objs/list.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class List(TMDb): 5 | _urls = { 6 | "details": "/list/%s", 7 | "check_status": "/list/%s/item_status", 8 | "create": "/list", 9 | "add_movie": "/list/%s/add_item", 10 | "remove_movie": "/list/%s/remove_item", 11 | "clear_list": "/list/%s/clear", 12 | "delete_list": "/list/%s", 13 | } 14 | 15 | def details(self, list_id): 16 | """ 17 | Get list details by id. 18 | :param list_id: int 19 | :return: 20 | """ 21 | return self._request_obj(self._urls["details"] % list_id, key="items") 22 | 23 | def check_item_status(self, list_id, movie_id): 24 | """ 25 | You can use this method to check if a movie has already been added to the list. 26 | :param list_id: int 27 | :param movie_id: int 28 | :return: 29 | """ 30 | return self._request_obj(self._urls["check_status"] % list_id, params="movie_id=%s" % movie_id)["item_present"] 31 | 32 | def create_list(self, name, description): 33 | """ 34 | You can use this method to check if a movie has already been added to the list. 35 | :param name: str 36 | :param description: str 37 | :return: 38 | """ 39 | return self._request_obj( 40 | self._urls["create"], 41 | params="session_id=%s" % self.session_id, 42 | method="POST", 43 | json={ 44 | "name": name, 45 | "description": description, 46 | "language": self.language 47 | } 48 | ).list_id 49 | 50 | def add_movie(self, list_id, movie_id): 51 | """ 52 | Add a movie to a list. 53 | :param list_id: int 54 | :param movie_id: int 55 | """ 56 | self._request_obj( 57 | self._urls["add_movie"] % list_id, 58 | params="session_id=%s" % self.session_id, 59 | method="POST", 60 | json={"media_id": movie_id} 61 | ) 62 | 63 | def remove_movie(self, list_id, movie_id): 64 | """ 65 | Remove a movie from a list. 66 | :param list_id: int 67 | :param movie_id: int 68 | """ 69 | self._request_obj( 70 | self._urls["remove_movie"] % list_id, 71 | params="session_id=%s" % self.session_id, 72 | method="POST", 73 | json={"media_id": movie_id} 74 | ) 75 | 76 | def clear_list(self, list_id): 77 | """ 78 | Clear all of the items from a list. 79 | :param list_id: int 80 | """ 81 | self._request_obj( 82 | self._urls["clear_list"] % list_id, 83 | params="session_id=%s&confirm=true" % self.session_id, 84 | method="POST" 85 | ) 86 | 87 | def delete_list(self, list_id): 88 | """ 89 | Delete a list. 90 | :param list_id: int 91 | """ 92 | self._request_obj( 93 | self._urls["delete_list"] % list_id, 94 | params="session_id=%s" % self.session_id, 95 | method="DELETE" 96 | ) 97 | -------------------------------------------------------------------------------- /tmdbv3api/objs/movie.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from tmdbv3api.tmdb import TMDb 3 | from .find import Find 4 | from .search import Search 5 | 6 | 7 | class Movie(TMDb): 8 | _urls = { 9 | "details": "/movie/%s", 10 | "account_states": "/movie/%s/account_states", 11 | "alternative_titles": "/movie/%s/alternative_titles", 12 | "changes": "/movie/%s/changes", 13 | "credits": "/movie/%s/credits", 14 | "external_ids": "/movie/%s/external_ids", 15 | "images": "/movie/%s/images", 16 | "keywords": "/movie/%s/keywords", 17 | "lists": "/movie/%s/lists", 18 | "recommendations": "/movie/%s/recommendations", 19 | "release_dates": "/movie/%s/release_dates", 20 | "reviews": "/movie/%s/reviews", 21 | "similar": "/movie/%s/similar", 22 | "translations": "/movie/%s/translations", 23 | "videos": "/movie/%s/videos", 24 | "watch_providers": "/movie/%s/watch/providers", 25 | "rate_movie": "/movie/%s/rating", 26 | "delete_rating": "/movie/%s/rating", 27 | "latest": "/movie/latest", 28 | "now_playing": "/movie/now_playing", 29 | "popular": "/movie/popular", 30 | "top_rated": "/movie/top_rated", 31 | "upcoming": "/movie/upcoming", 32 | } 33 | 34 | def details(self, movie_id, append_to_response="videos,trailers,images,casts,translations,keywords,release_dates"): 35 | """ 36 | Get the primary information about a movie. 37 | :param movie_id: int 38 | :param append_to_response: str 39 | :return: 40 | """ 41 | return self._request_obj( 42 | self._urls["details"] % movie_id, 43 | params="append_to_response=%s" % append_to_response 44 | ) 45 | 46 | def account_states(self, movie_id): 47 | """ 48 | Grab the following account states for a session: 49 | Movie rating, If it belongs to your watchlist, or If it belongs to your favourite list. 50 | :param movie_id: int 51 | :return: 52 | """ 53 | return self._request_obj( 54 | self._urls["account_states"] % movie_id, 55 | params="session_id=%s" % self.session_id 56 | ) 57 | 58 | def alternative_titles(self, movie_id, country=None): 59 | """ 60 | Get all of the alternative titles for a movie. 61 | :param movie_id: int 62 | :param country: str 63 | :return: 64 | """ 65 | return self._request_obj( 66 | self._urls["alternative_titles"] % movie_id, 67 | params="country=%s" % country if country else "", 68 | key="titles" 69 | ) 70 | 71 | def changes(self, movie_id, start_date=None, end_date=None, page=1): 72 | """ 73 | Get the changes for a movie. By default only the last 24 hours are returned. 74 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 75 | :param movie_id: int 76 | :param start_date: str 77 | :param end_date: str 78 | :param page: int 79 | :return: 80 | """ 81 | params = "page=%s" % page 82 | if start_date: 83 | params += "&start_date=%s" % start_date 84 | if end_date: 85 | params += "&end_date=%s" % end_date 86 | return self._request_obj( 87 | self._urls["changes"] % movie_id, 88 | params=params, 89 | key="changes" 90 | ) 91 | 92 | def credits(self, movie_id): 93 | """ 94 | Get the cast and crew for a movie. 95 | :param movie_id: int 96 | :return: 97 | """ 98 | return self._request_obj(self._urls["credits"] % movie_id) 99 | 100 | def external_ids(self, movie_id): 101 | """ 102 | Get the external ids for a movie. 103 | :param movie_id: int 104 | :return: 105 | """ 106 | return self._request_obj(self._urls["external_ids"] % movie_id) 107 | 108 | def images(self, movie_id, include_image_language=None): 109 | """ 110 | Get the images that belong to a movie. 111 | Querying images with a language parameter will filter the results. 112 | If you want to include a fallback language (especially useful for backdrops) 113 | you can use the include_image_language parameter. 114 | This should be a comma separated value like so: include_image_language=en,null. 115 | :param movie_id: int 116 | :param include_image_language: str 117 | :return: 118 | """ 119 | return self._request_obj( 120 | self._urls["images"] % movie_id, 121 | params="include_image_language=%s" % include_image_language if include_image_language else "" 122 | ) 123 | 124 | def keywords(self, movie_id): 125 | """ 126 | Get the keywords associated to a movie. 127 | :param movie_id: int 128 | :return: 129 | """ 130 | return self._request_obj( 131 | self._urls["keywords"] % movie_id, 132 | key="keywords" 133 | ) 134 | 135 | def lists(self, movie_id, page=1): 136 | """ 137 | Get a list of lists that this movie belongs to. 138 | :param movie_id: int 139 | :param page: int 140 | :return: 141 | """ 142 | return self._request_obj( 143 | self._urls["lists"] % movie_id, 144 | params="page=%s" % page, 145 | key="results" 146 | ) 147 | 148 | def recommendations(self, movie_id, page=1): 149 | """ 150 | Get a list of recommended movies for a movie. 151 | :param movie_id: int 152 | :param page: int 153 | :return: 154 | """ 155 | return self._request_obj( 156 | self._urls["recommendations"] % movie_id, 157 | params="page=%s" % page, 158 | key="results" 159 | ) 160 | 161 | def release_dates(self, movie_id): 162 | """ 163 | Get the release date along with the certification for a movie. 164 | :param movie_id: int 165 | :return: 166 | """ 167 | return self._request_obj( 168 | self._urls["release_dates"] % movie_id, 169 | key="results" 170 | ) 171 | 172 | def reviews(self, movie_id, page=1): 173 | """ 174 | Get the user reviews for a movie. 175 | :param movie_id: int 176 | :param page: int 177 | :return: 178 | """ 179 | return self._request_obj( 180 | self._urls["reviews"] % movie_id, 181 | params="page=%s" % page, 182 | key="results" 183 | ) 184 | 185 | def similar(self, movie_id, page=1): 186 | """ 187 | Get a list of similar movies. 188 | :param movie_id: int 189 | :param page: int 190 | :return: 191 | """ 192 | return self._request_obj( 193 | self._urls["similar"] % movie_id, 194 | params="page=%s" % page, 195 | key="results" 196 | ) 197 | 198 | def translations(self, movie_id): 199 | """ 200 | Get a list of translations that have been created for a movie. 201 | :param movie_id: int 202 | :return: 203 | """ 204 | return self._request_obj( 205 | self._urls["translations"] % movie_id, 206 | key="translations" 207 | ) 208 | 209 | def videos(self, movie_id, page=1): 210 | """ 211 | Get the videos that have been added to a movie. 212 | :param movie_id: int 213 | :param page: int 214 | :return: 215 | """ 216 | return self._request_obj( 217 | self._urls["videos"] % movie_id, 218 | params="page=%s" % page, 219 | key="results" 220 | ) 221 | 222 | def watch_providers(self, movie_id): 223 | """ 224 | You can query this method to get a list of the availabilities per country by provider. 225 | :param movie_id: int 226 | :return: 227 | """ 228 | return self._request_obj( 229 | self._urls["watch_providers"] % movie_id, 230 | key="results" 231 | ) 232 | 233 | def rate_movie(self, movie_id, rating): 234 | """ 235 | Rate a movie. 236 | :param movie_id: int 237 | :param rating: float 238 | """ 239 | self._request_obj( 240 | self._urls["rate_movie"] % movie_id, 241 | params="session_id=%s" % self.session_id, 242 | method="POST", 243 | json={"value": rating} 244 | ) 245 | 246 | def delete_rating(self, movie_id): 247 | """ 248 | Remove your rating for a movie. 249 | :param movie_id: int 250 | """ 251 | self._request_obj( 252 | self._urls["delete_rating"] % movie_id, 253 | params="session_id=%s" % self.session_id, 254 | method="DELETE" 255 | ) 256 | 257 | def latest(self): 258 | """ 259 | Get the most newly created movie. This is a live response and will continuously change. 260 | :return: 261 | """ 262 | return self._request_obj(self._urls["latest"]) 263 | 264 | def now_playing(self, region=None, page=1): 265 | """ 266 | Get a list of movies in theatres. 267 | :param region: str 268 | :param page: int 269 | :return: 270 | """ 271 | params = "page=%s" % page 272 | if region: 273 | params += "®ion=%s" % region 274 | return self._request_obj( 275 | self._urls["now_playing"], 276 | params=params, 277 | key="results" 278 | ) 279 | 280 | def popular(self, region=None, page=1): 281 | """ 282 | Get a list of the current popular movies on TMDb. This list updates daily. 283 | :param region: str 284 | :param page: int 285 | :return: 286 | """ 287 | params = "page=%s" % page 288 | if region: 289 | params += "®ion=%s" % region 290 | return self._request_obj( 291 | self._urls["popular"], 292 | params=params, 293 | key="results" 294 | ) 295 | 296 | def top_rated(self, region=None, page=1): 297 | """ 298 | Get the top rated movies on TMDb. 299 | :param region: str 300 | :param page: int 301 | :return: 302 | """ 303 | params = "page=%s" % page 304 | if region: 305 | params += "®ion=%s" % region 306 | return self._request_obj( 307 | self._urls["top_rated"], 308 | params=params, 309 | key="results" 310 | ) 311 | 312 | def upcoming(self, region=None, page=1): 313 | """ 314 | Get a list of upcoming movies in theatres. 315 | :param region: str 316 | :param page: int 317 | :return: 318 | """ 319 | params = "page=%s" % page 320 | if region: 321 | params += "®ion=%s" % region 322 | return self._request_obj( 323 | self._urls["upcoming"], 324 | params=params, 325 | key="results" 326 | ) 327 | 328 | def search(self, term, page=1): 329 | """ 330 | Search for movies. 331 | :param term: str 332 | :param page: int 333 | :return: 334 | """ 335 | warnings.warn("search method is deprecated use tmdbv3api.Search().movies(term)", 336 | DeprecationWarning) 337 | return Search().movies(term, page=page) 338 | 339 | def external(self, external_id, external_source): 340 | """ 341 | The find method makes it easy to search for objects in our database by an external id. For example, an IMDB ID. 342 | :param external_id: str 343 | :param external_source str 344 | :return: 345 | """ 346 | warnings.warn("external method is deprecated use tmdbv3api.Find().find(external_id, external_source)", 347 | DeprecationWarning) 348 | return Find().find(external_id, external_source) 349 | -------------------------------------------------------------------------------- /tmdbv3api/objs/network.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Network(TMDb): 5 | _urls = { 6 | "details": "/network/%s", 7 | "alternative_names": "/network/%s/alternative_names", 8 | "images": "/network/%s/images" 9 | } 10 | 11 | def details(self, network_id): 12 | """ 13 | Get a networks details by id. 14 | :param network_id: int 15 | :return: 16 | """ 17 | return self._request_obj(self._urls["details"] % network_id) 18 | 19 | def alternative_names(self, network_id): 20 | """ 21 | Get the alternative names of a network. 22 | :param network_id: int 23 | :return: 24 | """ 25 | return self._request_obj( 26 | self._urls["alternative_names"] % network_id, 27 | key="results" 28 | ) 29 | 30 | def images(self, network_id): 31 | """ 32 | Get the TV network logos by id. 33 | :param network_id: int 34 | :return: 35 | """ 36 | return self._request_obj( 37 | self._urls["images"] % network_id, 38 | key="logos" 39 | ) 40 | -------------------------------------------------------------------------------- /tmdbv3api/objs/person.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from tmdbv3api.tmdb import TMDb 3 | from .search import Search 4 | 5 | 6 | class Person(TMDb): 7 | _urls = { 8 | "details": "/person/%s", 9 | "changes": "/person/%s/changes", 10 | "movie_credits": "/person/%s/movie_credits", 11 | "tv_credits": "/person/%s/tv_credits", 12 | "combined_credits": "/person/%s/combined_credits", 13 | "external_ids": "/person/%s/external_ids", 14 | "images": "/person/%s/images", 15 | "tagged_images": "/person/%s/tagged_images", 16 | "translations": "/person/%s/translations", 17 | "latest": "/person/latest", 18 | "popular": "/person/popular", 19 | "search_people": "/search/person", 20 | } 21 | 22 | def details(self, person_id, append_to_response="videos,images"): 23 | """ 24 | Get the primary person details by id. 25 | :param append_to_response: str 26 | :param person_id: int 27 | :return: 28 | """ 29 | return self._request_obj( 30 | self._urls["details"] % person_id, 31 | params="append_to_response=%s" % append_to_response 32 | ) 33 | 34 | def changes(self, person_id, start_date=None, end_date=None, page=1): 35 | """ 36 | Get the changes for a person. By default only the last 24 hours are returned. 37 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 38 | :param person_id: int 39 | :param start_date: str 40 | :param end_date: str 41 | :param page: int 42 | :return: 43 | """ 44 | params = "page=%s" % page 45 | if start_date: 46 | params += "&start_date=%s" % start_date 47 | if end_date: 48 | params += "&end_date=%s" % end_date 49 | return self._request_obj( 50 | self._urls["changes"] % person_id, 51 | params=params, 52 | key="changes" 53 | ) 54 | 55 | def movie_credits(self, person_id): 56 | """ 57 | Get the movie credits for a person. 58 | :param person_id: int 59 | :return: 60 | """ 61 | return self._request_obj(self._urls["movie_credits"] % person_id) 62 | 63 | def tv_credits(self, person_id): 64 | """ 65 | Get the TV show credits for a person. 66 | :param person_id: int 67 | :return: 68 | """ 69 | return self._request_obj(self._urls["tv_credits"] % person_id) 70 | 71 | def combined_credits(self, person_id): 72 | """ 73 | Get the movie and TV credits together in a single response. 74 | :param person_id: int 75 | :return: 76 | """ 77 | return self._request_obj(self._urls["combined_credits"] % person_id) 78 | 79 | def external_ids(self, person_id): 80 | """ 81 | Get the external ids for a person. We currently support the following external sources. 82 | IMDB ID, Facebook, Freebase MID, Freebase ID, Instagram, TVRage ID, and Twitter 83 | :param person_id: int 84 | :return: 85 | """ 86 | return self._request_obj(self._urls["external_ids"] % person_id) 87 | 88 | def images(self, person_id): 89 | """ 90 | Get the images for a person. 91 | :param person_id: int 92 | :return: 93 | """ 94 | return self._request_obj( 95 | self._urls["images"] % person_id, 96 | key="profiles" 97 | ) 98 | 99 | def tagged_images(self, person_id, page=1): 100 | """ 101 | Get the images that this person has been tagged in. 102 | :param person_id: int 103 | :param page: int 104 | :return: 105 | """ 106 | return self._request_obj( 107 | self._urls["tagged_images"] % person_id, 108 | params="page=%s" % page, 109 | key="results" 110 | ) 111 | 112 | def translations(self, person_id): 113 | """ 114 | Get a list of translations that have been created for a person. 115 | :param person_id: int 116 | :return: 117 | """ 118 | return self._request_obj( 119 | self._urls["translations"] % person_id, 120 | key="translations" 121 | ) 122 | 123 | def latest(self): 124 | """ 125 | Get the most newly created person. This is a live response and will continuously change. 126 | :return: 127 | """ 128 | return self._request_obj(self._urls["latest"]) 129 | 130 | def popular(self, page=1): 131 | """ 132 | Get the list of popular people on TMDb. This list updates daily. 133 | :param page: int 134 | :return: 135 | """ 136 | return self._request_obj( 137 | self._urls["popular"], 138 | params="page=%s" % page, 139 | key="results" 140 | ) 141 | 142 | def search(self, term, page=1): 143 | """ 144 | Search for people. 145 | :param term: string 146 | :param page: int 147 | :return: 148 | """ 149 | warnings.warn("search method is deprecated use tmdbv3api.Search().people(params)", 150 | DeprecationWarning) 151 | return Search().people(term, page=page) 152 | -------------------------------------------------------------------------------- /tmdbv3api/objs/provider.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Provider(TMDb): 5 | _urls = { 6 | "regions": "/watch/providers/regions", # TODO: 7 | "movie": "/watch/providers/movie", # TODO: 8 | "tv": "/watch/providers/tv", # TODO: 9 | } 10 | 11 | def available_regions(self): 12 | """ 13 | Returns a list of all of the countries we have watch provider (OTT/streaming) data for. 14 | :return: 15 | """ 16 | return self._request_obj( 17 | self._urls["regions"], 18 | key="results" 19 | ) 20 | 21 | def movie_providers(self, region=None): 22 | """ 23 | Returns a list of the watch provider (OTT/streaming) data we have available for movies. 24 | :return: 25 | """ 26 | return self._request_obj( 27 | self._urls["movie"], 28 | params="watch_region=%s" % region if region else "", 29 | key="results" 30 | ) 31 | 32 | def tv_providers(self, region=None): 33 | """ 34 | Returns a list of the watch provider (OTT/streaming) data we have available for TV series. 35 | :return: 36 | """ 37 | return self._request_obj( 38 | self._urls["tv"], 39 | params="watch_region=%s" % region if region else "", 40 | key="results" 41 | ) 42 | -------------------------------------------------------------------------------- /tmdbv3api/objs/review.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Review(TMDb): 5 | _urls = { 6 | "details": "/review/%s", 7 | } 8 | 9 | def details(self, review_id): 10 | """ 11 | Get the primary person details by id. 12 | :param review_id: int 13 | :return: 14 | """ 15 | return self._request_obj(self._urls["details"] % review_id) 16 | -------------------------------------------------------------------------------- /tmdbv3api/objs/search.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | try: 4 | from urllib import quote 5 | except ImportError: 6 | from urllib.parse import quote 7 | 8 | 9 | class Search(TMDb): 10 | _urls = { 11 | "companies": "/search/company", 12 | "collections": "/search/collection", 13 | "keywords": "/search/keyword", 14 | "movies": "/search/movie", 15 | "multi": "/search/multi", 16 | "people": "/search/person", 17 | "tv_shows": "/search/tv", 18 | } 19 | 20 | def companies(self, term, page=1): 21 | """ 22 | Search for companies. 23 | :param term: str 24 | :param page: int 25 | :return: 26 | """ 27 | return self._request_obj( 28 | self._urls["companies"], 29 | params="query=%s&page=%s" % (quote(term), page), 30 | key="results" 31 | ) 32 | 33 | def collections(self, term, page=1): 34 | """ 35 | Search for collections. 36 | :param term: str 37 | :param page: int 38 | :return: 39 | """ 40 | return self._request_obj( 41 | self._urls["collections"], 42 | params="query=%s&page=%s" % (quote(term), page), 43 | key="results" 44 | ) 45 | 46 | def keywords(self, term, page=1): 47 | """ 48 | Search for keywords. 49 | :param term: str 50 | :param page: int 51 | :return: 52 | """ 53 | return self._request_obj( 54 | self._urls["keywords"], 55 | params="query=%s&page=%s" % (quote(term), page), 56 | key="results" 57 | ) 58 | 59 | def movies(self, term, adult=None, region=None, year=None, release_year=None, page=1): 60 | """ 61 | Search for movies. 62 | :param term: str 63 | :param adult: bool 64 | :param region: str 65 | :param year: int 66 | :param release_year: int 67 | :param page: int 68 | :return: 69 | """ 70 | params = "query=%s&page=%s" % (quote(term), page) 71 | if adult is not None: 72 | params += "&include_adult=%s" % "true" if adult else "false" 73 | if region is not None: 74 | params += "®ion=%s" % quote(region) 75 | if year is not None: 76 | params += "&year=%s" % year 77 | if release_year is not None: 78 | params += "&primary_release_year=%s" % release_year 79 | return self._request_obj( 80 | self._urls["movies"], 81 | params=params, 82 | key="results" 83 | ) 84 | 85 | def multi(self, term, adult=None, region=None, page=1): 86 | """ 87 | Search multiple models in a single request. 88 | Multi search currently supports searching for movies, tv shows and people in a single request. 89 | :param term: str 90 | :param adult: bool 91 | :param region: str 92 | :param page: int 93 | :return: 94 | """ 95 | params = "query=%s&page=%s" % (quote(term), page) 96 | if adult is not None: 97 | params += "&include_adult=%s" % "true" if adult else "false" 98 | if region is not None: 99 | params += "®ion=%s" % quote(region) 100 | return self._request_obj( 101 | self._urls["multi"], 102 | params=params, 103 | key="results" 104 | ) 105 | 106 | def people(self, term, adult=None, region=None, page=1): 107 | """ 108 | Search for people. 109 | :param term: str 110 | :param adult: bool 111 | :param region: str 112 | :param page: int 113 | :return: 114 | """ 115 | params = "query=%s&page=%s" % (quote(term), page) 116 | if adult is not None: 117 | params += "&include_adult=%s" % "true" if adult else "false" 118 | if region is not None: 119 | params += "®ion=%s" % quote(region) 120 | return self._request_obj( 121 | self._urls["people"], 122 | params=params, 123 | key="results" 124 | ) 125 | 126 | def tv_shows(self, term, adult=None, release_year=None, page=1): 127 | """ 128 | Search for a TV show. 129 | :param term: str 130 | :param adult: bool 131 | :param release_year: int 132 | :param page: int 133 | :return: 134 | """ 135 | params = "query=%s&page=%s" % (quote(term), page) 136 | if adult is not None: 137 | params += "&include_adult=%s" % "true" if adult else "false" 138 | if release_year is not None: 139 | params += "&first_air_date_year=%s" % release_year 140 | return self._request_obj( 141 | self._urls["tv_shows"], 142 | params=params, 143 | key="results" 144 | ) 145 | -------------------------------------------------------------------------------- /tmdbv3api/objs/season.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Season(TMDb): 5 | _urls = { 6 | "details": "/tv/%s/season/%s", 7 | "account_states": "/tv/%s/season/%s/account_states", 8 | "aggregate_credits": "/tv/%s/season/%s/aggregate_credits", 9 | "changes": "/tv/season/%s/changes", 10 | "credits": "/tv/%s/season/%s/credits", 11 | "external_ids": "/tv/%s/season/%s/external_ids", 12 | "images": "/tv/%s/season/%s/images", 13 | "translations": "/tv/%s/season/%s/translations", 14 | "videos": "/tv/%s/season/%s/videos", 15 | } 16 | 17 | def details(self, tv_id, season_num, append_to_response="videos,trailers,images,credits,translations"): 18 | """ 19 | Get the TV season details by id. 20 | :param tv_id: int 21 | :param season_num: int 22 | :param append_to_response: str 23 | :return: 24 | """ 25 | return self._request_obj( 26 | self._urls["details"] % (tv_id, season_num), 27 | params="append_to_response=%s" % append_to_response 28 | ) 29 | 30 | def account_states(self, tv_id, season_num): 31 | """ 32 | Get all of the user ratings for the season's episodes. 33 | :param tv_id: int 34 | :param season_num: int 35 | :return: 36 | """ 37 | return self._request_obj( 38 | self._urls["account_states"] % (tv_id, season_num), 39 | params="session_id=%s" % self.session_id, 40 | key="results" 41 | ) 42 | 43 | def aggregate_credits(self, tv_id, season_num): 44 | """ 45 | Get the aggregate credits for TV season. 46 | This call differs from the main credits call in that it does not only return the season credits, 47 | but rather is a view of all the cast & crew for all of the episodes belonging to a season. 48 | :param tv_id: int 49 | :param season_num: int 50 | :return: 51 | """ 52 | return self._request_obj(self._urls["aggregate_credits"] % (tv_id, season_num)) 53 | 54 | def changes(self, season_id, start_date=None, end_date=None, page=1): 55 | """ 56 | Get the changes for a TV season. By default only the last 24 hours are returned. 57 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 58 | :param season_id: int 59 | :param start_date: str 60 | :param end_date: str 61 | :param page: int 62 | :return: 63 | """ 64 | params = "page=%s" % page 65 | if start_date: 66 | params += "&start_date=%s" % start_date 67 | if end_date: 68 | params += "&end_date=%s" % end_date 69 | return self._request_obj( 70 | self._urls["changes"] % season_id, 71 | params=params, 72 | key="changes" 73 | ) 74 | 75 | def credits(self, tv_id, season_num): 76 | """ 77 | Get the credits for TV season. 78 | :param tv_id: int 79 | :param season_num: int 80 | :return: 81 | """ 82 | return self._request_obj(self._urls["credits"] % (tv_id, season_num)) 83 | 84 | def external_ids(self, tv_id, season_num): 85 | """ 86 | Get the external ids for a TV season. 87 | :param tv_id: int 88 | :param season_num: int 89 | :return: 90 | """ 91 | return self._request_obj(self._urls["external_ids"] % (tv_id, season_num)) 92 | 93 | def images(self, tv_id, season_num, include_image_language=None): 94 | """ 95 | Get the images that belong to a TV season. 96 | :param tv_id: int 97 | :param season_num: int 98 | :param include_image_language: str 99 | :return: 100 | """ 101 | return self._request_obj( 102 | self._urls["images"] % (tv_id, season_num), 103 | params="include_image_language=%s" % include_image_language if include_image_language else "", 104 | key="posters" 105 | ) 106 | 107 | def translations(self, tv_id, season_num): 108 | """ 109 | Get a list of the translations that exist for a TV show. 110 | :param tv_id: int 111 | :param season_num: int 112 | """ 113 | return self._request_obj( 114 | self._urls["translations"] % (tv_id, season_num), 115 | key="translations" 116 | ) 117 | 118 | def videos(self, tv_id, season_num, include_video_language=None, page=1): 119 | """ 120 | Get the videos that have been added to a TV show. 121 | :param tv_id: int 122 | :param season_num: int 123 | :param include_video_language: str 124 | :param page: int 125 | :return: 126 | """ 127 | params = "page=%s" % page 128 | if include_video_language: 129 | params += "&include_video_language=%s" % include_video_language 130 | return self._request_obj( 131 | self._urls["videos"] % (tv_id, season_num), 132 | params=params 133 | ) 134 | -------------------------------------------------------------------------------- /tmdbv3api/objs/trending.py: -------------------------------------------------------------------------------- 1 | from tmdbv3api.tmdb import TMDb 2 | 3 | 4 | class Trending(TMDb): 5 | _urls = {"trending": "/trending/%s/%s"} 6 | 7 | def _trending(self, media_type="all", time_window="day", page=1): 8 | return self._request_obj( 9 | self._urls["trending"] % (media_type, time_window), 10 | params="page=%s" % page 11 | ) 12 | 13 | def all_day(self, page=1): 14 | """ 15 | Get all daily trending 16 | :param page: int 17 | :return: 18 | """ 19 | return self._trending(media_type="all", time_window="day", page=page) 20 | 21 | def all_week(self, page=1): 22 | """ 23 | Get all weekly trending 24 | :param page: int 25 | :return: 26 | """ 27 | return self._trending(media_type="all", time_window="week", page=page) 28 | 29 | def movie_day(self, page=1): 30 | """ 31 | Get movie daily trending 32 | :param page: int 33 | :return: 34 | """ 35 | return self._trending(media_type="movie", time_window="day", page=page) 36 | 37 | def movie_week(self, page=1): 38 | """ 39 | Get movie weekly trending 40 | :param page: int 41 | :return: 42 | """ 43 | return self._trending(media_type="movie", time_window="week", page=page) 44 | 45 | def tv_day(self, page=1): 46 | """ 47 | Get tv daily trending 48 | :param page: int 49 | :return: 50 | """ 51 | return self._trending(media_type="tv", time_window="day", page=page) 52 | 53 | def tv_week(self, page=1): 54 | """ 55 | Get tv weekly trending 56 | :param page: int 57 | :return: 58 | """ 59 | return self._trending(media_type="tv", time_window="week", page=page) 60 | 61 | def person_day(self, page=1): 62 | """ 63 | Get person daily trending 64 | :param page: int 65 | :return: 66 | """ 67 | return self._trending(media_type="person", time_window="day", page=page) 68 | 69 | def person_week(self, page=1): 70 | """ 71 | Get person weekly trending 72 | :param page: int 73 | :return: 74 | """ 75 | return self._trending(media_type="person", time_window="week", page=page) 76 | -------------------------------------------------------------------------------- /tmdbv3api/objs/tv.py: -------------------------------------------------------------------------------- 1 | import warnings 2 | from tmdbv3api.tmdb import TMDb 3 | from .search import Search 4 | 5 | try: 6 | from urllib import quote 7 | except ImportError: 8 | from urllib.parse import quote 9 | 10 | 11 | class TV(TMDb): 12 | _urls = { 13 | "details": "/tv/%s", 14 | "account_states": "/tv/%s/account_states", 15 | "aggregate_credits": "/tv/%s/aggregate_credits", 16 | "alternative_titles": "/tv/%s/alternative_titles", 17 | "changes": "/tv/%s/changes", 18 | "content_ratings": "/tv/%s/content_ratings", 19 | "credits": "/tv/%s/credits", 20 | "episode_groups": "/tv/%s/episode_groups", 21 | "external_ids": "/tv/%s/external_ids", 22 | "images": "/tv/%s/images", 23 | "keywords": "/tv/%s/keywords", 24 | "recommendations": "/tv/%s/recommendations", 25 | "reviews": "/tv/%s/reviews", 26 | "screened_theatrically": "/tv/%s/screened_theatrically", 27 | "similar": "/tv/%s/similar", 28 | "translations": "/tv/%s/translations", 29 | "videos": "/tv/%s/videos", 30 | "watch_providers": "/tv/%s/watch/providers", 31 | "rate_tv_show": "/tv/%s/rating", 32 | "delete_rating": "/tv/%s/rating", 33 | "latest": "/tv/latest", 34 | "airing_today": "/tv/airing_today", 35 | "on_the_air": "/tv/on_the_air", 36 | "popular": "/tv/popular", 37 | "top_rated": "/tv/top_rated", 38 | } 39 | 40 | def details(self, tv_id, append_to_response="videos,trailers,images,credits,translations"): 41 | """ 42 | Get the primary TV show details by id. 43 | :param tv_id: int 44 | :param append_to_response: str 45 | :return: 46 | """ 47 | return self._request_obj( 48 | self._urls["details"] % tv_id, 49 | params="append_to_response=%s" % append_to_response, 50 | ) 51 | 52 | def account_states(self, tv_id): 53 | """ 54 | Grab the following account states for a session: 55 | TV show rating, If it belongs to your watchlist, or If it belongs to your favourite list. 56 | :param tv_id: int 57 | :return: 58 | """ 59 | return self._request_obj( 60 | self._urls["account_states"] % tv_id, 61 | params="session_id=%s" % self.session_id 62 | ) 63 | 64 | def aggregate_credits(self, tv_id): 65 | """ 66 | Get the aggregate credits (cast and crew) that have been added to a TV show. 67 | This call differs from the main credits call in that it does not return the newest season but rather, 68 | is a view of all the entire cast & crew for all episodes belonging to a TV show. 69 | :param tv_id: int 70 | :return: 71 | """ 72 | return self._request_obj(self._urls["aggregate_credits"] % tv_id) 73 | 74 | def alternative_titles(self, tv_id): 75 | """ 76 | Returns all of the alternative titles for a TV show. 77 | :param tv_id: int 78 | :return: 79 | """ 80 | return self._request_obj( 81 | self._urls["alternative_titles"] % tv_id, 82 | key="results" 83 | ) 84 | 85 | def changes(self, tv_id, start_date=None, end_date=None, page=1): 86 | """ 87 | Get the changes for a TV show. By default only the last 24 hours are returned. 88 | You can query up to 14 days in a single query by using the start_date and end_date query parameters. 89 | :param tv_id: int 90 | :param start_date: str 91 | :param end_date: str 92 | :param page: int 93 | """ 94 | params = "page=%s" % page 95 | if start_date: 96 | params += "&start_date=%s" % start_date 97 | if end_date: 98 | params += "&end_date=%s" % end_date 99 | return self._request_obj( 100 | self._urls["changes"] % tv_id, 101 | params=params, 102 | key="changes" 103 | ) 104 | 105 | def content_ratings(self, tv_id): 106 | """ 107 | Get the list of content ratings (certifications) that have been added to a TV show. 108 | :param tv_id: int 109 | :return: 110 | """ 111 | return self._request_obj( 112 | self._urls["content_ratings"] % tv_id, 113 | key="results" 114 | ) 115 | 116 | def credits(self, tv_id): 117 | """ 118 | Get the credits (cast and crew) that have been added to a TV show. 119 | :param tv_id: int 120 | :return: 121 | """ 122 | return self._request_obj(self._urls["credits"] % tv_id) 123 | 124 | def episode_groups(self, tv_id): 125 | """ 126 | Get all of the episode groups that have been created for a TV show. 127 | :param tv_id: int 128 | :return: 129 | """ 130 | return self._request_obj( 131 | self._urls["episode_groups"] % tv_id, 132 | key="results" 133 | ) 134 | 135 | def external_ids(self, tv_id): 136 | """ 137 | Get the external ids for a TV show. 138 | :param tv_id: int 139 | :return: 140 | """ 141 | return self._request_obj(self._urls["external_ids"] % tv_id) 142 | 143 | def images(self, tv_id, include_image_language=None): 144 | """ 145 | Get the images that belong to a TV show. 146 | Querying images with a language parameter will filter the results. 147 | If you want to include a fallback language (especially useful for backdrops) 148 | you can use the include_image_language parameter. 149 | This should be a comma separated value like so: include_image_language=en,null. 150 | :param tv_id: int 151 | :param include_image_language: str 152 | :return: 153 | """ 154 | return self._request_obj( 155 | self._urls["images"] % tv_id, 156 | params="include_image_language=%s" % include_image_language if include_image_language else "" 157 | ) 158 | 159 | def keywords(self, tv_id): 160 | """ 161 | Get the keywords that have been added to a TV show. 162 | :param tv_id: int 163 | :return: 164 | """ 165 | return self._request_obj( 166 | self._urls["keywords"] % tv_id, 167 | key="results" 168 | ) 169 | 170 | def recommendations(self, tv_id, page=1): 171 | """ 172 | Get the list of TV show recommendations for this item. 173 | :param tv_id: int 174 | :param page: int 175 | :return: 176 | """ 177 | return self._request_obj( 178 | self._urls["recommendations"] % tv_id, 179 | params="page=%s" % page, 180 | key="results" 181 | ) 182 | 183 | def reviews(self, tv_id, page=1): 184 | """ 185 | Get the reviews for a TV show. 186 | :param tv_id: int 187 | :param page: int 188 | :return: 189 | """ 190 | return self._request_obj( 191 | self._urls["reviews"] % tv_id, 192 | params="page=%s" % page, 193 | key="results" 194 | ) 195 | 196 | def screened_theatrically(self, tv_id): 197 | """ 198 | Get a list of seasons or episodes that have been screened in a film festival or theatre. 199 | :param tv_id: int 200 | :return: 201 | """ 202 | return self._request_obj( 203 | self._urls["screened_theatrically"] % tv_id, 204 | key="results" 205 | ) 206 | 207 | def similar(self, tv_id, page=1): 208 | """ 209 | Get the primary TV show details by id. 210 | :param tv_id: int 211 | :param page: int 212 | :return: 213 | """ 214 | return self._request_obj( 215 | self._urls["similar"] % tv_id, 216 | params="page=%s" % page, 217 | key="results" 218 | ) 219 | 220 | def translations(self, tv_id): 221 | """ 222 | Get a list of the translations that exist for a TV show. 223 | :param tv_id: int 224 | :return: 225 | """ 226 | return self._request_obj( 227 | self._urls["translations"] % tv_id, 228 | key="translations" 229 | ) 230 | 231 | def videos(self, tv_id, include_video_language=None, page=1): 232 | """ 233 | Get the videos that have been added to a TV show. 234 | :param tv_id: int 235 | :param include_video_language: str 236 | :param page: int 237 | :return: 238 | """ 239 | params = "page=%s" % page 240 | if include_video_language: 241 | params += "&include_video_language=%s" % include_video_language 242 | return self._request_obj( 243 | self._urls["videos"] % tv_id, 244 | params=params 245 | ) 246 | 247 | def watch_providers(self, tv_id): 248 | """ 249 | You can query this method to get a list of the availabilities per country by provider. 250 | :param tv_id: int 251 | :return: 252 | """ 253 | return self._request_obj( 254 | self._urls["watch_providers"] % tv_id, 255 | key="results" 256 | ) 257 | 258 | def rate_tv_show(self, tv_id, rating): 259 | """ 260 | Rate a TV show. 261 | :param tv_id: int 262 | :param rating: float 263 | """ 264 | self._request_obj( 265 | self._urls["rate_tv_show"] % tv_id, 266 | params="session_id=%s" % self.session_id, 267 | method="POST", 268 | json={"value": rating} 269 | ) 270 | 271 | def delete_rating(self, tv_id): 272 | """ 273 | Remove your rating for a TV show. 274 | :param tv_id: int 275 | """ 276 | self._request_obj( 277 | self._urls["delete_rating"] % tv_id, 278 | params="session_id=%s" % self.session_id, 279 | method="DELETE" 280 | ) 281 | 282 | def latest(self): 283 | """ 284 | Get the most newly created TV show. This is a live response and will continuously change. 285 | :return: 286 | """ 287 | return self._request_obj(self._urls["latest"]) 288 | 289 | def airing_today(self, page=1): 290 | """ 291 | Get a list of TV shows that are airing today. 292 | This query is purely day based as we do not currently support airing times. 293 | :param page: int 294 | :return: 295 | """ 296 | return self._request_obj( 297 | self._urls["airing_today"], 298 | params="page=%s" % page, 299 | key="results" 300 | ) 301 | 302 | def on_the_air(self, page=1): 303 | """ 304 | Get a list of shows that are currently on the air. 305 | :param page: 306 | :return: 307 | """ 308 | return self._request_obj( 309 | self._urls["on_the_air"], 310 | params="page=%s" % page, 311 | key="results" 312 | ) 313 | 314 | def popular(self, page=1): 315 | """ 316 | Get a list of the current popular TV shows on TMDb. This list updates daily. 317 | :param page: 318 | :return: 319 | """ 320 | return self._request_obj( 321 | self._urls["popular"], 322 | params="page=%s" % page, 323 | key="results" 324 | ) 325 | 326 | def top_rated(self, page=1): 327 | """ 328 | Get a list of the top rated TV shows on TMDb. 329 | :param page: 330 | :return: 331 | """ 332 | return self._request_obj( 333 | self._urls["top_rated"], 334 | params="page=%s" % page, 335 | key="results" 336 | ) 337 | 338 | def search(self, term, page=1): 339 | """ 340 | Search for a TV show. 341 | :param term: 342 | :param page: 343 | :return: 344 | """ 345 | warnings.warn("search method is deprecated use tmdbv3api.Search().tv_shows(term)", 346 | DeprecationWarning) 347 | return Search().tv_shows(term, page=page) 348 | -------------------------------------------------------------------------------- /tmdbv3api/tmdb.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | import logging 4 | import os 5 | import time 6 | 7 | import requests 8 | import requests.exceptions 9 | 10 | from .as_obj import AsObj 11 | from .exceptions import TMDbException 12 | 13 | try: 14 | from functools import lru_cache 15 | except ImportError: 16 | from backports.functools_lru_cache import lru_cache 17 | 18 | logger = logging.getLogger(__name__) 19 | 20 | 21 | class TMDb(object): 22 | _session = None 23 | TMDB_API_KEY = "TMDB_API_KEY" 24 | TMDB_LANGUAGE = "TMDB_LANGUAGE" 25 | TMDB_SESSION_ID = "TMDB_SESSION_ID" 26 | TMDB_WAIT_ON_RATE_LIMIT = "TMDB_WAIT_ON_RATE_LIMIT" 27 | TMDB_DEBUG_ENABLED = "TMDB_DEBUG_ENABLED" 28 | TMDB_CACHE_ENABLED = "TMDB_CACHE_ENABLED" 29 | TMDB_PROXIES = "TMDB_PROXIES" 30 | REQUEST_CACHE_MAXSIZE = None 31 | 32 | def __init__(self, obj_cached=True, session=None): 33 | if self.__class__._session is None or session is not None: 34 | self.__class__._session = requests.Session() if session is None else session 35 | self._base = "https://api.themoviedb.org/3" 36 | self._remaining = 40 37 | self._reset = None 38 | self.obj_cached = obj_cached 39 | if os.environ.get(self.TMDB_LANGUAGE) is None: 40 | os.environ[self.TMDB_LANGUAGE] = "en-US" 41 | 42 | @property 43 | def page(self): 44 | return os.environ["page"] 45 | 46 | @property 47 | def total_results(self): 48 | return os.environ["total_results"] 49 | 50 | @property 51 | def total_pages(self): 52 | return os.environ["total_pages"] 53 | 54 | @property 55 | def api_key(self): 56 | return os.environ.get(self.TMDB_API_KEY) 57 | 58 | @property 59 | def proxies(self): 60 | proxy = os.environ.get(self.TMDB_PROXIES) 61 | if proxy is not None: 62 | proxy = eval(proxy) 63 | return proxy 64 | 65 | @proxies.setter 66 | def proxies(self, proxies): 67 | if proxies is not None: 68 | os.environ[self.TMDB_PROXIES] = str(proxies) 69 | 70 | @api_key.setter 71 | def api_key(self, api_key): 72 | os.environ[self.TMDB_API_KEY] = str(api_key) 73 | 74 | @property 75 | def language(self): 76 | return os.environ.get(self.TMDB_LANGUAGE) 77 | 78 | @language.setter 79 | def language(self, language): 80 | os.environ[self.TMDB_LANGUAGE] = language 81 | 82 | @property 83 | def has_session(self): 84 | return True if os.environ.get(self.TMDB_SESSION_ID) else False 85 | 86 | @property 87 | def session_id(self): 88 | if not os.environ.get(self.TMDB_SESSION_ID): 89 | raise TMDbException("Must Authenticate to create a session run Authentication(username, password)") 90 | return os.environ.get(self.TMDB_SESSION_ID) 91 | 92 | @session_id.setter 93 | def session_id(self, session_id): 94 | os.environ[self.TMDB_SESSION_ID] = session_id 95 | 96 | @property 97 | def wait_on_rate_limit(self): 98 | if os.environ.get(self.TMDB_WAIT_ON_RATE_LIMIT) == "False": 99 | return False 100 | else: 101 | return True 102 | 103 | @wait_on_rate_limit.setter 104 | def wait_on_rate_limit(self, wait_on_rate_limit): 105 | os.environ[self.TMDB_WAIT_ON_RATE_LIMIT] = str(wait_on_rate_limit) 106 | 107 | @property 108 | def debug(self): 109 | if os.environ.get(self.TMDB_DEBUG_ENABLED) == "True": 110 | return True 111 | else: 112 | return False 113 | 114 | @debug.setter 115 | def debug(self, debug): 116 | os.environ[self.TMDB_DEBUG_ENABLED] = str(debug) 117 | 118 | @property 119 | def cache(self): 120 | if os.environ.get(self.TMDB_CACHE_ENABLED) == "False": 121 | return False 122 | else: 123 | return True 124 | 125 | @cache.setter 126 | def cache(self, cache): 127 | os.environ[self.TMDB_CACHE_ENABLED] = str(cache) 128 | 129 | @staticmethod 130 | @lru_cache(maxsize=REQUEST_CACHE_MAXSIZE) 131 | def cached_request(method, url, data, json, proxies): 132 | return requests.request(method, url, data=data, json=json, proxies=proxies) 133 | 134 | def cache_clear(self): 135 | return self.cached_request.cache_clear() 136 | 137 | def _request_obj(self, action, params="", call_cached=True, method="GET", data=None, json=None, key=None): 138 | if self.api_key is None or self.api_key == "": 139 | raise TMDbException("No API key found.") 140 | 141 | url = "%s%s?api_key=%s&%s&language=%s" % ( 142 | self._base, 143 | action, 144 | self.api_key, 145 | params, 146 | self.language, 147 | ) 148 | 149 | if self.cache and self.obj_cached and call_cached and method != "POST": 150 | req = self.cached_request(method, url, data, json, self.proxies) 151 | else: 152 | req = self.__class__._session.request(method, url, data=data, json=json, proxies=self.proxies) 153 | 154 | headers = req.headers 155 | 156 | if "X-RateLimit-Remaining" in headers: 157 | self._remaining = int(headers["X-RateLimit-Remaining"]) 158 | 159 | if "X-RateLimit-Reset" in headers: 160 | self._reset = int(headers["X-RateLimit-Reset"]) 161 | 162 | if self._remaining < 1: 163 | current_time = int(time.time()) 164 | sleep_time = self._reset - current_time 165 | 166 | if self.wait_on_rate_limit: 167 | logger.warning("Rate limit reached. Sleeping for: %d" % sleep_time) 168 | time.sleep(abs(sleep_time)) 169 | return self._request_obj(action, params, call_cached, method, data, json, key) 170 | else: 171 | raise TMDbException("Rate limit reached. Try again in %d seconds." % sleep_time) 172 | 173 | json = req.json() 174 | 175 | if "page" in json: 176 | os.environ["page"] = str(json["page"]) 177 | 178 | if "total_results" in json: 179 | os.environ["total_results"] = str(json["total_results"]) 180 | 181 | if "total_pages" in json: 182 | os.environ["total_pages"] = str(json["total_pages"]) 183 | 184 | if self.debug: 185 | logger.info(json) 186 | logger.info(self.cached_request.cache_info()) 187 | 188 | if "errors" in json: 189 | raise TMDbException(json["errors"]) 190 | 191 | if "success" in json and json["success"] is False: 192 | raise TMDbException(json["status_message"]) 193 | 194 | return AsObj(json, key=key) 195 | --------------------------------------------------------------------------------