Skip to content

Commit 673a2b7

Browse files
authored
compitable for python2 migration (#4)
ENHANCEMENT: - Provide static code analysis tools with ast transformer to sync python 3 sdk implementation to python 2 (#4) - Improve validation error message (#4) - Add client-level logger (#4)
1 parent fb60651 commit 673a2b7

File tree

52 files changed

+5615
-5535
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+5615
-5535
lines changed

.travis.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ deploy:
2828
local_dir: docs/build/html
2929
on:
3030
branch: master
31-
tags: true
3231
repo: ucloud/ucloud-sdk-python3
3332
python: 3.7
3433
- provider: pypi

docs/services.rst

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
UCloud SDK Services
22
===================
33

4-
UDPN
5-
----
4+
UDB
5+
---
66

7-
.. autoclass:: ucloud.services.udpn.client.UDPNClient
7+
.. autoclass:: ucloud.services.udb.client.UDBClient
88
:members:
99

1010
UAccount
@@ -13,16 +13,16 @@ UAccount
1313
.. autoclass:: ucloud.services.uaccount.client.UAccountClient
1414
:members:
1515

16-
UMem
17-
----
16+
UHost
17+
-----
1818

19-
.. autoclass:: ucloud.services.umem.client.UMemClient
19+
.. autoclass:: ucloud.services.uhost.client.UHostClient
2020
:members:
2121

22-
UDB
22+
ULB
2323
---
2424

25-
.. autoclass:: ucloud.services.udb.client.UDBClient
25+
.. autoclass:: ucloud.services.ulb.client.ULBClient
2626
:members:
2727

2828
UPHost
@@ -31,28 +31,16 @@ UPHost
3131
.. autoclass:: ucloud.services.uphost.client.UPHostClient
3232
:members:
3333

34-
UDisk
35-
-----
36-
37-
.. autoclass:: ucloud.services.udisk.client.UDiskClient
38-
:members:
39-
4034
VPC
4135
---
4236

4337
.. autoclass:: ucloud.services.vpc.client.VPCClient
4438
:members:
4539

46-
UNet
40+
UDPN
4741
----
4842

49-
.. autoclass:: ucloud.services.unet.client.UNetClient
50-
:members:
51-
52-
ULB
53-
---
54-
55-
.. autoclass:: ucloud.services.ulb.client.ULBClient
43+
.. autoclass:: ucloud.services.udpn.client.UDPNClient
5644
:members:
5745

5846
PathX
@@ -61,9 +49,21 @@ PathX
6149
.. autoclass:: ucloud.services.pathx.client.PathXClient
6250
:members:
6351

64-
UHost
52+
UDisk
6553
-----
6654

67-
.. autoclass:: ucloud.services.uhost.client.UHostClient
55+
.. autoclass:: ucloud.services.udisk.client.UDiskClient
56+
:members:
57+
58+
UMem
59+
----
60+
61+
.. autoclass:: ucloud.services.umem.client.UMemClient
62+
:members:
63+
64+
UNet
65+
----
66+
67+
.. autoclass:: ucloud.services.unet.client.UNetClient
6868
:members:
6969

examples/uhost/main.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from ucloud.helpers import wait, utils
77

88
logging.basicConfig()
9-
logger = logging.getLogger(__name__)
9+
logger = logging.getLogger('ucloud')
1010
logger.setLevel(logging.DEBUG)
1111

1212

@@ -19,7 +19,9 @@ def main():
1919
})
2020

2121
logger.info("finding image, random choice one")
22-
images = client.uhost().describe_image({'ImageType': 'Base'}).get('ImageSet', [])
22+
images = client.uhost().describe_image({
23+
'ImageType': 'Base', 'OsType': 'Linux'
24+
}).get('ImageSet', [])
2325

2426
assert len(images) > 0
2527

@@ -35,7 +37,7 @@ def main():
3537
'CPU': 1,
3638
'Memory': 1024,
3739
'Disks': [{
38-
'Size': 20,
40+
'Size': image["ImageSize"],
3941
'Type': 'CLOUD_NORMAL',
4042
'IsBoot': 'True',
4143
}],

setup.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,9 @@ def do_setup():
100100
"Intended Audience :: System Administrators",
101101
"License :: OSI Approved :: Apache Software License",
102102
"Programming Language :: Python :: 3 :: Only",
103+
"Programming Language :: Python :: 3.5",
104+
"Programming Language :: Python :: 3.6",
105+
"Programming Language :: Python :: 3.7",
103106
"Topic :: Software Development",
104107
],
105108
author="ucloud",

tests/test_core/test_client.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,11 @@ def client():
2121
)
2222

2323

24-
def test_pre_check(client):
25-
env.pre_check_env()
26-
27-
2824
class TestAccClient:
25+
@pytest.mark.skipif(env.is_ut(), reason=env.get_skip_reason())
26+
def test_pre_check(self, client):
27+
env.pre_check_env()
28+
2929
@pytest.mark.skipif(env.is_ut(), reason=env.get_skip_reason())
3030
def test_client_invoke(self, client):
3131
resp = client.invoke("DescribeUHostInstance")

tests/test_helpers/test_utils.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
from ucloud.helpers import utils
2+
3+
4+
def test_b64encode():
5+
encoded = utils.b64encode("foobar42")
6+
assert encoded == 'Zm9vYmFyNDI='
7+
8+
9+
def test_b64decode():
10+
decoded = utils.b64decode("Zm9vYmFyNDI=")
11+
assert decoded == 'foobar42'

ucloud/client.py

Lines changed: 64 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,52 +1,64 @@
1-
from ucloud.core import client
2-
3-
4-
class Client(client.Client):
5-
def __init__(self, config: dict, transport=None, middleware=None):
6-
self._config = config
7-
super(Client, self).__init__(config, transport, middleware)
8-
9-
def udb(self):
10-
from ucloud.services.udb.client import UDBClient
11-
return UDBClient(self._config, self.transport, self.middleware)
12-
13-
def uphost(self):
14-
from ucloud.services.uphost.client import UPHostClient
15-
return UPHostClient(self._config, self.transport, self.middleware)
16-
17-
def unet(self):
18-
from ucloud.services.unet.client import UNetClient
19-
return UNetClient(self._config, self.transport, self.middleware)
20-
21-
def vpc(self):
22-
from ucloud.services.vpc.client import VPCClient
23-
return VPCClient(self._config, self.transport, self.middleware)
24-
25-
def udpn(self):
26-
from ucloud.services.udpn.client import UDPNClient
27-
return UDPNClient(self._config, self.transport, self.middleware)
28-
29-
def uaccount(self):
30-
from ucloud.services.uaccount.client import UAccountClient
31-
return UAccountClient(self._config, self.transport, self.middleware)
32-
33-
def uhost(self):
34-
from ucloud.services.uhost.client import UHostClient
35-
return UHostClient(self._config, self.transport, self.middleware)
36-
37-
def umem(self):
38-
from ucloud.services.umem.client import UMemClient
39-
return UMemClient(self._config, self.transport, self.middleware)
40-
41-
def ulb(self):
42-
from ucloud.services.ulb.client import ULBClient
43-
return ULBClient(self._config, self.transport, self.middleware)
44-
45-
def udisk(self):
46-
from ucloud.services.udisk.client import UDiskClient
47-
return UDiskClient(self._config, self.transport, self.middleware)
48-
49-
def pathx(self):
50-
from ucloud.services.pathx.client import PathXClient
51-
return PathXClient(self._config, self.transport, self.middleware)
52-
1+
from ucloud.core import client
2+
3+
4+
class Client(client.Client):
5+
def __init__(self, config: dict, transport=None, middleware=None):
6+
self._config = config
7+
super(Client, self).__init__(config, transport, middleware)
8+
9+
def umem(self):
10+
from ucloud.services.umem.client import UMemClient
11+
12+
return UMemClient(self._config, self.transport, self.middleware, self.logger)
13+
14+
def unet(self):
15+
from ucloud.services.unet.client import UNetClient
16+
17+
return UNetClient(self._config, self.transport, self.middleware, self.logger)
18+
19+
def uaccount(self):
20+
from ucloud.services.uaccount.client import UAccountClient
21+
22+
return UAccountClient(
23+
self._config, self.transport, self.middleware, self.logger
24+
)
25+
26+
def udisk(self):
27+
from ucloud.services.udisk.client import UDiskClient
28+
29+
return UDiskClient(self._config, self.transport, self.middleware, self.logger)
30+
31+
def udpn(self):
32+
from ucloud.services.udpn.client import UDPNClient
33+
34+
return UDPNClient(self._config, self.transport, self.middleware, self.logger)
35+
36+
def uhost(self):
37+
from ucloud.services.uhost.client import UHostClient
38+
39+
return UHostClient(self._config, self.transport, self.middleware, self.logger)
40+
41+
def pathx(self):
42+
from ucloud.services.pathx.client import PathXClient
43+
44+
return PathXClient(self._config, self.transport, self.middleware, self.logger)
45+
46+
def uphost(self):
47+
from ucloud.services.uphost.client import UPHostClient
48+
49+
return UPHostClient(self._config, self.transport, self.middleware, self.logger)
50+
51+
def vpc(self):
52+
from ucloud.services.vpc.client import VPCClient
53+
54+
return VPCClient(self._config, self.transport, self.middleware, self.logger)
55+
56+
def udb(self):
57+
from ucloud.services.udb.client import UDBClient
58+
59+
return UDBClient(self._config, self.transport, self.middleware, self.logger)
60+
61+
def ulb(self):
62+
from ucloud.services.ulb.client import ULBClient
63+
64+
return ULBClient(self._config, self.transport, self.middleware, self.logger)

ucloud/core/client/_client.py

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@
55
from ucloud import version
66
from ucloud.core.client._cfg import Config
77
from ucloud.core.transport import Transport, RequestsTransport, Request, Response
8+
from ucloud.core.utils import log
89
from ucloud.core.utils.middleware import Middleware
910
from ucloud.core import auth, exc
1011

11-
logger = logging.getLogger(__name__)
12-
1312
default_transport = RequestsTransport()
1413

1514

@@ -19,31 +18,32 @@ def __init__(
1918
config: dict,
2019
transport: typing.Optional[Transport] = None,
2120
middleware: typing.Optional[Middleware] = None,
21+
logger: typing.Optional[logging.Logger] = None,
2222
):
2323
cfg, cred = self._parse_dict_config(config)
2424
self.config = cfg
2525
self.credential = cred
2626
self.transport = transport or default_transport
27-
27+
self.logger = logger or log.default_logger
2828
if middleware is None:
2929
middleware = Middleware()
30-
middleware.response(Client.logged_response_handler)
30+
middleware.response(self.logged_response_handler)
31+
middleware.request(self.logged_request_handler)
3132
self._middleware = middleware
3233

33-
def invoke(self, action: str, args: dict = None, **options: typing.Any) -> dict:
34+
def invoke(self, action: str, args: dict = None, **options) -> dict:
3435
""" invoke will invoke the action with arguments data and options
3536
3637
:param str action: the api action, like `CreateUHostInstance`
3738
:param dict args: arguments of api(action), see doc: `UCloud API Documentation <https://docs.ucloud.cn/api>`__
3839
:return:
3940
"""
4041
retries = 0
41-
req = self._build_request(action, args)
4242
max_retries = options.get("max_retries") or self.config.max_retries
4343

4444
while retries <= max_retries:
4545
try:
46-
return self._send(req, **options)
46+
return self._send(action, args or {}, **options)
4747
except exc.UCloudException as e:
4848
if e.retryable and retries != max_retries:
4949
logging.info(
@@ -61,14 +61,12 @@ def invoke(self, action: str, args: dict = None, **options: typing.Any) -> dict:
6161
def middleware(self) -> Middleware:
6262
return self._middleware
6363

64-
@staticmethod
65-
def logged_response_handler(resp: Response) -> Response:
66-
""" logging response data
64+
def logged_request_handler(self, req):
65+
self.logger.info("[request] {} {}".format(req.get("Action", ""), req))
66+
return req
6767

68-
:param resp:
69-
:return:
70-
"""
71-
logger.info(resp)
68+
def logged_response_handler(self, resp):
69+
self.logger.info("[response] {} {}".format(resp.get("Action", ""), resp))
7270
return resp
7371

7472
def __enter__(self):
@@ -78,9 +76,11 @@ def __enter__(self):
7876
def _parse_dict_config(config: dict) -> typing.Tuple[Config, auth.Credential]:
7977
return Config.from_dict(config), auth.Credential.from_dict(config)
8078

81-
def _send(self, req: Request, **options: dict) -> dict:
79+
def _send(self, action: str, args: dict, **options) -> dict:
80+
args["Action"] = action
8281
for handler in self.middleware.request_handlers:
83-
req = handler(req)
82+
args = handler(args)
83+
req = self._build_http_request(args)
8484

8585
max_retries = options.get("max_retries") or self.config.max_retries
8686
timeout = options.get("timeout") or self.config.timeout
@@ -98,12 +98,9 @@ def _send(self, req: Request, **options: dict) -> dict:
9898

9999
return resp
100100

101-
def _build_request(self, action: str, data: dict = None) -> Request:
101+
def _build_http_request(self, args: dict) -> Request:
102102
payload = {"Region": self.config.region, "ProjectId": self.config.project_id}
103-
payload.update(
104-
{k: v for k, v in (data or {}).items() if v is not None}
105-
) # overwrite region and project id
106-
payload["Action"] = action # overwrite action
103+
payload.update({k: v for k, v in args.items() if v is not None})
107104
payload["Signature"] = self.credential.verify_ac(payload)
108105

109106
return Request(

0 commit comments

Comments
 (0)