278 lines
9.8 KiB
Python
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
|