ucloud-sdk-python3 0.11.81__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ucloud/__init__.py +0 -0
- ucloud/client.py +469 -0
- ucloud/core/__init__.py +0 -0
- ucloud/core/auth/__init__.py +3 -0
- ucloud/core/auth/_cfg.py +72 -0
- ucloud/core/client/__init__.py +8 -0
- ucloud/core/client/_cfg.py +96 -0
- ucloud/core/client/_client.py +176 -0
- ucloud/core/exc/__init__.py +9 -0
- ucloud/core/exc/_exc.py +94 -0
- ucloud/core/transport/__init__.py +4 -0
- ucloud/core/transport/_requests.py +135 -0
- ucloud/core/transport/http.py +120 -0
- ucloud/core/transport/utils.py +40 -0
- ucloud/core/typesystem/__init__.py +0 -0
- ucloud/core/typesystem/abstract.py +60 -0
- ucloud/core/typesystem/encoder.py +33 -0
- ucloud/core/typesystem/fields.py +149 -0
- ucloud/core/typesystem/schema.py +97 -0
- ucloud/core/utils/__init__.py +0 -0
- ucloud/core/utils/compat.py +15 -0
- ucloud/core/utils/deco.py +31 -0
- ucloud/core/utils/log.py +29 -0
- ucloud/core/utils/middleware.py +63 -0
- ucloud/helpers/__init__.py +0 -0
- ucloud/helpers/utils.py +90 -0
- ucloud/helpers/wait.py +108 -0
- ucloud/services/__init__.py +0 -0
- ucloud/services/cube/__init__.py +0 -0
- ucloud/services/cube/client.py +618 -0
- ucloud/services/cube/schemas/__init__.py +0 -0
- ucloud/services/cube/schemas/apis.py +548 -0
- ucloud/services/cube/schemas/models.py +58 -0
- ucloud/services/iam/__init__.py +0 -0
- ucloud/services/iam/client.py +1078 -0
- ucloud/services/iam/schemas/__init__.py +0 -0
- ucloud/services/iam/schemas/apis.py +973 -0
- ucloud/services/iam/schemas/models.py +127 -0
- ucloud/services/ipsecvpn/__init__.py +0 -0
- ucloud/services/ipsecvpn/client.py +522 -0
- ucloud/services/ipsecvpn/schemas/__init__.py +0 -0
- ucloud/services/ipsecvpn/schemas/apis.py +455 -0
- ucloud/services/ipsecvpn/schemas/models.py +134 -0
- ucloud/services/ipv6gw/__init__.py +0 -0
- ucloud/services/ipv6gw/client.py +44 -0
- ucloud/services/ipv6gw/schemas/__init__.py +0 -0
- ucloud/services/ipv6gw/schemas/apis.py +34 -0
- ucloud/services/ipv6gw/schemas/models.py +3 -0
- ucloud/services/isms/__init__.py +0 -0
- ucloud/services/isms/client.py +330 -0
- ucloud/services/isms/schemas/__init__.py +0 -0
- ucloud/services/isms/schemas/apis.py +272 -0
- ucloud/services/isms/schemas/models.py +50 -0
- ucloud/services/pathx/__init__.py +0 -0
- ucloud/services/pathx/client.py +1656 -0
- ucloud/services/pathx/schemas/__init__.py +0 -0
- ucloud/services/pathx/schemas/apis.py +1289 -0
- ucloud/services/pathx/schemas/models.py +420 -0
- ucloud/services/stepflow/__init__.py +0 -0
- ucloud/services/stepflow/client.py +98 -0
- ucloud/services/stepflow/schemas/__init__.py +0 -0
- ucloud/services/stepflow/schemas/apis.py +67 -0
- ucloud/services/stepflow/schemas/models.py +37 -0
- ucloud/services/sts/__init__.py +0 -0
- ucloud/services/sts/client.py +46 -0
- ucloud/services/sts/schemas/__init__.py +0 -0
- ucloud/services/sts/schemas/apis.py +35 -0
- ucloud/services/sts/schemas/models.py +16 -0
- ucloud/services/tidb/__init__.py +0 -0
- ucloud/services/tidb/client.py +120 -0
- ucloud/services/tidb/schemas/__init__.py +0 -0
- ucloud/services/tidb/schemas/apis.py +103 -0
- ucloud/services/tidb/schemas/models.py +11 -0
- ucloud/services/uaaa/__init__.py +0 -0
- ucloud/services/uaaa/client.py +311 -0
- ucloud/services/uaaa/schemas/__init__.py +0 -0
- ucloud/services/uaaa/schemas/apis.py +252 -0
- ucloud/services/uaaa/schemas/models.py +47 -0
- ucloud/services/uaccount/__init__.py +0 -0
- ucloud/services/uaccount/client.py +547 -0
- ucloud/services/uaccount/schemas/__init__.py +0 -0
- ucloud/services/uaccount/schemas/apis.py +442 -0
- ucloud/services/uaccount/schemas/models.py +128 -0
- ucloud/services/uads/__init__.py +0 -0
- ucloud/services/uads/client.py +1148 -0
- ucloud/services/uads/schemas/__init__.py +0 -0
- ucloud/services/uads/schemas/apis.py +983 -0
- ucloud/services/uads/schemas/models.py +199 -0
- ucloud/services/ubill/__init__.py +0 -0
- ucloud/services/ubill/client.py +248 -0
- ucloud/services/ubill/schemas/__init__.py +0 -0
- ucloud/services/ubill/schemas/apis.py +183 -0
- ucloud/services/ubill/schemas/models.py +107 -0
- ucloud/services/ucdn/__init__.py +0 -0
- ucloud/services/ucdn/client.py +1964 -0
- ucloud/services/ucdn/schemas/__init__.py +0 -0
- ucloud/services/ucdn/schemas/apis.py +1395 -0
- ucloud/services/ucdn/schemas/models.py +576 -0
- ucloud/services/ucloudstack/__init__.py +0 -0
- ucloud/services/ucloudstack/client.py +3352 -0
- ucloud/services/ucloudstack/schemas/__init__.py +0 -0
- ucloud/services/ucloudstack/schemas/apis.py +2887 -0
- ucloud/services/ucloudstack/schemas/models.py +560 -0
- ucloud/services/ucompshare/__init__.py +0 -0
- ucloud/services/ucompshare/client.py +820 -0
- ucloud/services/ucompshare/schemas/__init__.py +0 -0
- ucloud/services/ucompshare/schemas/apis.py +623 -0
- ucloud/services/ucompshare/schemas/models.py +241 -0
- ucloud/services/udb/__init__.py +0 -0
- ucloud/services/udb/client.py +2463 -0
- ucloud/services/udb/schemas/__init__.py +0 -0
- ucloud/services/udb/schemas/apis.py +2053 -0
- ucloud/services/udb/schemas/models.py +319 -0
- ucloud/services/udbproxy/__init__.py +0 -0
- ucloud/services/udbproxy/client.py +67 -0
- ucloud/services/udbproxy/schemas/__init__.py +0 -0
- ucloud/services/udbproxy/schemas/apis.py +38 -0
- ucloud/services/udbproxy/schemas/models.py +31 -0
- ucloud/services/uddb/__init__.py +0 -0
- ucloud/services/uddb/client.py +456 -0
- ucloud/services/uddb/schemas/__init__.py +0 -0
- ucloud/services/uddb/schemas/apis.py +520 -0
- ucloud/services/uddb/schemas/models.py +96 -0
- ucloud/services/udi/__init__.py +0 -0
- ucloud/services/udi/client.py +250 -0
- ucloud/services/udi/schemas/__init__.py +0 -0
- ucloud/services/udi/schemas/apis.py +205 -0
- ucloud/services/udi/schemas/models.py +58 -0
- ucloud/services/udisk/__init__.py +0 -0
- ucloud/services/udisk/client.py +832 -0
- ucloud/services/udisk/schemas/__init__.py +0 -0
- ucloud/services/udisk/schemas/apis.py +741 -0
- ucloud/services/udisk/schemas/models.py +100 -0
- ucloud/services/udns/__init__.py +0 -0
- ucloud/services/udns/client.py +380 -0
- ucloud/services/udns/schemas/__init__.py +0 -0
- ucloud/services/udns/schemas/apis.py +293 -0
- ucloud/services/udns/schemas/models.py +58 -0
- ucloud/services/udpn/__init__.py +0 -0
- ucloud/services/udpn/client.py +240 -0
- ucloud/services/udpn/schemas/__init__.py +0 -0
- ucloud/services/udpn/schemas/apis.py +203 -0
- ucloud/services/udpn/schemas/models.py +29 -0
- ucloud/services/udts/__init__.py +0 -0
- ucloud/services/udts/client.py +410 -0
- ucloud/services/udts/schemas/__init__.py +0 -0
- ucloud/services/udts/schemas/apis.py +403 -0
- ucloud/services/udts/schemas/models.py +93 -0
- ucloud/services/uec/__init__.py +0 -0
- ucloud/services/uec/client.py +1510 -0
- ucloud/services/uec/schemas/__init__.py +0 -0
- ucloud/services/uec/schemas/apis.py +1195 -0
- ucloud/services/uec/schemas/models.py +316 -0
- ucloud/services/ufile/__init__.py +0 -0
- ucloud/services/ufile/client.py +698 -0
- ucloud/services/ufile/schemas/__init__.py +0 -0
- ucloud/services/ufile/schemas/apis.py +542 -0
- ucloud/services/ufile/schemas/models.py +139 -0
- ucloud/services/ufs/__init__.py +0 -0
- ucloud/services/ufs/client.py +328 -0
- ucloud/services/ufs/schemas/__init__.py +0 -0
- ucloud/services/ufs/schemas/apis.py +265 -0
- ucloud/services/ufs/schemas/models.py +52 -0
- ucloud/services/ugn/__init__.py +0 -0
- ucloud/services/ugn/client.py +857 -0
- ucloud/services/ugn/schemas/__init__.py +0 -0
- ucloud/services/ugn/schemas/apis.py +678 -0
- ucloud/services/ugn/schemas/models.py +191 -0
- ucloud/services/uhost/__init__.py +0 -0
- ucloud/services/uhost/client.py +1647 -0
- ucloud/services/uhost/schemas/__init__.py +0 -0
- ucloud/services/uhost/schemas/apis.py +1483 -0
- ucloud/services/uhost/schemas/models.py +427 -0
- ucloud/services/uhub/__init__.py +0 -0
- ucloud/services/uhub/client.py +229 -0
- ucloud/services/uhub/schemas/__init__.py +0 -0
- ucloud/services/uhub/schemas/apis.py +194 -0
- ucloud/services/uhub/schemas/models.py +39 -0
- ucloud/services/uk8s/__init__.py +0 -0
- ucloud/services/uk8s/client.py +729 -0
- ucloud/services/uk8s/schemas/__init__.py +0 -0
- ucloud/services/uk8s/schemas/apis.py +639 -0
- ucloud/services/uk8s/schemas/models.py +179 -0
- ucloud/services/ulb/__init__.py +0 -0
- ucloud/services/ulb/client.py +2285 -0
- ucloud/services/ulb/schemas/__init__.py +0 -0
- ucloud/services/ulb/schemas/apis.py +1678 -0
- ucloud/services/ulb/schemas/models.py +591 -0
- ucloud/services/ulighthost/__init__.py +0 -0
- ucloud/services/ulighthost/client.py +576 -0
- ucloud/services/ulighthost/schemas/__init__.py +0 -0
- ucloud/services/ulighthost/schemas/apis.py +445 -0
- ucloud/services/ulighthost/schemas/models.py +133 -0
- ucloud/services/umem/__init__.py +0 -0
- ucloud/services/umem/client.py +1829 -0
- ucloud/services/umem/schemas/__init__.py +0 -0
- ucloud/services/umem/schemas/apis.py +1477 -0
- ucloud/services/umem/schemas/models.py +327 -0
- ucloud/services/umongodb/__init__.py +0 -0
- ucloud/services/umongodb/client.py +752 -0
- ucloud/services/umongodb/schemas/__init__.py +0 -0
- ucloud/services/umongodb/schemas/apis.py +567 -0
- ucloud/services/umongodb/schemas/models.py +220 -0
- ucloud/services/unet/__init__.py +0 -0
- ucloud/services/unet/client.py +1278 -0
- ucloud/services/unet/schemas/__init__.py +0 -0
- ucloud/services/unet/schemas/apis.py +1006 -0
- ucloud/services/unet/schemas/models.py +275 -0
- ucloud/services/unvs/__init__.py +0 -0
- ucloud/services/unvs/client.py +87 -0
- ucloud/services/unvs/schemas/__init__.py +0 -0
- ucloud/services/unvs/schemas/apis.py +66 -0
- ucloud/services/unvs/schemas/models.py +19 -0
- ucloud/services/upfs/__init__.py +0 -0
- ucloud/services/upfs/client.py +252 -0
- ucloud/services/upfs/schemas/__init__.py +0 -0
- ucloud/services/upfs/schemas/apis.py +204 -0
- ucloud/services/upfs/schemas/models.py +36 -0
- ucloud/services/upgsql/__init__.py +0 -0
- ucloud/services/upgsql/client.py +1007 -0
- ucloud/services/upgsql/schemas/__init__.py +0 -0
- ucloud/services/upgsql/schemas/apis.py +827 -0
- ucloud/services/upgsql/schemas/models.py +158 -0
- ucloud/services/uphone/__init__.py +0 -0
- ucloud/services/uphone/client.py +2122 -0
- ucloud/services/uphone/schemas/__init__.py +0 -0
- ucloud/services/uphone/schemas/apis.py +1799 -0
- ucloud/services/uphone/schemas/models.py +357 -0
- ucloud/services/uphost/__init__.py +0 -0
- ucloud/services/uphost/client.py +847 -0
- ucloud/services/uphost/schemas/__init__.py +0 -0
- ucloud/services/uphost/schemas/apis.py +689 -0
- ucloud/services/uphost/schemas/models.py +175 -0
- ucloud/services/urocketmq/__init__.py +0 -0
- ucloud/services/urocketmq/client.py +117 -0
- ucloud/services/urocketmq/schemas/__init__.py +0 -0
- ucloud/services/urocketmq/schemas/apis.py +92 -0
- ucloud/services/urocketmq/schemas/models.py +14 -0
- ucloud/services/uslk/__init__.py +0 -0
- ucloud/services/uslk/client.py +249 -0
- ucloud/services/uslk/schemas/__init__.py +0 -0
- ucloud/services/uslk/schemas/apis.py +191 -0
- ucloud/services/uslk/schemas/models.py +74 -0
- ucloud/services/usms/__init__.py +0 -0
- ucloud/services/usms/client.py +759 -0
- ucloud/services/usms/schemas/__init__.py +0 -0
- ucloud/services/usms/schemas/apis.py +653 -0
- ucloud/services/usms/schemas/models.py +215 -0
- ucloud/services/utsdb/__init__.py +0 -0
- ucloud/services/utsdb/client.py +604 -0
- ucloud/services/utsdb/schemas/__init__.py +0 -0
- ucloud/services/utsdb/schemas/apis.py +515 -0
- ucloud/services/utsdb/schemas/models.py +61 -0
- ucloud/services/uvms/__init__.py +0 -0
- ucloud/services/uvms/client.py +119 -0
- ucloud/services/uvms/schemas/__init__.py +0 -0
- ucloud/services/uvms/schemas/apis.py +88 -0
- ucloud/services/uvms/schemas/models.py +40 -0
- ucloud/services/vpc/__init__.py +0 -0
- ucloud/services/vpc/client.py +3233 -0
- ucloud/services/vpc/schemas/__init__.py +0 -0
- ucloud/services/vpc/schemas/apis.py +2529 -0
- ucloud/services/vpc/schemas/models.py +651 -0
- ucloud/testing/__init__.py +0 -0
- ucloud/testing/driver/__init__.py +5 -0
- ucloud/testing/driver/_scenario.py +93 -0
- ucloud/testing/driver/_specification.py +57 -0
- ucloud/testing/driver/_step.py +166 -0
- ucloud/testing/env.py +28 -0
- ucloud/testing/exc.py +18 -0
- ucloud/testing/funcs.py +68 -0
- ucloud/testing/mock.py +28 -0
- ucloud/testing/op.py +177 -0
- ucloud/testing/utest.py +195 -0
- ucloud/version.py +1 -0
- ucloud_sdk_python3-0.11.81.dist-info/LICENSE +202 -0
- ucloud_sdk_python3-0.11.81.dist-info/METADATA +71 -0
- ucloud_sdk_python3-0.11.81.dist-info/RECORD +280 -0
- ucloud_sdk_python3-0.11.81.dist-info/WHEEL +5 -0
- ucloud_sdk_python3-0.11.81.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import typing
|
|
3
|
+
from collections.abc import Iterable
|
|
4
|
+
|
|
5
|
+
from ucloud.core.typesystem import abstract
|
|
6
|
+
from ucloud.core.exc import ValidationException
|
|
7
|
+
from ucloud.core.utils.compat import str
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class List(abstract.Field):
|
|
11
|
+
"""array param is the custom field to parse custom param such as:
|
|
12
|
+
|
|
13
|
+
- IP.N
|
|
14
|
+
- UDisk.N.Size
|
|
15
|
+
- NetInterface.N.EIP.Bandwidth
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
def __init__(
|
|
19
|
+
self,
|
|
20
|
+
item: typing.Union[abstract.Field, abstract.Schema],
|
|
21
|
+
default=list,
|
|
22
|
+
**kwargs
|
|
23
|
+
):
|
|
24
|
+
super(List, self).__init__(default=default, **kwargs)
|
|
25
|
+
self.item = item
|
|
26
|
+
|
|
27
|
+
def dumps(self, value, name=None, **kwargs):
|
|
28
|
+
if not isinstance(value, Iterable):
|
|
29
|
+
raise ValidationException(
|
|
30
|
+
"invalid field {}, expect list, got {}".format(
|
|
31
|
+
name, type(value)
|
|
32
|
+
)
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
errors = []
|
|
36
|
+
values = []
|
|
37
|
+
for each in value:
|
|
38
|
+
try:
|
|
39
|
+
v = self.item.dumps(each)
|
|
40
|
+
except ValidationException as e:
|
|
41
|
+
errors.extend(e.errors)
|
|
42
|
+
else:
|
|
43
|
+
values.append(v)
|
|
44
|
+
|
|
45
|
+
if len(errors) > 0:
|
|
46
|
+
raise ValidationException(errors)
|
|
47
|
+
|
|
48
|
+
return values
|
|
49
|
+
|
|
50
|
+
def loads(self, value, name=None, **kwargs):
|
|
51
|
+
if not isinstance(value, Iterable):
|
|
52
|
+
raise ValidationException(
|
|
53
|
+
"invalid field {}, expect list, got {}".format(
|
|
54
|
+
name, type(value)
|
|
55
|
+
)
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
errors = []
|
|
59
|
+
values = []
|
|
60
|
+
for each in value:
|
|
61
|
+
try:
|
|
62
|
+
v = self.item.loads(each)
|
|
63
|
+
except ValidationException as e:
|
|
64
|
+
errors.extend(e.errors)
|
|
65
|
+
else:
|
|
66
|
+
values.append(v)
|
|
67
|
+
|
|
68
|
+
if len(errors) > 0:
|
|
69
|
+
raise ValidationException(errors)
|
|
70
|
+
|
|
71
|
+
return values
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class Str(abstract.Field):
|
|
75
|
+
def dumps(self, value, name=None, **kwargs):
|
|
76
|
+
return self._convert(value, name)
|
|
77
|
+
|
|
78
|
+
def loads(self, value, name=None, **kwargs):
|
|
79
|
+
return self._convert(value, name)
|
|
80
|
+
|
|
81
|
+
def _convert(self, value, name=None):
|
|
82
|
+
if self.strict and not isinstance(value, str):
|
|
83
|
+
self.fail(name, "str", type(value))
|
|
84
|
+
|
|
85
|
+
return str(value)
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
class Base64(Str):
|
|
89
|
+
def dumps(self, value, name=None, **kwargs):
|
|
90
|
+
s = super(Base64, self).dumps(value, name)
|
|
91
|
+
return base64.b64encode(s.encode()).decode()
|
|
92
|
+
|
|
93
|
+
def loads(self, value, name=None, **kwargs):
|
|
94
|
+
s = super(Base64, self).loads(value, name)
|
|
95
|
+
return base64.b64decode(s.encode()).decode()
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
class Int(abstract.Field):
|
|
99
|
+
def dumps(self, value, name=None, **kwargs):
|
|
100
|
+
return self._convert(value, name)
|
|
101
|
+
|
|
102
|
+
def loads(self, value, name=None, **kwargs):
|
|
103
|
+
return self._convert(value, name)
|
|
104
|
+
|
|
105
|
+
def _convert(self, value, name=None):
|
|
106
|
+
if self.strict and not isinstance(value, int):
|
|
107
|
+
self.fail(name, "int", type(value))
|
|
108
|
+
|
|
109
|
+
try:
|
|
110
|
+
return int(value)
|
|
111
|
+
except ValueError:
|
|
112
|
+
self.fail(name, "int", type(value))
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
class Float(abstract.Field):
|
|
116
|
+
def dumps(self, value, name=None, **kwargs):
|
|
117
|
+
return self._convert(value, name)
|
|
118
|
+
|
|
119
|
+
def loads(self, value, name=None, **kwargs):
|
|
120
|
+
return self._convert(value, name)
|
|
121
|
+
|
|
122
|
+
def _convert(self, value, name=None):
|
|
123
|
+
if self.strict and not isinstance(value, float):
|
|
124
|
+
self.fail(name, "float", type(value))
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
return float(value)
|
|
128
|
+
except ValueError:
|
|
129
|
+
self.fail(name, "float", type(value))
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
class Bool(abstract.Field):
|
|
133
|
+
def dumps(self, value, name=None, **kwargs):
|
|
134
|
+
return self._convert(value, name)
|
|
135
|
+
|
|
136
|
+
def loads(self, value, name=None, **kwargs):
|
|
137
|
+
return self._convert(value, name)
|
|
138
|
+
|
|
139
|
+
def _convert(self, value, name=None):
|
|
140
|
+
if self.strict and not isinstance(value, bool):
|
|
141
|
+
self.fail(name, "bool", type(value))
|
|
142
|
+
|
|
143
|
+
if value == "true" or value is True:
|
|
144
|
+
return True
|
|
145
|
+
|
|
146
|
+
if value == "false" or value is False:
|
|
147
|
+
return False
|
|
148
|
+
|
|
149
|
+
self.fail(name, "bool", type(value))
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from ucloud.core.typesystem import abstract
|
|
3
|
+
from ucloud.core.exc import ValidationException
|
|
4
|
+
from ucloud.core.utils import compat
|
|
5
|
+
|
|
6
|
+
logger = logging.getLogger(__name__)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class Schema(abstract.Schema):
|
|
10
|
+
fields = {} # noqa: F811
|
|
11
|
+
|
|
12
|
+
def dumps(self, d: dict, name=None, **kwargs) -> dict:
|
|
13
|
+
result = {}
|
|
14
|
+
errors = []
|
|
15
|
+
|
|
16
|
+
for k, field in self.fields.items():
|
|
17
|
+
v = d.get(k)
|
|
18
|
+
|
|
19
|
+
# resolve value is empty
|
|
20
|
+
if v is None:
|
|
21
|
+
if field.required:
|
|
22
|
+
errors.append(
|
|
23
|
+
ValidationException(
|
|
24
|
+
"the field {k} is required".format(k=k)
|
|
25
|
+
)
|
|
26
|
+
)
|
|
27
|
+
continue
|
|
28
|
+
|
|
29
|
+
if field.default is None:
|
|
30
|
+
continue
|
|
31
|
+
|
|
32
|
+
if isinstance(field.default, compat.Callable):
|
|
33
|
+
v = field.default()
|
|
34
|
+
else:
|
|
35
|
+
v = field.default
|
|
36
|
+
|
|
37
|
+
try:
|
|
38
|
+
serialized = field.dumps(v, name=k)
|
|
39
|
+
except ValidationException as e:
|
|
40
|
+
errors.extend(e.errors)
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
result[field.dump_to or k] = serialized
|
|
44
|
+
|
|
45
|
+
if len(errors) > 0:
|
|
46
|
+
raise ValidationException(errors)
|
|
47
|
+
|
|
48
|
+
return result
|
|
49
|
+
|
|
50
|
+
def loads(self, d: dict, name=None, **kwargs) -> dict:
|
|
51
|
+
result = {}
|
|
52
|
+
errors = []
|
|
53
|
+
|
|
54
|
+
if not self.case_sensitive:
|
|
55
|
+
d = {k.lower(): v for k, v in d.items()}
|
|
56
|
+
|
|
57
|
+
for k, field in self.fields.items():
|
|
58
|
+
load_key = field.load_from or k
|
|
59
|
+
v = d.get(load_key if self.case_sensitive else load_key.lower())
|
|
60
|
+
if v is None:
|
|
61
|
+
if field.default is None:
|
|
62
|
+
continue
|
|
63
|
+
|
|
64
|
+
if isinstance(field.default, compat.Callable):
|
|
65
|
+
v = field.default()
|
|
66
|
+
else:
|
|
67
|
+
v = field.default
|
|
68
|
+
|
|
69
|
+
try:
|
|
70
|
+
serialized = field.loads(v, name=k)
|
|
71
|
+
except ValidationException as e:
|
|
72
|
+
errors.extend(e.errors)
|
|
73
|
+
continue
|
|
74
|
+
|
|
75
|
+
result[k] = serialized
|
|
76
|
+
|
|
77
|
+
if len(errors) > 0:
|
|
78
|
+
raise ValidationException(errors)
|
|
79
|
+
|
|
80
|
+
return result
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class RequestSchema(Schema):
|
|
84
|
+
fields = {} # noqa: F811
|
|
85
|
+
|
|
86
|
+
def dumps(self, d: dict, name=None, **kwargs) -> dict:
|
|
87
|
+
if not isinstance(d, dict):
|
|
88
|
+
raise ValidationException(
|
|
89
|
+
"invalid field {}, expect dict, got {}".format(name, type(d))
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
result = super(RequestSchema, self).dumps(d, name=name, **kwargs)
|
|
93
|
+
return result
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
class ResponseSchema(Schema):
|
|
97
|
+
pass
|
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import sys
|
|
2
|
+
|
|
3
|
+
PY3 = sys.version_info[0] == 3
|
|
4
|
+
|
|
5
|
+
if PY3:
|
|
6
|
+
str = str
|
|
7
|
+
string_types = (str,)
|
|
8
|
+
from collections.abc import Callable
|
|
9
|
+
else:
|
|
10
|
+
import types
|
|
11
|
+
|
|
12
|
+
str = unicode # noqa: F821
|
|
13
|
+
string_types = types.StringTypes
|
|
14
|
+
|
|
15
|
+
from collections import Callable
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import logging
|
|
3
|
+
|
|
4
|
+
logger = logging.getLogger("ucloud")
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def deprecated(instead_of="", message=""):
|
|
8
|
+
"""deprecated is a decorator to mark a function is deprecated.
|
|
9
|
+
it will logging warning when this function called
|
|
10
|
+
|
|
11
|
+
>>> @deprecated(instead_of="new_function")
|
|
12
|
+
... def an_old_function():
|
|
13
|
+
... pass
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def deco(fn):
|
|
17
|
+
@functools.wraps(fn)
|
|
18
|
+
def wrapper(*args, **kwargs):
|
|
19
|
+
msg = [
|
|
20
|
+
"this function/method `{}` is deprecated".format(fn.__name__)
|
|
21
|
+
]
|
|
22
|
+
instead_of and msg.append(
|
|
23
|
+
"please use `{}` instead".format(instead_of)
|
|
24
|
+
)
|
|
25
|
+
message and msg.append(message)
|
|
26
|
+
logger.warning(", ".join(msg))
|
|
27
|
+
return fn(*args, **kwargs)
|
|
28
|
+
|
|
29
|
+
return wrapper
|
|
30
|
+
|
|
31
|
+
return deco
|
ucloud/core/utils/log.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
|
|
3
|
+
DEFAULT_LOGGER_NAME = "ucloud"
|
|
4
|
+
DEFAULT_FORMAT = "%(asctime)s [%(levelname)8s] %(message)s (%(filename)s:%(lineno)s %(name)s)"
|
|
5
|
+
DEFAULT_LEVEL = logging.INFO
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def init_default_logger():
|
|
9
|
+
logger = logging.getLogger(DEFAULT_LOGGER_NAME)
|
|
10
|
+
logger.setLevel(DEFAULT_LEVEL)
|
|
11
|
+
|
|
12
|
+
# create console handler and set level to debug
|
|
13
|
+
ch = logging.StreamHandler()
|
|
14
|
+
ch.setLevel(DEFAULT_LEVEL)
|
|
15
|
+
|
|
16
|
+
# create formatter
|
|
17
|
+
formatter = logging.Formatter(DEFAULT_FORMAT)
|
|
18
|
+
|
|
19
|
+
# add formatter to ch
|
|
20
|
+
ch.setFormatter(formatter)
|
|
21
|
+
|
|
22
|
+
# add ch to logger
|
|
23
|
+
logger.removeHandler(ch)
|
|
24
|
+
logger.addHandler(ch)
|
|
25
|
+
|
|
26
|
+
return logger
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
default_logger = init_default_logger()
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
class Middleware:
|
|
2
|
+
"""middleware is the object to store request/response handlers
|
|
3
|
+
|
|
4
|
+
>>> middleware = Middleware()
|
|
5
|
+
|
|
6
|
+
Add a request handler to prepare the request
|
|
7
|
+
|
|
8
|
+
>>> @middleware.request
|
|
9
|
+
... def prepare(req):
|
|
10
|
+
... req['Region'] = 'cn-bj2'
|
|
11
|
+
... return req
|
|
12
|
+
|
|
13
|
+
Add a response handler to log the response detail
|
|
14
|
+
|
|
15
|
+
>>> @middleware.response
|
|
16
|
+
... def logged(resp):
|
|
17
|
+
... print(resp)
|
|
18
|
+
... return resp
|
|
19
|
+
|
|
20
|
+
>>> len(middleware.request_handlers), len(middleware.response_handlers)
|
|
21
|
+
(1, 1)
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def __init__(self):
|
|
25
|
+
self.request_handlers = []
|
|
26
|
+
self.response_handlers = []
|
|
27
|
+
self.exception_handlers = []
|
|
28
|
+
|
|
29
|
+
def request(self, handler, index=-1):
|
|
30
|
+
"""request is the request handler register to add request handler.
|
|
31
|
+
|
|
32
|
+
:param handler: request handler function, receive request object
|
|
33
|
+
and return a new request
|
|
34
|
+
:param int index: the position of request in the handler list,
|
|
35
|
+
default is append it to end
|
|
36
|
+
:return:
|
|
37
|
+
"""
|
|
38
|
+
self.request_handlers.insert(index, handler)
|
|
39
|
+
return handler
|
|
40
|
+
|
|
41
|
+
def response(self, handler, index=-1):
|
|
42
|
+
"""response is the response handler register to add response handler.
|
|
43
|
+
|
|
44
|
+
:param handler: response handler function, receive response object
|
|
45
|
+
and return a new response
|
|
46
|
+
:param int index: the position of response in the handler list,
|
|
47
|
+
default is append it to end
|
|
48
|
+
:return:
|
|
49
|
+
"""
|
|
50
|
+
self.response_handlers.insert(index, handler)
|
|
51
|
+
return handler
|
|
52
|
+
|
|
53
|
+
def exception(self, handler, index=-1):
|
|
54
|
+
"""exception is the exception handler register to add exception handler.
|
|
55
|
+
|
|
56
|
+
:param handler: exception handler function, receive exception object
|
|
57
|
+
and raise a new exception or ignore it
|
|
58
|
+
:param int index: the position of handler in the handler list,
|
|
59
|
+
default is append it to end
|
|
60
|
+
:return:
|
|
61
|
+
"""
|
|
62
|
+
self.exception_handlers.insert(index, handler)
|
|
63
|
+
return handler
|
|
File without changes
|
ucloud/helpers/utils.py
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import random
|
|
2
|
+
import base64
|
|
3
|
+
import typing
|
|
4
|
+
|
|
5
|
+
_lowercase = "abcdefghijklmnopqrstuvwxyz"
|
|
6
|
+
_uppercase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
7
|
+
_numbers = "0123456789"
|
|
8
|
+
_specials = "_"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def gen_password(
|
|
12
|
+
n: int,
|
|
13
|
+
lower_letters: str = _lowercase,
|
|
14
|
+
upper_letters: str = _uppercase,
|
|
15
|
+
number_letters: str = _numbers,
|
|
16
|
+
special_letters: str = _specials,
|
|
17
|
+
min_lower: int = 1,
|
|
18
|
+
min_upper: int = 1,
|
|
19
|
+
min_number: int = 1,
|
|
20
|
+
min_specials: int = 1,
|
|
21
|
+
):
|
|
22
|
+
"""generate password for any resource
|
|
23
|
+
|
|
24
|
+
>>> len(gen_password(20))
|
|
25
|
+
20
|
|
26
|
+
|
|
27
|
+
:param int n: password total length
|
|
28
|
+
:param str lower_letters: all lowercase letters
|
|
29
|
+
:param str upper_letters: all uppercase letters
|
|
30
|
+
:param str number_letters: all number letters
|
|
31
|
+
:param str special_letters: all special letters
|
|
32
|
+
:param int min_lower: minimal number of lowercase letters
|
|
33
|
+
:param int min_upper: minimal number of uppercase letters
|
|
34
|
+
:param int min_number: minimal number of number letters
|
|
35
|
+
:param int min_specials: minimal number of special letters
|
|
36
|
+
:return:
|
|
37
|
+
"""
|
|
38
|
+
all_letters = "".join(
|
|
39
|
+
[lower_letters, upper_letters, number_letters, special_letters]
|
|
40
|
+
)
|
|
41
|
+
minimal_total = min_lower + min_upper + min_number + min_specials
|
|
42
|
+
if n < minimal_total:
|
|
43
|
+
raise ValueError(
|
|
44
|
+
(
|
|
45
|
+
"the length of password must be larger than "
|
|
46
|
+
"total minimal letters number"
|
|
47
|
+
)
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
minimal_letters = "".join(
|
|
51
|
+
[
|
|
52
|
+
gen_string(lower_letters, min_lower),
|
|
53
|
+
gen_string(upper_letters, min_upper),
|
|
54
|
+
gen_string(number_letters, min_number),
|
|
55
|
+
gen_string(special_letters, min_specials),
|
|
56
|
+
]
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
additional_letters = random.sample(all_letters, n - minimal_total)
|
|
60
|
+
results = list(minimal_letters) + additional_letters
|
|
61
|
+
random.shuffle(results)
|
|
62
|
+
return "".join(results)
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def gen_string(letters: str, length: int):
|
|
66
|
+
return "".join([random.choice(letters) for i in range(length)])
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def first(arr: typing.List[typing.Any]) -> typing.Any:
|
|
70
|
+
if len(arr) == 0:
|
|
71
|
+
return None
|
|
72
|
+
return arr[0]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
def b64encode(s: str) -> str:
|
|
76
|
+
"""base64 encode
|
|
77
|
+
|
|
78
|
+
:param str s: input string
|
|
79
|
+
:return: base64 string
|
|
80
|
+
"""
|
|
81
|
+
return base64.b64encode(s.encode()).decode()
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def b64decode(s: str) -> str:
|
|
85
|
+
"""base64 decode
|
|
86
|
+
|
|
87
|
+
:param str s: base64 string
|
|
88
|
+
:return: output string
|
|
89
|
+
"""
|
|
90
|
+
return base64.b64decode(s.encode()).decode()
|
ucloud/helpers/wait.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import time
|
|
2
|
+
import typing
|
|
3
|
+
import logging
|
|
4
|
+
from ucloud.core import exc
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
MAX_BACKOFF_INTERVAL = 10
|
|
8
|
+
|
|
9
|
+
logger = logging.getLogger(__name__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class WaitTimeoutException(exc.UCloudException):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class StateConf:
|
|
17
|
+
"""StateConf is the utilities class to wait the state return by refresh function achieve the specific state,
|
|
18
|
+
the generally usage is wait the cloud resource, such as uhost, udb ... is
|
|
19
|
+
ready after created.
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
def __init__(
|
|
23
|
+
self,
|
|
24
|
+
pending: typing.List[str],
|
|
25
|
+
target: typing.List[str],
|
|
26
|
+
refresh: typing.Callable,
|
|
27
|
+
timeout: float,
|
|
28
|
+
startup_delay: float = 0,
|
|
29
|
+
min_backoff_interval: float = 0.1,
|
|
30
|
+
max_backoff_interval: float = MAX_BACKOFF_INTERVAL,
|
|
31
|
+
):
|
|
32
|
+
self.pending = pending
|
|
33
|
+
self.target = target
|
|
34
|
+
self.refresh = refresh
|
|
35
|
+
self.timeout = timeout
|
|
36
|
+
self.startup_delay = startup_delay
|
|
37
|
+
self.min_backoff_interval = min_backoff_interval
|
|
38
|
+
self.max_backoff_interval = max_backoff_interval
|
|
39
|
+
|
|
40
|
+
def wait(self):
|
|
41
|
+
start_time = time.time()
|
|
42
|
+
interval = self.min_backoff_interval
|
|
43
|
+
|
|
44
|
+
# delay on start up
|
|
45
|
+
time.sleep(self.startup_delay)
|
|
46
|
+
|
|
47
|
+
# waiting for state changed to target state
|
|
48
|
+
while time.time() - start_time < self.timeout:
|
|
49
|
+
state = self.refresh()
|
|
50
|
+
|
|
51
|
+
if state in self.pending:
|
|
52
|
+
time.sleep(interval)
|
|
53
|
+
interval *= 2
|
|
54
|
+
if interval > self.max_backoff_interval:
|
|
55
|
+
interval = self.max_backoff_interval
|
|
56
|
+
logger.info(
|
|
57
|
+
"waiting state for {self.refresh}, got state {state}".format(
|
|
58
|
+
self=self, state=state
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
if state in self.target:
|
|
64
|
+
return
|
|
65
|
+
|
|
66
|
+
raise WaitTimeoutException(
|
|
67
|
+
"wait timeout {self.timeout}s for {self.refresh}".format(self=self)
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def wait_for_state(
|
|
72
|
+
pending: typing.List[str],
|
|
73
|
+
target: typing.List[str],
|
|
74
|
+
refresh: typing.Callable,
|
|
75
|
+
timeout: float,
|
|
76
|
+
startup_delay: float = 0,
|
|
77
|
+
min_backoff_interval: float = 0.1,
|
|
78
|
+
max_backoff_interval: float = MAX_BACKOFF_INTERVAL,
|
|
79
|
+
):
|
|
80
|
+
"""wait_for_state is a utilities function to wait the state return by refresh function achieve the specific state,
|
|
81
|
+
the generally usage is wait the cloud resource, such as uhost, udb ... is
|
|
82
|
+
ready after created.
|
|
83
|
+
|
|
84
|
+
>>> wait_for_state(
|
|
85
|
+
... pending=["pending"],
|
|
86
|
+
... target=["running"],
|
|
87
|
+
... refresh=lambda: "running",
|
|
88
|
+
... timeout=0.5,
|
|
89
|
+
... )
|
|
90
|
+
|
|
91
|
+
:param pending: pending is the list of pending state, the state is returned by refresh function
|
|
92
|
+
:param target: target is the list of target state, it is usually the terminate state, eg. running and fail
|
|
93
|
+
:param refresh: the customized refresh function, expect no arguments and return a state
|
|
94
|
+
:param timeout: timeout is the total time to wait state is achieved
|
|
95
|
+
:param startup_delay: the time to wait before first refresh function is called
|
|
96
|
+
:param min_backoff_interval: the backoff time for first refresh interval
|
|
97
|
+
:param max_backoff_interval: the max backoff time for refresh interval
|
|
98
|
+
"""
|
|
99
|
+
conf = StateConf(
|
|
100
|
+
pending=pending,
|
|
101
|
+
target=target,
|
|
102
|
+
refresh=refresh,
|
|
103
|
+
timeout=timeout,
|
|
104
|
+
startup_delay=startup_delay,
|
|
105
|
+
min_backoff_interval=min_backoff_interval,
|
|
106
|
+
max_backoff_interval=max_backoff_interval,
|
|
107
|
+
)
|
|
108
|
+
return conf.wait()
|
|
File without changes
|
|
File without changes
|