diff --git a/platformio/commands/account/client.py b/platformio/clients/account.py similarity index 65% rename from platformio/commands/account/client.py rename to platformio/clients/account.py index e49f30bb..078e2b8a 100644 --- a/platformio/commands/account/client.py +++ b/platformio/clients/account.py @@ -12,47 +12,42 @@ # See the License for the specific language governing permissions and # limitations under the License. -# pylint: disable=unused-argument - import os import time -import requests.adapters -from requests.packages.urllib3.util.retry import Retry # pylint:disable=import-error - from platformio import __accounts_api__, app -from platformio.commands.account import exception -from platformio.exception import InternetIsOffline +from platformio.clients.rest import RESTClient +from platformio.exception import PlatformioException -class AccountClient(object): +class AccountError(PlatformioException): + + MESSAGE = "{0}" + + +class AccountNotAuthorized(AccountError): + + MESSAGE = "You are not authorized! Please log in to PIO Account." + + +class AccountAlreadyAuthorized(AccountError): + + MESSAGE = "You are already authorized with {0} account." + + +class AccountClient(RESTClient): SUMMARY_CACHE_TTL = 60 * 60 * 24 * 7 - def __init__( - self, api_base_url=__accounts_api__, retries=3, - ): - if api_base_url.endswith("/"): - api_base_url = api_base_url[:-1] - self.api_base_url = api_base_url - self._session = requests.Session() - self._session.headers.update({"User-Agent": app.get_user_agent()}) - retry = Retry( - total=retries, - read=retries, - connect=retries, - backoff_factor=2, - method_whitelist=list(Retry.DEFAULT_METHOD_WHITELIST) + ["POST"], - ) - adapter = requests.adapters.HTTPAdapter(max_retries=retry) - self._session.mount(api_base_url, adapter) + def __init__(self): + super(AccountClient, self).__init__(base_url=__accounts_api__) @staticmethod def get_refresh_token(): try: return app.get_state_item("account").get("auth").get("refresh_token") except: # pylint:disable=bare-except - raise exception.AccountNotAuthorized() + raise AccountNotAuthorized() @staticmethod def delete_local_session(): @@ -72,14 +67,12 @@ class AccountClient(object): except: # pylint:disable=bare-except pass else: - raise exception.AccountAlreadyAuthorized( + raise AccountAlreadyAuthorized( app.get_state_item("account", {}).get("email", "") ) result = self.send_request( - "post", - self.api_base_url + "/v1/login", - data={"username": username, "password": password}, + "post", "/v1/login", data={"username": username, "password": password}, ) app.set_state_item("account", result) return result @@ -90,13 +83,13 @@ class AccountClient(object): except: # pylint:disable=bare-except pass else: - raise exception.AccountAlreadyAuthorized( + raise AccountAlreadyAuthorized( app.get_state_item("account", {}).get("email", "") ) result = self.send_request( "post", - self.api_base_url + "/v1/login/code", + "/v1/login/code", data={"client_id": client_id, "code": code, "redirect_uri": redirect_uri}, ) app.set_state_item("account", result) @@ -107,11 +100,9 @@ class AccountClient(object): self.delete_local_session() try: self.send_request( - "post", - self.api_base_url + "/v1/logout", - data={"refresh_token": refresh_token}, + "post", "/v1/logout", data={"refresh_token": refresh_token}, ) - except exception.AccountError: + except AccountError: pass return True @@ -119,7 +110,7 @@ class AccountClient(object): token = self.fetch_authentication_token() self.send_request( "post", - self.api_base_url + "/v1/password", + "/v1/password", headers={"Authorization": "Bearer %s" % token}, data={"old_password": old_password, "new_password": new_password}, ) @@ -133,13 +124,13 @@ class AccountClient(object): except: # pylint:disable=bare-except pass else: - raise exception.AccountAlreadyAuthorized( + raise AccountAlreadyAuthorized( app.get_state_item("account", {}).get("email", "") ) return self.send_request( "post", - self.api_base_url + "/v1/registration", + "/v1/registration", data={ "username": username, "email": email, @@ -153,23 +144,19 @@ class AccountClient(object): token = self.fetch_authentication_token() result = self.send_request( "post", - self.api_base_url + "/v1/token", + "/v1/token", headers={"Authorization": "Bearer %s" % token}, data={"password": password, "regenerate": 1 if regenerate else 0}, ) return result.get("auth_token") def forgot_password(self, username): - return self.send_request( - "post", self.api_base_url + "/v1/forgot", data={"username": username}, - ) + return self.send_request("post", "/v1/forgot", data={"username": username},) def get_profile(self): token = self.fetch_authentication_token() return self.send_request( - "get", - self.api_base_url + "/v1/profile", - headers={"Authorization": "Bearer %s" % token}, + "get", "/v1/profile", headers={"Authorization": "Bearer %s" % token}, ) def update_profile(self, profile, current_password): @@ -178,7 +165,7 @@ class AccountClient(object): self.delete_local_state("summary") response = self.send_request( "put", - self.api_base_url + "/v1/profile", + "/v1/profile", headers={"Authorization": "Bearer %s" % token}, data=profile, ) @@ -187,7 +174,7 @@ class AccountClient(object): def get_account_info(self, offline=False): account = app.get_state_item("account") if not account: - raise exception.AccountNotAuthorized() + raise AccountNotAuthorized() if ( account.get("summary") and account["summary"].get("expire_at", 0) > time.time() @@ -202,9 +189,7 @@ class AccountClient(object): } token = self.fetch_authentication_token() result = self.send_request( - "get", - self.api_base_url + "/v1/summary", - headers={"Authorization": "Bearer %s" % token}, + "get", "/v1/summary", headers={"Authorization": "Bearer %s" % token}, ) account["summary"] = dict( profile=result.get("profile"), @@ -227,36 +212,13 @@ class AccountClient(object): try: result = self.send_request( "post", - self.api_base_url + "/v1/login", + "/v1/login", headers={ "Authorization": "Bearer %s" % auth.get("refresh_token") }, ) app.set_state_item("account", result) return result.get("auth").get("access_token") - except exception.AccountError: + except AccountError: self.delete_local_session() - raise exception.AccountNotAuthorized() - - def send_request(self, method, url, headers=None, data=None): - try: - response = getattr(self._session, method)( - url, headers=headers or {}, data=data or {} - ) - except requests.exceptions.ConnectionError: - raise InternetIsOffline() - return self.raise_error_from_response(response) - - def raise_error_from_response(self, response, expected_codes=(200, 201, 202)): - if response.status_code in expected_codes: - try: - return response.json() - except ValueError: - pass - try: - message = response.json()["message"] - except (KeyError, ValueError): - message = response.text - if "Authorization session has been expired" in message: - self.delete_local_session() - raise exception.AccountError(message) + raise AccountNotAuthorized() diff --git a/platformio/clients/registry.py b/platformio/clients/registry.py index 6e9ea3fa..8c4d41c6 100644 --- a/platformio/clients/registry.py +++ b/platformio/clients/registry.py @@ -13,8 +13,8 @@ # limitations under the License. from platformio import __registry_api__ +from platformio.clients.account import AccountClient from platformio.clients.rest import RESTClient -from platformio.commands.account.client import AccountClient from platformio.package.pack import PackageType diff --git a/platformio/commands/account/command.py b/platformio/commands/account.py similarity index 98% rename from platformio/commands/account/command.py rename to platformio/commands/account.py index 0177d00a..78c5aa9e 100644 --- a/platformio/commands/account/command.py +++ b/platformio/commands/account.py @@ -21,8 +21,7 @@ import re import click from tabulate import tabulate -from platformio.commands.account import exception -from platformio.commands.account.client import AccountClient +from platformio.clients.account import AccountClient, AccountNotAuthorized @click.group("account", short_help="Manage PIO Account") @@ -167,7 +166,7 @@ def account_update(current_password, **kwargs): return None try: client.logout() - except exception.AccountNotAuthorized: + except AccountNotAuthorized: pass if email_changed: return click.secho( diff --git a/platformio/commands/account/__init__.py b/platformio/commands/account/__init__.py deleted file mode 100644 index b0514903..00000000 --- a/platformio/commands/account/__init__.py +++ /dev/null @@ -1,13 +0,0 @@ -# Copyright (c) 2014-present PlatformIO -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. diff --git a/platformio/commands/account/exception.py b/platformio/commands/account/exception.py deleted file mode 100644 index a1a0059e..00000000 --- a/platformio/commands/account/exception.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2014-present PlatformIO -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from platformio.exception import PlatformioException - - -class AccountError(PlatformioException): - - MESSAGE = "{0}" - - -class AccountNotAuthorized(AccountError): - - MESSAGE = "You are not authorized! Please log in to PIO Account." - - -class AccountAlreadyAuthorized(AccountError): - - MESSAGE = "You are already authorized with {0} account." diff --git a/platformio/commands/home/rpc/handlers/account.py b/platformio/commands/home/rpc/handlers/account.py index 911006bc..d28379f8 100644 --- a/platformio/commands/home/rpc/handlers/account.py +++ b/platformio/commands/home/rpc/handlers/account.py @@ -14,7 +14,7 @@ import jsonrpc # pylint: disable=import-error -from platformio.commands.account.client import AccountClient +from platformio.clients.account import AccountClient class AccountRPC(object): diff --git a/platformio/commands/remote/factory/client.py b/platformio/commands/remote/factory/client.py index 26abe080..2b47ab01 100644 --- a/platformio/commands/remote/factory/client.py +++ b/platformio/commands/remote/factory/client.py @@ -17,7 +17,7 @@ from twisted.internet import defer, protocol, reactor # pylint: disable=import- from twisted.spread import pb # pylint: disable=import-error from platformio.app import get_host_id -from platformio.commands.account.client import AccountClient +from platformio.clients.account import AccountClient class RemoteClientFactory(pb.PBClientFactory, protocol.ReconnectingClientFactory): diff --git a/tests/commands/test_account.py b/tests/commands/test_account.py index ef7ffbad..5b160f0c 100644 --- a/tests/commands/test_account.py +++ b/tests/commands/test_account.py @@ -18,7 +18,7 @@ import time import pytest -from platformio.commands.account.command import cli as cmd_account +from platformio.commands.account import cli as cmd_account pytestmark = pytest.mark.skipif( not (