| 19 | |
| 20 | |
| 21 | class KaggleWebClient: |
| 22 | |
| 23 | def __init__(self): |
| 24 | url_base_override = os.getenv(_KAGGLE_URL_BASE_ENV_VAR_NAME) |
| 25 | self.url_base = url_base_override or _KAGGLE_DEFAULT_URL_BASE |
| 26 | # Follow the OAuth 2.0 Authorization standard (https://tools.ietf.org/html/rfc6750) |
| 27 | self.jwt_token = os.getenv(_KAGGLE_USER_SECRETS_TOKEN_ENV_VAR_NAME) |
| 28 | if self.jwt_token is None: |
| 29 | raise CredentialError( |
| 30 | 'A JWT Token is required to call Kaggle, ' |
| 31 | f'but none found in environment variable {_KAGGLE_USER_SECRETS_TOKEN_ENV_VAR_NAME}') |
| 32 | self.headers = { |
| 33 | 'Content-type': 'application/json', |
| 34 | 'X-Kaggle-Authorization': f'Bearer {self.jwt_token}', |
| 35 | } |
| 36 | iap_token = os.getenv(_KAGGLE_IAP_TOKEN_ENV_VAR_NAME) |
| 37 | if iap_token: |
| 38 | self.headers['Authorization'] = f'Bearer {iap_token}' |
| 39 | |
| 40 | def make_post_request(self, data: dict, endpoint: str, timeout: int = TIMEOUT_SECS) -> dict: |
| 41 | url = f'{self.url_base}{endpoint}' |
| 42 | request_body = dict(data) |
| 43 | req = urllib.request.Request(url, headers=self.headers, data=bytes( |
| 44 | json.dumps(request_body), encoding="utf-8")) |
| 45 | try: |
| 46 | with urllib.request.urlopen(req, timeout=timeout) as response: |
| 47 | response_json = json.loads(response.read()) |
| 48 | if not response_json.get('wasSuccessful') or 'result' not in response_json: |
| 49 | raise BackendError( |
| 50 | f'Unexpected response from the service. Response: {response_json}.') |
| 51 | return response_json['result'] |
| 52 | except (URLError, socket.timeout) as e: |
| 53 | if isinstance( |
| 54 | e, socket.timeout) or isinstance( |
| 55 | e.reason, socket.timeout): |
| 56 | raise ConnectionError( |
| 57 | 'Timeout error trying to communicate with service. Please ensure internet is on.') from e |
| 58 | raise ConnectionError( |
| 59 | 'Connection error trying to communicate with service.') from e |
| 60 | except HTTPError as e: |
| 61 | if e.code == 401 or e.code == 403: |
| 62 | raise CredentialError( |
| 63 | f'Service responded with error code {e.code}.' |
| 64 | ' Please ensure you have access to the resource.') from e |
| 65 | raise BackendError('Unexpected response from the service.') from e |