Skip to content

Commit

Permalink
fix: Fix linting for Python3 and fix all lint issues
Browse files Browse the repository at this point in the history
  • Loading branch information
Mike Kistler committed Oct 29, 2019
1 parent 57e1aa2 commit 14f2999
Show file tree
Hide file tree
Showing 27 changed files with 297 additions and 144 deletions.
16 changes: 14 additions & 2 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -1,5 +1,17 @@
# lint Python modules using external checkers.
[MASTER]
ignore=SVN
disable=R0903,R0912,R0913,R0914,R0915,W0141,C0111,C0103,W0603,W0703,R0911,C0301,C0302,R0902,R0904,W0142,W0212,E1101,E1103,R0201,W0201,W0122,W0232,RP0001,RP0003,RP0101,RP0002,RP0401,RP0701,RP0801,F0401,E0611,R0801,I0011,F0401,E0611,E1004,C0111,I0011,I0012,W0704,W0142,W0212,W0232,W0613,W0702,R0201,W0614,R0914,R0912,R0915,R0913,R0904,R0801,C0301,C0411,R0204,W0622,E1121,inconsistent-return-statements,missing-docstring

disable=
bare-except,
duplicate-code,
missing-module-docstring,
too-many-arguments,
unnecessary-pass

[TYPECHECK]
ignored-classes= responses

[FORMAT]

# Maximum number of characters on a single line.
max-line-length=120
5 changes: 4 additions & 1 deletion ibm_cloud_sdk_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@
classes:
BaseService: Abstract class for common functionality between each service.
DetailedResponse: The object returned from successful service operations.
IAMTokenManager: Requests and refreshes IAM tokens using an apikey, and optionally a client_id and client_secret pair.
IAMTokenManager: Requests and refreshes IAM tokens using an apikey, and optionally a client_id and client_secret.
JWTTokenManager: Abstract class for common functionality between each JWT token manager.
CP4DTokenManager: Requests and refreshes CP4D tokens given a username and password.
ApiException: Custom exception class for errors returned from service operations.
functions:
datetime_to_string: Serializes a datetime to a string.
string_to_datetime: De-serializes a string to a datetime.
convert_model: Convert a model object into an equivalent dict.
convert_list: Convert a list of strings into comma-separated string.
read_external_sources: Get config object from external sources.
get_authenticator_from_environment: Get authenticator from external sources.
"""
Expand All @@ -36,4 +38,5 @@
from .cp4d_token_manager import CP4DTokenManager
from .api_exception import ApiException
from .utils import datetime_to_string, string_to_datetime, read_external_sources
from .utils import convert_model, convert_list
from .get_authenticator import get_authenticator_from_environment
5 changes: 3 additions & 2 deletions ibm_cloud_sdk_core/api_exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@
# 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 requests import Response
from typing import Optional
from requests import Response


class ApiException(Exception):
Expand Down Expand Up @@ -49,7 +49,8 @@ def __str__(self):
msg += ' , X-global-transaction-id: ' + str(self.global_transaction_id)
return msg

def _get_error_message(self, response: Response):
@staticmethod
def _get_error_message(response: Response):
error_message = 'Unknown error'
try:
error_json = response.json()
Expand Down
5 changes: 3 additions & 2 deletions ibm_cloud_sdk_core/authenticators/basic_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from .authenticator import Authenticator
from ..utils import has_bad_first_or_last_char
import base64
from requests import Request

from .authenticator import Authenticator
from ..utils import has_bad_first_or_last_char


class BasicAuthenticator(Authenticator):
"""The BasicAuthenticator is used to add basic authentication information to requests.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from .authenticator import Authenticator
from requests import Request

from .authenticator import Authenticator

class BearerTokenAuthenticator(Authenticator):
"""The BearerTokenAuthenticator will add a user-supplied bearer token
to requests.
Expand Down
6 changes: 4 additions & 2 deletions ibm_cloud_sdk_core/authenticators/cp4d_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Dict, Optional

from requests import Request

from .authenticator import Authenticator
from ..cp4d_token_manager import CP4DTokenManager
from ..utils import has_bad_first_or_last_char
from requests import Request
from typing import Dict, Optional


class CloudPakForDataAuthenticator(Authenticator):
Expand Down
7 changes: 4 additions & 3 deletions ibm_cloud_sdk_core/authenticators/iam_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Dict, Optional

from requests import Request

from .authenticator import Authenticator
from ..iam_token_manager import IAMTokenManager
from ..utils import has_bad_first_or_last_char
from requests import Request
from typing import Dict, Optional


class IAMAuthenticator(Authenticator):
"""The IAMAuthenticator utilizes an apikey, or client_id and client_secret pair to
Expand Down
72 changes: 46 additions & 26 deletions ibm_cloud_sdk_core/base_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,27 +14,28 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from os.path import basename
import logging
from http.cookiejar import CookieJar
import json as json_import
from os.path import basename
import platform
import requests
from requests.structures import CaseInsensitiveDict
import sys
from typing import Dict, List, Optional, Tuple, Union

import requests
from requests.structures import CaseInsensitiveDict
from ibm_cloud_sdk_core.authenticators import Authenticator
from .version import __version__
from .utils import has_bad_first_or_last_char, remove_null_values, cleanup_values, read_external_sources
from .detailed_response import DetailedResponse
from .api_exception import ApiException
from ibm_cloud_sdk_core.authenticators import Authenticator
from .jwt_token_manager import JWTTokenManager
from http.cookiejar import CookieJar
import logging

# Uncomment this to enable http debugging
# import http.client as http_client
# http_client.HTTPConnection.debuglevel = 1

class BaseService(object):
class BaseService:
"""Common functionality shared by generated service classes.
The base service authenticates requests via its authenticator, stores cookies, and
Expand All @@ -53,15 +54,15 @@ class BaseService(object):
the server's SSL certificate should be disabled or not.
default_headers (dict): A dictionary of headers to be sent with every HTTP request to the service endpoint.
jar (http.cookiejar.CookieJar): Stores cookies received from the service.
http_config (dict): The dictionary can contain values that control the timeout, proxies, and etc of HTTP requests.
http_config (dict): A dictionary containing values that control the timeout, proxies, and etc of HTTP requests.
Raises:
ValueError: If Authenticator is not provided or invalid type.
"""
SDK_NAME = 'ibm-python-sdk-core'
ERROR_MSG_DISABLE_SSL = 'The connection failed because the SSL certificate is not valid. To use a self-signed certificate, '\
'disable verification of the server\'s SSL certificate by invoking the set_disable_ssl_verification(True) '\
'on your service instance and/ or use the disable_ssl_verification option of the authenticator.'
ERROR_MSG_DISABLE_SSL = 'The connection failed because the SSL certificate is not valid. To use a self-signed '\
'certificate, disable verification of the server\'s SSL certificate by invoking the '\
'set_disable_ssl_verification(True) on your service instance and/ or use the '\
'disable_ssl_verification option of the authenticator.'

def __init__(self,
service_url: str = None,
Expand All @@ -80,7 +81,8 @@ def __init__(self,
raise ValueError(
'authenticator should be of type Authenticator')

def _get_system_info(self):
@staticmethod
def _get_system_info():
return '{0} {1} {2}'.format(
platform.system(), # OS
platform.release(), # OS version
Expand Down Expand Up @@ -132,7 +134,8 @@ def set_http_config(self, http_config: dict):
"""
if isinstance(http_config, dict):
self.http_config = http_config
if self.authenticator and hasattr(self.authenticator, 'token_manager') and isinstance(self.authenticator.token_manager, JWTTokenManager):
if (self.authenticator and hasattr(self.authenticator, 'token_manager') and
isinstance(self.authenticator.token_manager, JWTTokenManager)):
self.authenticator.token_manager.http_config = http_config
else:
raise TypeError("http_config parameter must be a dictionary")
Expand Down Expand Up @@ -217,13 +220,13 @@ def send(self, request: requests.Request, **kwargs) -> DetailedResponse:
result = response
return DetailedResponse(result, response.headers,
response.status_code)
else:
error_message = None
if response.status_code == 401:
error_message = 'Unauthorized: Access is denied due to ' \
'invalid credentials'
raise ApiException(
response.status_code, error_message, http_response=response)

error_message = None
if response.status_code == 401:
error_message = 'Unauthorized: Access is denied due to ' \
'invalid credentials'
raise ApiException(
response.status_code, error_message, http_response=response)
except requests.exceptions.SSLError:
logging.exception(self.ERROR_MSG_DISABLE_SSL)
raise
Expand Down Expand Up @@ -265,6 +268,7 @@ def prepare_request(self,
Returns:
Prepared request dictionary.
"""
# pylint: disable=unused-argument; necessary for kwargs
request = {'method': method}

# validate the service url is set
Expand Down Expand Up @@ -308,16 +312,32 @@ def prepare_request(self,
files = remove_null_values(files)
files = files.items()
# Next, fill in any missing filenames from file tuples.
for part_name, tuple in files:
if tuple and len(tuple) == 3 and tuple[0] is None:
file = tuple[1]
for part_name, file_tuple in files:
if file_tuple and len(file_tuple) == 3 and file_tuple[0] is None:
file = file_tuple[1]
if file and hasattr(file, 'name'):
filename = basename(file.name)
tuple = (filename, tuple[1], tuple[2])
new_files.append((part_name, tuple))
file_tuple = (filename, file_tuple[1], file_tuple[2])
new_files.append((part_name, file_tuple))
request['files'] = new_files
return request

@staticmethod
def encode_path_vars(*args: str) -> List[str]:
"""Encode path variables to be substituted into a URL path.
Arguments:
args: A list of strings to be URL path encoded
Returns:
A list of encoded strings that are safe to substitute into a URL path.
"""
return (requests.utils.quote(x, safe='') for x in args)

# The methods below are kept for compatibility and should be removed
# in the next major release.

# pylint: disable=protected-access

@staticmethod
def _convert_model(val):
Expand Down
2 changes: 1 addition & 1 deletion ibm_cloud_sdk_core/cp4d_token_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,4 @@ def set_proxies(self, proxies: Dict[str, str]):
if isinstance(proxies, dict):
self.proxies = proxies
else:
raise TypeError('proxies must be a dictionary')
raise TypeError('proxies must be a dictionary')
5 changes: 3 additions & 2 deletions ibm_cloud_sdk_core/detailed_response.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from typing import Dict, Optional

import json
import requests
from typing import Dict, Optional

class DetailedResponse(object):
class DetailedResponse:
"""Custom class for detailed response returned from APIs.
Keyword Args:
Expand Down
3 changes: 2 additions & 1 deletion ibm_cloud_sdk_core/get_authenticator.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.

from .authenticators import Authenticator, BasicAuthenticator, BearerTokenAuthenticator, CloudPakForDataAuthenticator, IAMAuthenticator, NoAuthAuthenticator
from .authenticators import (Authenticator, BasicAuthenticator, BearerTokenAuthenticator,
CloudPakForDataAuthenticator, IAMAuthenticator, NoAuthAuthenticator)
from .utils import read_external_sources

def get_authenticator_from_environment(service_name: str) -> Authenticator:
Expand Down
5 changes: 3 additions & 2 deletions ibm_cloud_sdk_core/iam_token_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ class IAMTokenManager(JWTTokenManager):
proxies (dict): Proxies to use for communicating with IAM.
proxies.http (str): The proxy endpoint to use for HTTP requests.
proxies.https (str): The proxy endpoint to use for HTTPS requests.
http_config (dict): The dictionary can contain values that control the timeout, proxies, and etc of HTTP requests.
http_config (dict): A dictionary containing values that control the timeout, proxies, and etc of HTTP requests.
Args:
apikey: A generated APIKey from ibmcloud.
Expand Down Expand Up @@ -81,7 +81,8 @@ def __init__(self,
def request_token(self) -> dict:
"""Request an IAM OAuth token given an API Key.
If client_id and client_secret are specified use their values as a user and pass auth set according to WHATWG url spec.
If client_id and client_secret are specified use their values as a user and pass auth set
according to WHATWG url spec.
Returns:
A dictionary containing the bearer token to be subsequently used service requests.
Expand Down
16 changes: 9 additions & 7 deletions ibm_cloud_sdk_core/jwt_token_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import jwt
import requests
import time
from typing import Optional

import jwt
import requests
from .api_exception import ApiException


class JWTTokenManager(object):
class JWTTokenManager:
"""An abstract class to contain functionality for parsing, storing, and requesting JWT tokens.
get_token will retrieve a new token from the url in case the that there is no existing token,
Expand All @@ -43,7 +44,7 @@ class JWTTokenManager(object):
token_name (str): The key used of the token in the dict returned from request_token.
token_info (dict): The most token_response from request_token.
time_for_new_token (int): The time in epoch seconds when the current token within token_info will expire.
http_config (dict): The dictionary can contain values that control the timeout, proxies, and etc of HTTP requests.
http_config (dict): A dictionary containing values that control the timeout, proxies, and etc of HTTP requests.
"""

def __init__(self, url: str, disable_ssl_verification: bool = False, token_name: Optional[str] = None):
Expand Down Expand Up @@ -89,7 +90,8 @@ def request_token(self):
'request_token MUST be overridden by a subclass of JWTTokenManager.'
)

def _get_current_time(self):
@staticmethod
def _get_current_time():
return int(time.time())

def _is_token_expired(self):
Expand Down Expand Up @@ -160,5 +162,5 @@ def _request(self,
**kwargs)
if 200 <= response.status_code <= 299:
return response.json()
else:
raise ApiException(response.status_code, http_response=response)

raise ApiException(response.status_code, http_response=response)
Loading

0 comments on commit 14f2999

Please sign in to comment.