huaweicloud-sdk-python-v3/huaweicloud-sdk-core/huaweicloudsdkcore/client.py

278 lines
9.8 KiB
Python

# coding: utf-8
"""
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you 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.
"""
import datetime
import importlib
import json
import os
import re
import six
from six.moves.urllib.parse import quote, urlparse
from huaweicloudsdkcore.auth.credentials import BasicCredentials
from huaweicloudsdkcore.exceptions import exceptions
from huaweicloudsdkcore.http.http_client import HttpClient
from huaweicloudsdkcore.http.primitive_types import native_types_mapping
from huaweicloudsdkcore.http.primitive_types import primitive_types
from huaweicloudsdkcore.sdk_request import SdkRequest
from huaweicloudsdkcore.sdk_response import SdkResponse
from huaweicloudsdkcore.utils import http_utils
class ClientBuilder:
def __init__(self, clazz):
self.__clazz = clazz
self.__config = None
self.__credentials = None
self.__endpoint = None
def with_config(self, config):
self.__config = config
return self
def with_credentials(self, credentials):
self.__credentials = credentials
return self
def with_endpoint(self, endpoint):
self.__endpoint = endpoint
return self
def build(self):
client = self.__clazz()
if self.__credentials is None:
self.__credentials = self.get_credential_from_environment_variables()
client.set_config(self.__config)
client.set_credentials(self.__credentials)
client.set_endpoint(self.__endpoint)
return client
def get_credential_from_environment_variables(self):
ak = os.environ.get("HUAWEICLOUD_SDK_AK")
sk = os.environ.get("HUAWEICLOUD_SDK_SK")
project_id = os.environ.get("HUAWEICLOUD_SDK_PROJECT_ID")
domain_id = os.environ.get("HUAWEICLOUD_SDK_DOMAIN_ID")
return BasicCredentials(ak, sk, project_id, domain_id)
class Client:
@staticmethod
def new_builder(clazz):
return ClientBuilder(clazz)
def __init__(self):
self.__http_config = None
self.__credentials = None
self.__config = None
self.__endpoint = None
self.__agent = {"User-Agent": "huaweicloud-sdk-pythons/3.0"}
self.preset_headers = {}
self.model_package = None
try:
exception_handler_model_name = "%s.exception_handler" % self.__module__[:self.__module__.rindex('.')]
self.exception_handler_model = importlib.import_module(exception_handler_model_name)
except ModuleNotFoundError:
self.exception_handler_model = None
def set_config(self, config):
self.__config = config
def set_credentials(self, credentials):
self.__credentials = credentials
def set_endpoint(self, endpoint):
self.__endpoint = endpoint
def get_config(self):
return self.__http_config
def get_credentials(self):
return self.__credentials
def get_endpoint(self):
return self.__endpoint
def do_http_request(self, method, resource_path, path_params=None,
query_params=None, header_params=None, body=None, post_params=None,
response_type=None, collection_formats=None):
url_parse_result = urlparse(self.__endpoint)
schema = url_parse_result.scheme
host = url_parse_result.netloc
header_params = header_params or {}
header_params.update(self.preset_headers)
if header_params:
header_params = http_utils.sanitize_for_serialization(header_params)
header_params = dict(http_utils.parameters_to_tuples(header_params, collection_formats))
header_params.update(self.__agent)
path_params = self.postProcessParams(path_params) or {}
if "project_id" not in path_params:
path_params.update({"project_id": self.get_credentials().project_id})
if path_params:
path_params = http_utils.sanitize_for_serialization(path_params)
path_params = http_utils.parameters_to_tuples(path_params, collection_formats)
for k, v in path_params:
resource_path = resource_path.replace('{%s}' % k, quote(str(v), safe=''))
query_params = self.postProcessParams(query_params) or []
if query_params:
query_params = http_utils.sanitize_for_serialization(query_params)
query_params = http_utils.parameters_to_tuples(query_params, collection_formats)
post_params = self.postProcessParams(post_params) if post_params else []
if post_params:
post_params = http_utils.sanitize_for_serialization(post_params)
post_params = http_utils.parameters_to_tuples(post_params, collection_formats)
if body:
body = http_utils.sanitize_for_serialization(body)
body = json.dumps(body)
else:
body = ""
sdk_request = SdkRequest(method, schema, host, resource_path, path_params,
query_params, header_params, body, post_params)
response = self.__do_http_request(sdk_request)
return_data = response
if self.__config.preload_content:
if response_type:
return_data = self.deserialize(return_data, response_type)
else:
return_data = None
if self.__config.return_http_data_only:
return return_data
else:
return SdkResponse(response.status_code, response.headers, return_data)
def postProcessParams(self, params):
if type(params) == dict:
for key in list(params.keys()):
if params[key] is None:
del [params[key]]
return params
elif type(params) == list:
list_filter = filter(lambda x: type(x) == tuple and len(x) == 2 and x[1] is not None, params)
return [i for i in list_filter]
def __do_http_request(self, sdk_request):
request = self.__credentials.sign_request(sdk_request)
client = HttpClient(request)
client.set_config(self.__config)
if self.exception_handler_model is not None:
client.set_service_spec_exception_handler(getattr(self.exception_handler_model, "handle_exception"))
response = client.do_request()
return response
def deserialize(self, response, response_type):
try:
data = json.loads(response.text)
except ValueError:
data = response.text
return self.__deserialize(data, response_type)
def __deserialize(self, data, klass):
if data is None:
return None
if type(klass) == str:
if klass.startswith('list['):
sub_kls = re.match(r'list\[(.*)\]', klass).group(1)
return [self.__deserialize(sub_data, sub_kls)
for sub_data in data]
if klass.startswith('dict('):
sub_kls = re.match(r'dict\(([^,]*), (.*)\)', klass).group(2)
return {k: self.__deserialize(v, sub_kls)
for k, v in six.iteritems(data)}
if klass in native_types_mapping:
klass = native_types_mapping[klass]
else:
klass = getattr(self.model_package, klass)
if klass in primitive_types:
return self.__deserialize_primitive(data, klass)
elif klass == object:
return self.__deserialize_object(data)
elif klass == datetime.date:
return self.__deserialize_date(data)
elif klass == datetime.datetime:
return self.__deserialize_datatime(data)
else:
return self.__deserialize_model(data, klass)
def __deserialize_primitive(self, data, klass):
try:
return klass(data)
except UnicodeEncodeError:
return six.text_type(data)
except TypeError:
return data
def __deserialize_object(self, value):
return value
def __deserialize_date(self, string):
try:
from dateutil.parser import parse
return parse(string).date()
except ImportError:
return string
except ValueError:
return string
def __deserialize_datatime(self, string):
try:
from dateutil.parser import parse
return parse(string)
except ImportError:
return string
except ValueError:
return string
def __deserialize_model(self, data, klass):
if not klass.openapi_types and not hasattr(klass, 'get_real_child_model'):
return data
kwargs = {}
if klass.openapi_types is not None:
for attr, attr_type in six.iteritems(klass.openapi_types):
if (data is not None and
klass.attribute_map[attr] in data and
isinstance(data, (list, dict))):
value = data[klass.attribute_map[attr]]
kwargs[attr] = self.__deserialize(value, attr_type)
instance = klass(**kwargs)
if hasattr(instance, 'get_real_child_model'):
klass_name = instance.get_real_child_model(data)
if klass_name:
instance = self.__deserialize(data, klass_name)
return instance