cloudpss 4.0.2a1__py3-none-any.whl → 4.1.1a2__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.
- cloudpss/__init__.py +2 -2
- cloudpss/function/functionExecution.py +1 -1
- cloudpss/ieslab/IESLabPlan.py +0 -87
- cloudpss/ieslab/IESLabSimulation.py +2 -62
- cloudpss/job/job.py +98 -135
- cloudpss/job/messageStreamReceiver.py +59 -53
- cloudpss/job/messageStreamSender.py +38 -33
- cloudpss/model/implements/diagram.py +0 -113
- cloudpss/model/model.py +365 -364
- cloudpss/model/revision.py +9 -9
- cloudpss/model/topology.py +9 -2
- cloudpss/runner/__init__.py +5 -3
- cloudpss/runner/receiver.py +2 -0
- cloudpss/runner/runner.py +91 -18
- cloudpss/utils/AsyncIterable.py +27 -0
- cloudpss/utils/__init__.py +5 -1
- cloudpss/utils/httpAsyncRequest.py +89 -0
- cloudpss/utils/httprequests.py +6 -1
- cloudpss/utils/yamlLoader.py +40 -41
- cloudpss/version.py +1 -1
- {cloudpss-4.0.2a1.dist-info → cloudpss-4.1.1a2.dist-info}/METADATA +4 -1
- {cloudpss-4.0.2a1.dist-info → cloudpss-4.1.1a2.dist-info}/RECORD +24 -22
- {cloudpss-4.0.2a1.dist-info → cloudpss-4.1.1a2.dist-info}/WHEEL +0 -0
- {cloudpss-4.0.2a1.dist-info → cloudpss-4.1.1a2.dist-info}/top_level.txt +0 -0
cloudpss/__init__.py
CHANGED
@@ -6,13 +6,13 @@ from .model import Model, ModelRevision, ModelTopology
|
|
6
6
|
from .project import Project
|
7
7
|
from .utils import MatlabDataEncoder, DateTimeEncode
|
8
8
|
from . import function
|
9
|
-
|
9
|
+
from .job import Job
|
10
10
|
from .function import FunctionExecution
|
11
11
|
from .version import __version__
|
12
12
|
__all__ = [
|
13
13
|
'setToken', 'Model', 'ModelRevision', 'ModelTopology', 'Runner', 'Result',
|
14
14
|
'PowerFlowResult', 'EMTResult', 'MatlabDataEncoder', 'DateTimeEncode',
|
15
|
-
'function', 'Project', 'currentJob', 'IESLabSimulation', 'IESLabPlan','__version__'
|
15
|
+
'function', 'Project', 'currentJob', 'IESLabSimulation', 'IESLabPlan','__version__','Job'
|
16
16
|
]
|
17
17
|
|
18
18
|
|
@@ -163,7 +163,7 @@ class FunctionExecution(object):
|
|
163
163
|
sys.exit(code)
|
164
164
|
|
165
165
|
def print(self, data):
|
166
|
-
print(json.dumps(data, cls=MatlabDataEncoder), flush=True)
|
166
|
+
print(json.dumps(data, cls=MatlabDataEncoder)+'\n', flush=True)
|
167
167
|
|
168
168
|
def log(self, content, level='info', html=False, key=None):
|
169
169
|
'''
|
cloudpss/ieslab/IESLabPlan.py
CHANGED
@@ -130,90 +130,3 @@ class IESLabPlan(object):
|
|
130
130
|
:return: Boolean
|
131
131
|
'''
|
132
132
|
return self.planModel.kill()
|
133
|
-
|
134
|
-
def createProjectGroup(self, name):
|
135
|
-
'''
|
136
|
-
创建项目组
|
137
|
-
|
138
|
-
:params name: 项目组名称
|
139
|
-
|
140
|
-
:return: 返回一个创建的项目组
|
141
|
-
'''
|
142
|
-
|
143
|
-
@staticmethod
|
144
|
-
def createProjectGroup(group_name, desc=None, createById=None):
|
145
|
-
'''
|
146
|
-
创建项目组
|
147
|
-
|
148
|
-
:params group_name: String 项目组名称
|
149
|
-
:params desc: String 项目组描述 可选参数
|
150
|
-
:params createById Int 父项目组id 可选参数,如果是从已有项目组导入的项目组,必填此项
|
151
|
-
|
152
|
-
:return: Int 返回创建的项目组id
|
153
|
-
'''
|
154
|
-
try:
|
155
|
-
if createById is None:
|
156
|
-
isImport = 0
|
157
|
-
else:
|
158
|
-
isImport = 1
|
159
|
-
payload = {
|
160
|
-
'group_name': group_name,
|
161
|
-
'desc': desc,
|
162
|
-
'isImport': isImport,
|
163
|
-
'createById': createById,
|
164
|
-
}
|
165
|
-
r = request(
|
166
|
-
'POST', 'api/ieslab-plan/rest/projectgroup/', data=json.dumps(payload))
|
167
|
-
project = json.loads(r.text)
|
168
|
-
return project.get('id', None)
|
169
|
-
except Exception as e:
|
170
|
-
raise Exception('创建项目组失败')
|
171
|
-
|
172
|
-
@staticmethod
|
173
|
-
def createProject(name, project_group, start_date, end_date, construction_cycle, desc=None, createById=None):
|
174
|
-
'''
|
175
|
-
创建项目
|
176
|
-
|
177
|
-
:params name: String 项目名称
|
178
|
-
:params project_group: Int 父项目组id
|
179
|
-
:param start_date: Int 项目开始年限,范围在[1500,3000]之间
|
180
|
-
:param end_date: Int 项目结束年限,范围在项目开始时间之后且不超过五十年
|
181
|
-
:param construction_cycle: Int 项目建设周期(年), 必须小于等于 项目结束年限 - 项目开始年限
|
182
|
-
:params desc: String 项目描述, 可选参数
|
183
|
-
:params createById Int 父项目id, 可选参数, 如果是从已有项目导入的项目,必填此项
|
184
|
-
|
185
|
-
:return: Int 返回创建的项目id
|
186
|
-
'''
|
187
|
-
try:
|
188
|
-
if start_date < 1500 or start_date > 3000:
|
189
|
-
raise Exception('项目开始年限错误,范围在[1500,3000]之间')
|
190
|
-
if end_date < start_date or end_date > start_date + 50:
|
191
|
-
raise Exception('项目结束年限错误,范围在项目开始时间之后且不超过五十年')
|
192
|
-
if construction_cycle > end_date - start_date:
|
193
|
-
raise Exception('项目建设周期错误,必须小于等于 项目结束年限 - 项目开始年限')
|
194
|
-
if createById is None:
|
195
|
-
payload = {
|
196
|
-
'name': name,
|
197
|
-
'project_group': project_group,
|
198
|
-
'start_date': start_date,
|
199
|
-
'end_date': end_date,
|
200
|
-
'construction_cycle': construction_cycle,
|
201
|
-
'desc': desc
|
202
|
-
}
|
203
|
-
else:
|
204
|
-
payload = {
|
205
|
-
'name': name,
|
206
|
-
'project_group': project_group,
|
207
|
-
'start_date': start_date,
|
208
|
-
'end_date': end_date,
|
209
|
-
'construction_cycle': construction_cycle,
|
210
|
-
'desc': desc,
|
211
|
-
'createById': createById
|
212
|
-
}
|
213
|
-
r = request(
|
214
|
-
'POST', 'api/ieslab-plan/rest/simu/', data=json.dumps(payload))
|
215
|
-
project = json.loads(r.text)
|
216
|
-
return project.get('id', None)
|
217
|
-
except Exception as e:
|
218
|
-
raise Exception('创建项目失败')
|
219
|
-
|
@@ -30,6 +30,7 @@ class IESLabSimulation(object):
|
|
30
30
|
r = request(
|
31
31
|
'GET', 'api/ieslab-simulation/rest/simu/{0}/'.format(simulationId))
|
32
32
|
project = json.loads(r.text)
|
33
|
+
print(project)
|
33
34
|
return IESLabSimulation(project)
|
34
35
|
except:
|
35
36
|
raise Exception('未查询到当前算例')
|
@@ -48,67 +49,6 @@ class IESLabSimulation(object):
|
|
48
49
|
job = self.model.jobs[currentJob]
|
49
50
|
|
50
51
|
job['args']['simulationId'] = self.id
|
52
|
+
print(job)
|
51
53
|
return self.model.run(job, name=name)
|
52
|
-
|
53
|
-
@staticmethod
|
54
|
-
def createProjectGroup(group_name, desc=None, createById=None):
|
55
|
-
'''
|
56
|
-
创建项目组
|
57
|
-
|
58
|
-
:params group_name: String 项目组名称
|
59
|
-
:params desc: String 项目组描述 可选参数
|
60
|
-
:params createById Int 父项目组id 可选参数,如果是从已有项目组导入的项目组,必填此项
|
61
|
-
|
62
|
-
:return: Int 返回创建的项目组id
|
63
|
-
'''
|
64
|
-
try:
|
65
|
-
if createById is None:
|
66
|
-
isImport = 0
|
67
|
-
else:
|
68
|
-
isImport = 1
|
69
|
-
payload = {
|
70
|
-
'group_name': group_name,
|
71
|
-
'desc': desc,
|
72
|
-
'isImport': isImport,
|
73
|
-
'createById': createById,
|
74
|
-
}
|
75
|
-
r = request(
|
76
|
-
'POST', 'api/ieslab-simulation/rest/projectgroup/', data=json.dumps(payload))
|
77
|
-
project = json.loads(r.text)
|
78
|
-
return project.get('id', None)
|
79
|
-
except Exception as e:
|
80
|
-
raise Exception('创建项目组失败')
|
81
|
-
|
82
|
-
@staticmethod
|
83
|
-
def createProject(name, project_group, desc=None, createById=None):
|
84
|
-
'''
|
85
|
-
创建项目
|
86
|
-
|
87
|
-
:params name: String 项目名称
|
88
|
-
:params project_group: Int 父项目组id,
|
89
|
-
:params desc: String 项目描述, 可选参数
|
90
|
-
:params createById Int 父项目id, 可选参数, 如果是从已有项目导入的项目,必填此项
|
91
|
-
|
92
|
-
:return: Int 返回创建的项目id
|
93
|
-
'''
|
94
|
-
try:
|
95
|
-
if createById is None:
|
96
|
-
payload = {
|
97
|
-
'name': name,
|
98
|
-
'project_group': project_group,
|
99
|
-
'desc': desc
|
100
|
-
}
|
101
|
-
else:
|
102
|
-
payload = {
|
103
|
-
'name': name,
|
104
|
-
'project_group': project_group,
|
105
|
-
'desc': desc,
|
106
|
-
'createById': createById
|
107
|
-
}
|
108
|
-
r = request(
|
109
|
-
'POST', 'api/ieslab-simulation/rest/simu/', data=json.dumps(payload))
|
110
|
-
project = json.loads(r.text)
|
111
|
-
return project.get('id', None)
|
112
|
-
except Exception as e:
|
113
|
-
raise Exception('创建项目失败')
|
114
54
|
|
cloudpss/job/job.py
CHANGED
@@ -1,6 +1,10 @@
|
|
1
|
+
import asyncio
|
1
2
|
import random
|
2
3
|
import re
|
3
4
|
import time
|
5
|
+
from cloudpss.utils.AsyncIterable import CustomAsyncIterable
|
6
|
+
|
7
|
+
from cloudpss.utils.httpAsyncRequest import graphql_fetch
|
4
8
|
from .view import getViewClass
|
5
9
|
|
6
10
|
from cloudpss.utils.IO import IO
|
@@ -12,20 +16,33 @@ from .jobMachine import JobMachine
|
|
12
16
|
from .messageStreamSender import MessageStreamSender
|
13
17
|
|
14
18
|
|
15
|
-
|
16
19
|
class Job(object):
|
17
20
|
"""docstring for Job"""
|
18
21
|
|
19
|
-
def __init__(
|
20
|
-
|
21
|
-
|
22
|
+
def __init__(
|
23
|
+
self,
|
24
|
+
id,
|
25
|
+
args,
|
26
|
+
createTime,
|
27
|
+
startTime,
|
28
|
+
endTime,
|
29
|
+
status,
|
30
|
+
context,
|
31
|
+
user,
|
32
|
+
priority,
|
33
|
+
policy,
|
34
|
+
machine,
|
35
|
+
input,
|
36
|
+
output,
|
37
|
+
position,
|
38
|
+
):
|
22
39
|
super(Job, self).__init__()
|
23
40
|
self.id = id
|
24
41
|
self.args = args
|
25
42
|
self.createTime = createTime
|
26
43
|
self.startTime = startTime
|
27
44
|
self.endTime = endTime
|
28
|
-
self.
|
45
|
+
self.job_status = status #这里的status字段与原本的status()冲突
|
29
46
|
self.context = context
|
30
47
|
self.user = user
|
31
48
|
self.priority = priority
|
@@ -36,15 +53,16 @@ class Job(object):
|
|
36
53
|
self.position = position
|
37
54
|
self.__receiver = None
|
38
55
|
self.__sender = None
|
56
|
+
self._result = None
|
39
57
|
|
40
58
|
@staticmethod
|
41
|
-
def fetch(id):
|
59
|
+
async def fetch(id):
|
42
60
|
"""
|
43
61
|
获取job信息
|
44
62
|
"""
|
45
63
|
if id is None:
|
46
|
-
raise Exception(
|
47
|
-
query =
|
64
|
+
raise Exception("id is None")
|
65
|
+
query = """query($_a:JobInput!){
|
48
66
|
job(input:$_a){
|
49
67
|
id
|
50
68
|
args
|
@@ -79,165 +97,103 @@ class Job(object):
|
|
79
97
|
output
|
80
98
|
position
|
81
99
|
}
|
82
|
-
}
|
100
|
+
}"""
|
83
101
|
variables = {"_a": {"id": id}}
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
102
|
+
|
103
|
+
r = await graphql_fetch(query, variables)
|
104
|
+
if "errors" in r:
|
105
|
+
raise Exception(r["errors"])
|
106
|
+
return Job(**r["data"]["job"])
|
88
107
|
|
89
108
|
@staticmethod
|
90
|
-
def fetchMany(
|
109
|
+
def fetchMany(*args):
|
91
110
|
"""
|
92
111
|
批量获取任务信息
|
93
112
|
"""
|
94
|
-
|
95
|
-
raise Exception('input is None')
|
96
|
-
query = '''query($_a:JobsInput!){
|
97
|
-
jobs(input:$_a){
|
98
|
-
item {
|
99
|
-
id
|
100
|
-
args
|
101
|
-
createTime
|
102
|
-
startTime
|
103
|
-
endTime
|
104
|
-
status
|
105
|
-
context
|
106
|
-
user
|
107
|
-
priority
|
108
|
-
policy {
|
109
|
-
id
|
110
|
-
name
|
111
|
-
users
|
112
|
-
functions
|
113
|
-
tres {
|
114
|
-
cpu
|
115
|
-
ecpu
|
116
|
-
mem
|
117
|
-
}
|
118
|
-
minPriority
|
119
|
-
maxPriority
|
120
|
-
maxDuration
|
121
|
-
createTime
|
122
|
-
updateTime
|
123
|
-
visibility
|
124
|
-
queue
|
125
|
-
}
|
126
|
-
machine {
|
127
|
-
id
|
128
|
-
name
|
129
|
-
tres {
|
130
|
-
cpu
|
131
|
-
ecpu
|
132
|
-
mem
|
133
|
-
}
|
134
|
-
valid
|
135
|
-
}
|
136
|
-
input
|
137
|
-
output
|
138
|
-
position
|
139
|
-
}
|
140
|
-
cursor
|
141
|
-
count
|
142
|
-
total
|
143
|
-
}
|
144
|
-
}'''
|
145
|
-
variables = {"_a": input}
|
146
|
-
r = graphql_request(query, variables)
|
147
|
-
if 'errors' in r:
|
148
|
-
raise Exception(r['errors'])
|
149
|
-
jobs = []
|
150
|
-
for job in r['data']['jobs']['item']:
|
151
|
-
jobs.append(Job(**job))
|
113
|
+
jobs = CustomAsyncIterable(Job.fetch,*args)
|
152
114
|
return jobs
|
115
|
+
|
153
116
|
|
154
117
|
@staticmethod
|
155
|
-
def create(revisionHash,
|
156
|
-
|
157
|
-
|
158
|
-
name=None,
|
159
|
-
rid='',
|
160
|
-
policy=None,
|
161
|
-
**kwargs):
|
162
|
-
'''
|
163
|
-
创建一个运行任务
|
118
|
+
async def create(revisionHash, job, config, name=None, rid="", policy=None, **kwargs):
|
119
|
+
"""
|
120
|
+
创建一个运行任务
|
164
121
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
122
|
+
:params: revision 项目版本号
|
123
|
+
:params: job 调用仿真时使用的计算方案,为空时使用项目的第一个计算方案
|
124
|
+
:params: config 调用仿真时使用的参数方案,为空时使用项目的第一个参数方案
|
125
|
+
:params: name 任务名称,为空时使用项目的参数方案名称和计算方案名称
|
126
|
+
:params: rid 项目rid,可为空
|
170
127
|
|
171
|
-
|
128
|
+
:return: 返回一个运行实例
|
172
129
|
|
173
|
-
|
174
|
-
|
130
|
+
>>> runner = Runner.runRevision(revision,job,config,'')
|
131
|
+
"""
|
175
132
|
|
176
|
-
|
133
|
+
# 处理policy字段
|
177
134
|
if policy is None:
|
178
135
|
policy = {}
|
179
|
-
if policy.get(
|
180
|
-
policy[
|
181
|
-
policy[
|
182
|
-
policy[
|
183
|
-
tres = {
|
184
|
-
tresStr = job[
|
185
|
-
for t in re.split(
|
186
|
-
if t ==
|
136
|
+
if policy.get("tres", None) is None:
|
137
|
+
policy["tres"] = {}
|
138
|
+
policy["queue"] = job["args"].get("@queue", 1)
|
139
|
+
policy["priority"] = job["args"].get("@priority", 0)
|
140
|
+
tres = {"cpu": 1, "ecpu": 0, "mem": 0}
|
141
|
+
tresStr = job["args"].get("@tres", "")
|
142
|
+
for t in re.split("\s+", tresStr):
|
143
|
+
if t == "":
|
187
144
|
continue
|
188
|
-
k, v = t.split(
|
189
|
-
tres[k] = float(v) #type: ignore
|
190
|
-
policy[
|
145
|
+
k, v = t.split("=")
|
146
|
+
tres[k] = float(v) # type: ignore
|
147
|
+
policy["tres"] = tres
|
191
148
|
|
192
|
-
query =
|
193
|
-
function = job[
|
194
|
-
'function/CloudPSS/')
|
149
|
+
query = """mutation($input:CreateJobInput!){job:createJob(input:$input){id input output status position}}"""
|
150
|
+
function = job["rid"].replace("job-definition/cloudpss/", "function/CloudPSS/")
|
195
151
|
variables = {
|
196
|
-
|
152
|
+
"input": {
|
197
153
|
"args": {
|
198
|
-
**job[
|
199
|
-
|
154
|
+
**job["args"],
|
155
|
+
"_ModelRevision": revisionHash,
|
156
|
+
"_ModelArgs": config["args"],
|
200
157
|
},
|
201
158
|
"context": [
|
202
159
|
function,
|
203
160
|
rid,
|
204
|
-
f"model/@sdk/{str(int(time.time() * random.random()))}"
|
161
|
+
f"model/@sdk/{str(int(time.time() * random.random()))}",
|
205
162
|
],
|
206
|
-
"policy":
|
207
|
-
policy,
|
163
|
+
"policy": policy,
|
208
164
|
}
|
209
165
|
}
|
210
|
-
r =
|
211
|
-
if
|
212
|
-
raise Exception(r[
|
213
|
-
id = r[
|
214
|
-
return Job.fetch(id)
|
166
|
+
r = await graphql_fetch(query, variables)
|
167
|
+
if "errors" in r:
|
168
|
+
raise Exception(r["errors"])
|
169
|
+
id = r["data"]["job"]["id"]
|
170
|
+
return await Job.fetch(id)
|
215
171
|
|
216
172
|
@staticmethod
|
217
|
-
def abort(id, timeout):
|
173
|
+
async def abort(id, timeout):
|
218
174
|
"""
|
219
175
|
结束当前运行的算例
|
220
176
|
|
221
177
|
"""
|
222
|
-
query =
|
178
|
+
query = """mutation ($input: AbortJobInput!) {
|
223
179
|
job: abortJob(input: $input) {
|
224
180
|
id
|
225
181
|
status
|
226
182
|
}
|
227
183
|
}
|
228
|
-
|
229
|
-
variables = {
|
230
|
-
|
184
|
+
"""
|
185
|
+
variables = {"input": {"id": id, "timeout": timeout}}
|
186
|
+
await graphql_fetch(query, variables)
|
231
187
|
|
232
188
|
@staticmethod
|
233
|
-
def load(file, format=
|
189
|
+
def load(file, format="yaml"):
|
234
190
|
return IO.load(file, format)
|
235
191
|
|
236
192
|
@staticmethod
|
237
|
-
def dump(job, file, format=
|
193
|
+
def dump(job, file, format="yaml", compress="gzip"):
|
238
194
|
return IO.dump(job, file, format, compress)
|
239
195
|
|
240
|
-
def read(self, receiver=None, dev=False, **kwargs):
|
196
|
+
async def read(self, receiver=None, dev=False, **kwargs):
|
241
197
|
"""
|
242
198
|
使用接收器获取当前运行实例的输出
|
243
199
|
"""
|
@@ -245,33 +201,40 @@ class Job(object):
|
|
245
201
|
self.__sender = receiver
|
246
202
|
if self.__receiver is None:
|
247
203
|
self.__receiver = MessageStreamReceiver(self, dev)
|
248
|
-
self.__receiver.connect(**kwargs)
|
204
|
+
await self.__receiver.connect(**kwargs)
|
249
205
|
return self.__receiver
|
250
206
|
|
251
|
-
def write(self,sender=None, dev=False, **kwargs)->MessageStreamSender:
|
207
|
+
async def write(self, sender=None, dev=False, **kwargs) -> MessageStreamSender:
|
252
208
|
"""
|
253
|
-
|
209
|
+
使用发送器为当前运行实例输入
|
254
210
|
"""
|
255
|
-
|
211
|
+
|
256
212
|
if sender is not None:
|
257
213
|
self.__sender = sender
|
258
214
|
if self.__sender is None:
|
259
|
-
self.__sender =MessageStreamSender(self,dev)
|
260
|
-
self.__sender.connect(**kwargs)
|
215
|
+
self.__sender = MessageStreamSender(self, dev)
|
216
|
+
await self.__sender.connect(**kwargs)
|
261
217
|
return self.__sender
|
262
218
|
|
219
|
+
def status(self):
|
220
|
+
if self.__receiver is not None:
|
221
|
+
return self.__receiver.status
|
222
|
+
return 0
|
223
|
+
|
263
224
|
@property
|
264
225
|
def result(self):
|
265
226
|
"""
|
266
227
|
获取当前运行实例的输出
|
267
228
|
"""
|
268
|
-
|
269
|
-
|
229
|
+
if self._result is None:
|
230
|
+
viewType = getViewClass(self.context[0])
|
231
|
+
self._result = asyncio.run(self.view(viewType))
|
232
|
+
return self._result
|
270
233
|
|
271
|
-
def view(self, viewType):
|
234
|
+
async def view(self, viewType):
|
272
235
|
"""
|
273
236
|
获取当前运行实例的输出
|
274
237
|
"""
|
275
|
-
receiver = self.read()
|
276
|
-
sender=self.write()
|
277
|
-
return viewType(receiver,sender)
|
238
|
+
receiver = await self.read()
|
239
|
+
sender = await self.write()
|
240
|
+
return viewType(receiver, sender)
|