Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
193 commits
Select commit Hold shift + click to select a range
09183fc
PoC: New api client
glensc Jan 13, 2022
6b6a8ec
fixup! PoC: New api client
glensc Jan 13, 2022
25ab87d
Update
glensc Jan 13, 2022
2b7ab97
fixup! Update
glensc Jan 13, 2022
a7b6efa
fixup! fixup! Update
glensc Jan 13, 2022
071ae07
fixup! fixup! fixup! Update
glensc Jan 13, 2022
dd8c18e
fixup! fixup! fixup! fixup! Update
glensc Jan 13, 2022
b3eca0b
fixup! fixup! fixup! fixup! fixup! Update
glensc Jan 13, 2022
f73905e
Add api factory
glensc Jan 13, 2022
8136350
fixup! Add api factory
glensc Jan 13, 2022
7949a0c
Add api test
glensc Jan 13, 2022
e00e3d0
Add decorators module
glensc Jan 13, 2022
cf74de7
Always set base url
glensc Jan 13, 2022
d04c085
fixup! Add decorators module
glensc Jan 13, 2022
2d62830
fixup! fixup! Add decorators module
glensc Jan 13, 2022
6683794
Test tvshow
glensc Jan 13, 2022
51d9792
Integrate new_get
glensc Jan 13, 2022
05e76c6
Test new api
glensc Jan 13, 2022
cbd7e7b
fixup! Integrate new_get
glensc Jan 13, 2022
1facdef
fixup! fixup! Add decorators module
glensc Jan 13, 2022
9a7640d
Use api global
glensc Jan 13, 2022
d54a152
fixup! Test new api
glensc Jan 13, 2022
ee9f76d
fixup! fixup! Integrate new_get
glensc Jan 13, 2022
8496e7b
Undo new get
glensc Jan 13, 2022
2844a96
Use new decorators
glensc Jan 13, 2022
387a4c6
Invoke api() only once
glensc Jan 13, 2022
ce526fa
Export api
glensc Jan 13, 2022
54abe3b
Use api() from core
glensc Jan 13, 2022
7b4070a
Cleanup test
glensc Jan 13, 2022
daac127
more tests
glensc Jan 13, 2022
1f3af81
fixup! Use new decorators
glensc Jan 13, 2022
034570c
Add TokenAuth class for requests
glensc Jan 13, 2022
2185902
Implement token as Request auth plugin
glensc Jan 13, 2022
3db0214
Update api() factory
glensc Jan 13, 2022
fb82bb8
Update test_api
glensc Jan 13, 2022
bff202d
Delete unused TraktApiTokenAuth, TraktApi classes
glensc Jan 13, 2022
c4f4516
Update test to test for something that is mocked as well
glensc Jan 13, 2022
9a9f729
Update mock to use new api client
glensc Jan 13, 2022
b46fa05
Drop old decorators export
glensc Jan 13, 2022
843f91d
Drop Core class
glensc Jan 13, 2022
a6c7381
Drop unused headers
glensc Jan 13, 2022
56477ee
Cleanup
glensc Jan 13, 2022
c440ead
Invert to exit early
glensc Jan 13, 2022
a29d398
Use loop rather massive typing
glensc Jan 13, 2022
fb8297e
Cleanup
glensc Jan 13, 2022
8c498fe
Deep copy response rather whole mock data
glensc Jan 13, 2022
acda749
Revert "Drop unused headers"
glensc Jan 13, 2022
7f470d1
Set default headers (inline them rather?)
glensc Jan 13, 2022
d5b5e80
Set config path for token auth
glensc Jan 13, 2022
e4d7a69
Update factory
glensc Jan 13, 2022
70f5076
No base url needed
glensc Jan 13, 2022
89fc7e0
Remove BASE_URL from TraktApiParameters
glensc Jan 13, 2022
d30aa45
Drop unused Core helpers
glensc Jan 13, 2022
94d36a1
Add TraktApiParameters to core module
glensc Jan 13, 2022
1d03ef7
Use TraktApiParameters from core module
glensc Jan 13, 2022
c2f7c5c
fixup! Add TraktApiParameters to core module
glensc Jan 13, 2022
4510290
Rename to AuthConfig
glensc Jan 13, 2022
bc61310
Rename to AuthConfig
glensc Jan 13, 2022
6fe62e1
Add auth module
glensc Jan 13, 2022
ddfec0d
Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
87ab38a
fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
7be1054
Add trakt/auth/pin_auth.py module
glensc Jan 13, 2022
0d54919
fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
7033e41
Add trakt/auth/device_auth.py module
glensc Jan 13, 2022
0f7a949
Add auth init()
glensc Jan 13, 2022
22952af
fixup! Add auth init()
glensc Jan 13, 2022
8b5ec76
fixup! fixup! Add auth init()
glensc Jan 13, 2022
502d3f4
fixup! Add trakt/auth/device_auth.py module
glensc Jan 13, 2022
85c969a
fixup! fixup! Add trakt/auth/device_auth.py module
glensc Jan 13, 2022
7b176ac
fixup! fixup! fixup! Add trakt/auth/device_auth.py module
glensc Jan 13, 2022
8487437
fixup! fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
4b09d70
fixup! Add trakt/auth/pin_auth.py module
glensc Jan 13, 2022
af52f85
Setup auth module
glensc Jan 13, 2022
a5969e1
fixup! Add auth module
glensc Jan 13, 2022
562ad35
Call DeviceAuth
glensc Jan 13, 2022
6dc9c9e
fixup! fixup! Add auth module
glensc Jan 13, 2022
c07cd4f
fixup! fixup! fixup! Add auth module
glensc Jan 13, 2022
d7b4423
fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
8ef4987
fixup! fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
e446293
fixup! fixup! Add auth module
glensc Jan 13, 2022
03792d7
fixup! Add trakt/auth/pin_auth.py module
glensc Jan 13, 2022
91fa928
fixup! fixup! Add auth module
glensc Jan 13, 2022
a0e618a
fixup! fixup! fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
8dccde5
fixup! fixup! Add auth module
glensc Jan 13, 2022
44e6349
fixup! fixup! Add trakt/auth/device_auth.py module
glensc Jan 13, 2022
c51c8c9
fixup! fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
05c2f12
Add Config class
glensc Jan 13, 2022
1ab597e
fixup! Add Config class
glensc Jan 13, 2022
8e113f0
Add config factory
glensc Jan 13, 2022
004d476
Add _store wrapper
glensc Jan 13, 2022
1766c72
fixup! fixup! fixup! Add trakt/auth/device_auth.py module
glensc Jan 13, 2022
9fda49b
fixup! fixup! fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
a0bc9c8
fixup! fixup! Add trakt/auth/pin_auth.py module
glensc Jan 13, 2022
e0bc0ee
fixup! fixup! Add trakt/auth/pin_auth.py module
glensc Jan 13, 2022
ca55cc4
fixup! fixup! fixup! fixup! fixup! Add trakt/auth/oauth_auth.py module
glensc Jan 13, 2022
5dc7ffb
fixup! Update test to test for something that is mocked as well
glensc Jan 13, 2022
c54661a
Cleanup unused code from Core
glensc Jan 13, 2022
e3963ac
Inline AuthConfig
glensc Jan 13, 2022
d0c62b0
Add exists method to Config
glensc Jan 13, 2022
737509b
Add load method to Config
glensc Jan 13, 2022
b6c1469
fixup! Add load method to Config
glensc Jan 13, 2022
1210437
Use Config in TokenAuth
glensc Jan 13, 2022
5b62b0b
Use Config in TokenAuth
glensc Jan 13, 2022
7442f3f
OAUTH_TOKEN_VALID Is not configurable property but state
glensc Jan 13, 2022
b095215
OAUTH_TOKEN_VALID Is not configurable property but state
glensc Jan 13, 2022
f89ff00
Inline REDIRECT_URI (not configurable)
glensc Jan 13, 2022
61b923d
fixup! Inline REDIRECT_URI (not configurable)
glensc Jan 13, 2022
558b153
Disallow headers configurability
glensc Jan 13, 2022
c6fd8a2
fixup! fixup! Inline REDIRECT_URI (not configurable)
glensc Jan 13, 2022
774ee78
Disallow headers configurability
glensc Jan 13, 2022
6e2fa82
fixup! Disallow headers configurability
glensc Jan 13, 2022
b843dc0
Cosmetics
glensc Jan 13, 2022
6785998
MaxSize=None
glensc Jan 13, 2022
b861379
Update Config to extend AuthConfig
glensc Jan 13, 2022
b78cdc4
Change AuthConfig to dataclass
glensc Jan 13, 2022
5ed8770
Update to use new Config
glensc Jan 13, 2022
14d6964
Update to use new Config
glensc Jan 13, 2022
3f3d7fc
Export AuthConfig
glensc Jan 13, 2022
737fa11
Add get/set to AuthConfig
glensc Jan 13, 2022
ee2e8e4
Update TokenAuth to use properties of Config
glensc Jan 13, 2022
f28c147
Remove dict parent, confuses callable check
glensc Jan 13, 2022
8eed801
More dict fixes
glensc Jan 13, 2022
4109adb
Merge AuthConfig and Config
glensc Jan 13, 2022
039dece
Merge AuthConfig and Config
glensc Jan 13, 2022
67530e9
Merge AuthConfig and Config
glensc Jan 13, 2022
6e27231
Add default param for config.get
glensc Jan 13, 2022
dd3b4ed
Add have_refresh_token helper
glensc Jan 13, 2022
3dde453
Use have_refresh_token
glensc Jan 13, 2022
9adb586
Bulk update config
glensc Jan 13, 2022
8603a8a
Store internal properties
glensc Jan 13, 2022
f1c3ecc
Store internal properties
glensc Jan 13, 2022
2d3cf50
Load config by Config class
glensc Jan 13, 2022
5ee895c
Sort list
glensc Jan 13, 2022
49958ca
Use config class load
glensc Jan 13, 2022
0700f90
Use magic __annotations__
glensc Jan 13, 2022
e123edd
Use magic to save config
glensc Jan 13, 2022
81a0794
Remove REDIRECT_URI from AuthConfig
glensc Jan 13, 2022
354173b
Cosmetics
glensc Jan 13, 2022
84897e7
Simplify
glensc Jan 13, 2022
5d78505
Docstring update
glensc Jan 13, 2022
1919e8b
Cleanup imports
glensc Jan 13, 2022
6e7d126
Global not needed?
glensc Jan 13, 2022
75c89bc
Cleanup imports
glensc Jan 13, 2022
cff1531
Config update from config method
glensc Jan 13, 2022
ae8a953
Fix logger name
glensc Jan 13, 2022
943b379
Drop unused Errors class
glensc Jan 13, 2022
0eef8b1
Export decorators for backward compat
glensc Jan 13, 2022
961c25c
fixup! Export decorators for backward compat
glensc Jan 13, 2022
1308900
Partial update to use AuthConfig for DeviceAuth
glensc Jan 13, 2022
9e165f1
Optional headers support for post (maybe not needed)
glensc Jan 13, 2022
6e60a42
Use HttpClient for get_device_code
glensc Jan 13, 2022
49fc9b3
Extract common token update logic
glensc Jan 13, 2022
c95eeeb
Style fix
glensc Jan 13, 2022
f5e7d2c
Simplified import
glensc Jan 13, 2022
ed9af4c
Variable cosmetic
glensc Jan 13, 2022
1b6e0b3
Use HttpClient in get_device_token
glensc Jan 13, 2022
a417b78
Bulk update config
glensc Jan 13, 2022
6854cb2
use self.config.store
glensc Jan 13, 2022
abb3274
Fix DeviceAuth factory
glensc Jan 13, 2022
b13e654
Use exceptions
glensc Jan 13, 2022
f5046ab
Move mappings to class properties
glensc Jan 13, 2022
8d43972
Update OAuth to work
glensc Jan 14, 2022
e1640e8
Update PinAuth to work
glensc Jan 14, 2022
3701b4a
Remove "store" logic from adapters
glensc Jan 14, 2022
1188a4f
Rename auth classes with Adapter suffix
glensc Jan 14, 2022
16ada2c
fixup! Remove "store" logic from adapters
glensc Jan 14, 2022
0e407d2
Remove client_id, client_secret from Adapter constructor
glensc Jan 14, 2022
9a2074c
fixup! Remove client_id, client_secret from Adapter constructor
glensc Jan 14, 2022
ef08590
fixup! fixup! Remove client_id, client_secret from Adapter constructor
glensc Jan 14, 2022
09220aa
DeviceAuthAdapter has no other arguments
glensc Jan 14, 2022
17e790a
Add APPLICATION_ID to AuthConfig
glensc Jan 14, 2022
1479769
Guard TokenAuth to skip oauth requests
glensc Jan 14, 2022
b5d93cd
fixup! Guard TokenAuth to skip oauth requests
glensc Jan 14, 2022
5c384a6
fixup! fixup! Guard TokenAuth to skip oauth requests
glensc Jan 14, 2022
caf5d0a
Cleanup
glensc Jan 14, 2022
97a8541
Change auth init not to return anything
glensc Jan 14, 2022
5a270d6
fixup! Change auth init not to return anything
glensc Jan 14, 2022
89f25d0
Shift named args
glensc Jan 14, 2022
970b41c
Add BaseAdapter class
glensc Jan 14, 2022
806742e
Move REDIRECT_URI to Base Adapter
glensc Jan 14, 2022
f8bbc17
Add NEEDS_APPLICATION_ID to adapters
glensc Jan 14, 2022
39dc7f8
Update get_client_info to ask app id
glensc Jan 14, 2022
fb0c148
Import global APPLICATION_ID
glensc Jan 14, 2022
7d9410f
Drop todo
glensc Jan 14, 2022
168c5a7
Fix BadRequestException handling. must continue waiting for code input
glensc Jan 14, 2022
4e143b8
Fix success flow
glensc Jan 14, 2022
c139049
Revert "Optional headers support for post (maybe not needed)"
glensc Jan 14, 2022
353623b
Remove duplicate logging
glensc Jan 15, 2022
e53aafa
Unify REQUEST/RESPONSE logging formatting
glensc Jan 15, 2022
18cc0ea
Add BadResponseException exception with code -1
glensc Jan 15, 2022
a60c869
Catch json decode errors for unhandled status codes
glensc Jan 15, 2022
c8865dc
isort trakt/api.py
glensc Jan 15, 2022
e378190
PEP formatting
glensc Jan 15, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 16 additions & 14 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
import json
import os
from copy import deepcopy
from functools import lru_cache

from requests import Session

import trakt
from trakt.api import HttpClient

TESTS_DIR = os.path.dirname(__file__)
MOCK_DATA_DIR = os.path.join(TESTS_DIR, "mock_data")
Expand All @@ -25,31 +29,29 @@
]


class MockCore(trakt.core.Core):
def __init__(self, *args, **kwargs):
super(MockCore, self).__init__(*args, **kwargs)
class MockCore():
def __init__(self):
self.mock_data = {}
for mock_file in MOCK_DATA_FILES:
with open(mock_file, encoding='utf-8') as f:
self.mock_data.update(json.load(f))

def _handle_request(self, method, url, data=None):
uri = url[len(trakt.core.BASE_URL):]
def request(self, method, uri, data=None):
if uri.startswith('/'):
uri = uri[1:]
# use a deepcopy of the mocked data to ensure clean responses on every
# request. this prevents rewrites to JSON responses from persisting
method_responses = deepcopy(self.mock_data).get(uri, {})
return method_responses.get(method.upper())
method_responses = self.mock_data.get(uri, {})
response = method_responses.get(method.upper())
if response is None:
print(f"No mock for {uri}")
return deepcopy(response)


"""Override utility functions from trakt.core to use an underlying MockCore
instance
"""Override request function with MockCore instance
"""
trakt.core.CORE = MockCore()
trakt.core.get = trakt.core.CORE.get
trakt.core.post = trakt.core.CORE.post
trakt.core.delete = trakt.core.CORE.delete
trakt.core.put = trakt.core.CORE.put

trakt.core.api().request = MockCore().request

trakt.core.CLIENT_ID = 'FOO'
trakt.core.CLIENT_SECRET = 'BAR'
16 changes: 16 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
"""trakt.tv functional tests"""
from trakt.api import HttpClient
from trakt.core import api, Alias
from trakt.tv import TVShow


def test_api():
api1 = api()
api2 = api()
assert isinstance(api1, HttpClient)
assert api1 == api2

show = TVShow('Game of Thrones')
assert show.title == 'Game of Thrones'
assert show.certification == 'TV-MA'
183 changes: 183 additions & 0 deletions trakt/api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
# -*- coding: utf-8 -*-
"""Interfaces to all of the People objects offered by the Trakt.tv API"""
import json
import logging
from datetime import datetime, timedelta, timezone
from functools import lru_cache
from json import JSONDecodeError

from requests import Session
from requests.auth import AuthBase

from trakt import errors
from trakt.config import AuthConfig
from trakt.errors import BadResponseException, OAuthException

__author__ = 'Jon Nappi, Elan Ruusamäe'


class HttpClient:
"""Class for abstracting HTTP requests
"""

#: Default request HEADERS
headers = {'Content-Type': 'application/json', 'trakt-api-version': '2'}

def __init__(self, base_url: str, session: Session):
self.base_url = base_url
self.session = session
self.logger = logging.getLogger('trakt.http_client')
self.auth = None

def get(self, url: str):
return self.request('get', url)

def delete(self, url: str):
self.request('delete', url)

def post(self, url: str, data):
return self.request('post', url, data=data)

def put(self, url: str, data):
return self.request('put', url, data=data)

def set_auth(self, auth):
self.auth = auth

def request(self, method, url, data=None):
"""Handle actually talking out to the trakt API, logging out debug
information, raising any relevant `TraktException` Exception types,
and extracting and returning JSON data

:param method: The HTTP method we're executing on. Will be one of
post, put, delete, get
:param url: The fully qualified url to send our request to
:param data: Optional data payload to send to the API
:return: The decoded JSON response from the Trakt API
:raises TraktException: If any non-200 return code is encountered
"""

url = self.base_url + url
self.logger.debug('REQUEST [%s] (%s)', method, url)
if method == 'get': # GETs need to pass data as params, not body
response = self.session.request(method, url, headers=self.headers, auth=self.auth, params=data)
else:
response = self.session.request(method, url, headers=self.headers, auth=self.auth, data=json.dumps(data))
self.logger.debug('RESPONSE [%s] (%s): %s', method, url, str(response))

if response.status_code == 204: # HTTP no content
return None
self.raise_if_needed(response)

return self.decode_response(response)

@staticmethod
def decode_response(response):
try:
return json.loads(response.content.decode('UTF-8', 'ignore'))
except JSONDecodeError as e:
raise BadResponseException(f"Unable to parse JSON: {e}")

def raise_if_needed(self, response):
if response.status_code in self.error_map:
raise self.error_map[response.status_code](response)

@property
@lru_cache(maxsize=None)
def error_map(self):
"""Map HTTP response codes to exception types
"""

# Get all of our exceptions except the base exception
errs = [getattr(errors, att) for att in errors.__all__
if att != 'TraktException']

return {err.http_code: err for err in errs}


class TokenAuth(AuthBase):
"""Attaches Trakt.tv token Authentication to the given Request object."""

# OAuth token validity checked
OAUTH_TOKEN_VALID = None

#: The OAuth2 Redirect URI for your OAuth Application
REDIRECT_URI: str = 'urn:ietf:wg:oauth:2.0:oob'

def __init__(self, client: HttpClient, config: AuthConfig):
super().__init__()
self.config = config
self.client = client
self.logger = logging.getLogger('trakt.api.token_auth')

def __call__(self, r):
# Skip oauth requests
if r.path_url.startswith('/oauth/'):
return r

[client_id, client_token] = self.get_token()

r.headers.update({
'trakt-api-key': client_id,
'Authorization': f'Bearer {client_token}',
})
return r

def get_token(self):
"""Return client_id, client_token pair needed for Trakt.tv authentication
"""

self.config.load()
# Check token validity and refresh token if needed
if not self.OAUTH_TOKEN_VALID and self.config.have_refresh_token():
self.validate_token()

return [
self.config.CLIENT_ID,
self.config.OAUTH_TOKEN,
]

def validate_token(self):
"""Check if current OAuth token has not expired"""

current = datetime.now(tz=timezone.utc)
expires_at = datetime.fromtimestamp(self.config.OAUTH_EXPIRES_AT, tz=timezone.utc)
if expires_at - current > timedelta(days=2):
self.OAUTH_TOKEN_VALID = True
else:
self.refresh_token()

def refresh_token(self):
"""Request Trakt API for a new valid OAuth token using refresh_token"""

self.logger.info("OAuth token has expired, refreshing now...")
data = {
'client_id': self.config.CLIENT_ID,
'client_secret': self.config.CLIENT_SECRET,
'refresh_token': self.config.OAUTH_REFRESH,
'redirect_uri': self.REDIRECT_URI,
'grant_type': 'refresh_token'
}

try:
response = self.client.post('/oauth/token', data)
except OAuthException:
self.logger.debug(
"Rejected - Unable to refresh expired OAuth token, "
"refresh_token is invalid"
)
return

self.config.update(
OAUTH_TOKEN=response.get("access_token"),
OAUTH_REFRESH=response.get("refresh_token"),
OAUTH_EXPIRES_AT=response.get("created_at") + response.get("expires_in"),
)
self.OAUTH_TOKEN_VALID = True

self.logger.info(
"OAuth token successfully refreshed, valid until {}".format(
datetime.fromtimestamp(self.config.OAUTH_EXPIRES_AT, tz=timezone.utc)
)
)
self.config.store()
74 changes: 74 additions & 0 deletions trakt/auth/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
"""Authentication methods"""

__author__ = 'Jon Nappi, Elan Ruusamäe'

from trakt import PIN_AUTH, OAUTH_AUTH, DEVICE_AUTH, api, config as config_factory
from trakt.config import AuthConfig


def pin_auth(*args, config, **kwargs):
from trakt.auth.pin import PinAuthAdapter

return PinAuthAdapter(*args, client=api(), config=config, **kwargs).authenticate()


def oauth_auth(*args, config, **kwargs):
from trakt.auth.oauth import OAuthAdapter

return OAuthAdapter(*args, client=api(), config=config, **kwargs).authenticate()


def device_auth(config):
from trakt.auth.device import DeviceAuthAdapter

return DeviceAuthAdapter(client=api(), config=config).authenticate()


def get_client_info(app_id: bool, config: AuthConfig):
"""Helper function to poll the user for Client ID and Client Secret
strings

:return: A 2-tuple of client_id, client_secret
"""
print('If you do not have a client ID and secret. Please visit the '
'following url to create them.')
print('http://trakt.tv/oauth/applications')
client_id = input('Please enter your client id: ')
client_secret = input('Please enter your client secret: ')
if app_id:
msg = f'Please enter your application ID ({config.APPLICATION_ID}): '
user_input = input(msg)
if user_input:
config.APPLICATION_ID = user_input
return client_id, client_secret


def init_auth(method: str, *args, client_id=None, client_secret=None, store=False, **kwargs):
"""Run the auth function specified by *AUTH_METHOD*

:param store: Boolean flag used to determine if your trakt api auth data
should be stored locally on the system. Default is :const:`False` for
the security conscious
"""

methods = {
PIN_AUTH: pin_auth,
OAUTH_AUTH: oauth_auth,
DEVICE_AUTH: device_auth,
}

config = config_factory()
adapter = methods.get(method, PIN_AUTH)

"""
Update client_id, client_secret from input or ask them interactively
"""
if client_id is None and client_secret is None:
client_id, client_secret = get_client_info(adapter.NEEDS_APPLICATION_ID, config)
config.CLIENT_ID, config.CLIENT_SECRET = client_id, client_secret

adapter(*args, config=config, **kwargs)

if store:
config.store()
6 changes: 6 additions & 0 deletions trakt/auth/base.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
class BaseAdapter:
#: The OAuth2 Redirect URI for your OAuth Application
REDIRECT_URI: str = 'urn:ietf:wg:oauth:2.0:oob'

#: True if the Adapter needs APPLICATION_ID
NEEDS_APPLICATION_ID = False
Loading