cloudpss 4.1.1b8__tar.gz → 4.5.13__tar.gz

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.
Files changed (126) hide show
  1. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/PKG-INFO +1 -1
  2. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/__init__.py +2 -3
  3. cloudpss-4.5.13/cloudpss/asyncio/__init__.py +8 -0
  4. cloudpss-4.5.13/cloudpss/asyncio/job/job.py +116 -0
  5. cloudpss-4.5.13/cloudpss/asyncio/job/messageStreamReceiver.py +121 -0
  6. cloudpss-4.5.13/cloudpss/asyncio/job/messageStreamSender.py +45 -0
  7. cloudpss-4.5.13/cloudpss/asyncio/model/model.py +257 -0
  8. cloudpss-4.5.13/cloudpss/asyncio/model/revision.py +41 -0
  9. cloudpss-4.5.13/cloudpss/asyncio/model/topology.py +34 -0
  10. cloudpss-4.5.13/cloudpss/asyncio/utils/__init__.py +6 -0
  11. {cloudpss-4.1.1b8/cloudpss → cloudpss-4.5.13/cloudpss/asyncio}/utils/httpAsyncRequest.py +2 -2
  12. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/function/functionExecution.py +74 -5
  13. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/ieslab/DataManageModel.py +144 -9
  14. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/ieslab/EvaluationModel.py +80 -9
  15. cloudpss-4.5.13/cloudpss/ieslab/IESLabOpt.py +235 -0
  16. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/ieslab/IESLabPlan.py +82 -4
  17. cloudpss-4.5.13/cloudpss/ieslab/IESLabSimulation.py +116 -0
  18. cloudpss-4.5.13/cloudpss/ieslab/PlanModel.py +347 -0
  19. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/ieslab/__init__.py +2 -1
  20. cloudpss-4.5.13/cloudpss/job/__init__.py +5 -0
  21. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/job/job.py +136 -141
  22. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/job/jobReceiver.py +8 -2
  23. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/job/messageStreamReceiver.py +42 -99
  24. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/job/messageStreamSender.py +5 -42
  25. cloudpss-4.1.1b8/cloudpss/job/view/EMTView.py → cloudpss-4.5.13/cloudpss/job/result/EMTResult.py +57 -14
  26. cloudpss-4.5.13/cloudpss/job/result/IESLabSimulationResult.py +5 -0
  27. cloudpss-4.5.13/cloudpss/job/result/IESLabTypicalDayResult.py +134 -0
  28. cloudpss-4.1.1b8/cloudpss/job/view/IESView.py → cloudpss-4.5.13/cloudpss/job/result/IESResult.py +7 -5
  29. cloudpss-4.1.1b8/cloudpss/job/view/PowerFlowView.py → cloudpss-4.5.13/cloudpss/job/result/PowerFlowResult.py +2 -2
  30. cloudpss-4.5.13/cloudpss/job/result/__init__.py +40 -0
  31. cloudpss-4.1.1b8/cloudpss/job/view/view.py → cloudpss-4.5.13/cloudpss/job/result/result.py +38 -8
  32. cloudpss-4.5.13/cloudpss/model/__init__.py +5 -0
  33. cloudpss-4.5.13/cloudpss/model/implements/diagram.py +186 -0
  34. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/model/jobDefinitions.py +6 -6
  35. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/model/model.py +245 -226
  36. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/model/revision.py +30 -35
  37. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/model/topology.py +26 -15
  38. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/IESLabEvaluationResult.py +14 -6
  39. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/IESLabPlanResult.py +91 -35
  40. cloudpss-4.5.13/cloudpss/runner/IESLabTypicalDayResult.py +154 -0
  41. cloudpss-4.5.13/cloudpss/runner/MessageStreamReceiver.py +98 -0
  42. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/result.py +6 -1
  43. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/runner.py +97 -53
  44. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/utils/IO.py +3 -1
  45. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/utils/graphqlUtil.py +3 -2
  46. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/utils/httprequests.py +19 -10
  47. cloudpss-4.5.13/cloudpss/version.py +1 -0
  48. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss.egg-info/PKG-INFO +1 -1
  49. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss.egg-info/SOURCES.txt +31 -22
  50. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss.egg-info/requires.txt +1 -1
  51. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/setup.py +1 -1
  52. cloudpss-4.5.13/test/test-plot.py +42 -0
  53. cloudpss-4.5.13/test/test-plot1.py +0 -0
  54. cloudpss-4.5.13/test/test-topology.py +41 -0
  55. cloudpss-4.1.1b8/test/test.py → cloudpss-4.5.13/test/test-topology1.py +8 -6
  56. cloudpss-4.5.13/test/test-yield.py +16 -0
  57. cloudpss-4.5.13/test/test.py +35 -0
  58. cloudpss-4.5.13/test/test11.py +69 -0
  59. cloudpss-4.5.13/test/test12.py +21 -0
  60. cloudpss-4.5.13/test/testRt-test.py +148 -0
  61. cloudpss-4.5.13/test/testRt.py +193 -0
  62. cloudpss-4.1.1b8/test/testRt.py → cloudpss-4.5.13/test/testRt2.py +39 -23
  63. cloudpss-4.5.13/test/testSend.py +47 -0
  64. cloudpss-4.5.13/test/test_modepower_ampratio(3).py +244 -0
  65. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test_ws.py +14 -16
  66. cloudpss-4.5.13/test/test_ws2.py +114 -0
  67. cloudpss-4.5.13/test/test_ws3.py +49 -0
  68. cloudpss-4.1.1b8/cloudpss/dslab/__init__.py +0 -2
  69. cloudpss-4.1.1b8/cloudpss/dslab/dataManageModel.py +0 -275
  70. cloudpss-4.1.1b8/cloudpss/dslab/dslab.py +0 -210
  71. cloudpss-4.1.1b8/cloudpss/dslab/files/__init__.py +0 -2
  72. cloudpss-4.1.1b8/cloudpss/dslab/files/curveData.py +0 -140229
  73. cloudpss-4.1.1b8/cloudpss/dslab/files/files.py +0 -27
  74. cloudpss-4.1.1b8/cloudpss/dslab/financialAnalysisModel.py +0 -137
  75. cloudpss-4.1.1b8/cloudpss/ieslab/IESLabSimulation.py +0 -89
  76. cloudpss-4.1.1b8/cloudpss/ieslab/PlanModel.py +0 -143
  77. cloudpss-4.1.1b8/cloudpss/job/jobMachine.py +0 -11
  78. cloudpss-4.1.1b8/cloudpss/job/jobPolicy.py +0 -129
  79. cloudpss-4.1.1b8/cloudpss/job/jobQueue.py +0 -14
  80. cloudpss-4.1.1b8/cloudpss/job/jobTres.py +0 -6
  81. cloudpss-4.1.1b8/cloudpss/job/view/IESLabSimulationView.py +0 -5
  82. cloudpss-4.1.1b8/cloudpss/job/view/IESLabTypicalDayView.py +0 -27
  83. cloudpss-4.1.1b8/cloudpss/job/view/__init__.py +0 -42
  84. cloudpss-4.1.1b8/cloudpss/model/implements/diagram.py +0 -46
  85. cloudpss-4.1.1b8/cloudpss/runner/DSLabResult.py +0 -92
  86. cloudpss-4.1.1b8/cloudpss/runner/IESLabTypicalDayResult.py +0 -142
  87. cloudpss-4.1.1b8/cloudpss/runner/MessageStreamReceiver.py +0 -193
  88. cloudpss-4.1.1b8/cloudpss/version.py +0 -1
  89. cloudpss-4.1.1b8/test/test-topology.py +0 -26
  90. cloudpss-4.1.1b8/test/testRt copy.py +0 -107
  91. cloudpss-4.1.1b8/test/testSend.py +0 -39
  92. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/README.md +0 -0
  93. {cloudpss-4.1.1b8/cloudpss → cloudpss-4.5.13/cloudpss/asyncio}/job/__init__.py +0 -0
  94. {cloudpss-4.1.1b8/cloudpss → cloudpss-4.5.13/cloudpss/asyncio}/model/__init__.py +0 -0
  95. {cloudpss-4.1.1b8/cloudpss → cloudpss-4.5.13/cloudpss/asyncio}/utils/AsyncIterable.py +0 -0
  96. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/function/__init__.py +0 -0
  97. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/function/function.py +0 -0
  98. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/function/job.py +0 -0
  99. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/model/implements/__init__.py +0 -0
  100. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/model/implements/component.py +0 -0
  101. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/model/implements/implement.py +0 -0
  102. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/project/__init__.py +0 -0
  103. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/project/project.py +0 -0
  104. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/__init__.py +0 -0
  105. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/receiver.py +0 -0
  106. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/storage.py +0 -0
  107. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/runner/transform.py +0 -0
  108. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/utils/__init__.py +0 -0
  109. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/utils/dataEncoder.py +0 -0
  110. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/utils/matlab.py +0 -0
  111. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/utils/yamlLoader.py +0 -0
  112. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss/verify.py +0 -0
  113. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss.egg-info/dependency_links.txt +0 -0
  114. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/cloudpss.egg-info/top_level.txt +0 -0
  115. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/setup.cfg +0 -0
  116. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test-async.py +0 -0
  117. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test-async2.py +0 -0
  118. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test-async3.py +0 -0
  119. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test-sdk.py +0 -0
  120. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test-sdk1.py +0 -0
  121. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test-snapshot.py +0 -0
  122. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test7950.py +0 -0
  123. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/testAsync.py +0 -0
  124. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/testEvent.py +0 -0
  125. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/test_in_new_web_1.py +0 -0
  126. {cloudpss-4.1.1b8 → cloudpss-4.5.13}/test/testb.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: cloudpss
3
- Version: 4.1.1b8
3
+ Version: 4.5.13
4
4
  Summary: cloudpss sdk
5
5
  Home-page: https://www.cloudpss.net
6
6
  Author: cloudpss
@@ -1,5 +1,5 @@
1
1
  # coding=UTF-8
2
- from cloudpss.ieslab import IESLabSimulation, IESLabPlan
2
+ from cloudpss.ieslab import IESLabSimulation, IESLabPlan, IESLabOpt
3
3
  from .verify import setToken
4
4
  from .runner import Runner, Result, EMTResult, PowerFlowResult
5
5
  from .model import Model, ModelRevision, ModelTopology
@@ -9,11 +9,10 @@ from . import function
9
9
  from .job import Job
10
10
  from .function import FunctionExecution
11
11
  from .version import __version__
12
- from .dslab import DSLab
13
12
  __all__ = [
14
13
  'setToken', 'Model', 'ModelRevision', 'ModelTopology', 'Runner', 'Result',
15
14
  'PowerFlowResult', 'EMTResult', 'MatlabDataEncoder', 'DateTimeEncode',
16
- 'function', 'Project', 'currentJob', 'IESLabSimulation', 'IESLabPlan','__version__','Job','DSLab'
15
+ 'function', 'Project', 'currentJob', 'IESLabSimulation', 'IESLabPlan','IESLabOpt','__version__','Job'
17
16
  ]
18
17
 
19
18
 
@@ -0,0 +1,8 @@
1
+ # coding=UTF-8
2
+ from .model import Model, ModelRevision, ModelTopology
3
+ from .job import Job
4
+ from ..verify import setToken
5
+ __all__ = [
6
+ 'Model', 'ModelRevision', 'ModelTopology','Job','setToken'
7
+ ]
8
+
@@ -0,0 +1,116 @@
1
+ from cloudpss.asyncio.job.messageStreamReceiver import MessageStreamReceiver
2
+ from cloudpss.asyncio.job.messageStreamSender import MessageStreamSender
3
+ from cloudpss.asyncio.utils.AsyncIterable import CustomAsyncIterable
4
+ from cloudpss.asyncio.utils.httpAsyncRequest import graphql_request
5
+ from cloudpss.job import Job as JobBase
6
+ from typing import Any, Callable, TypeVar
7
+ F = TypeVar('F', bound=Callable[..., Any])
8
+
9
+ class Job(JobBase):
10
+
11
+ @staticmethod
12
+ async def fetch(id):
13
+ """
14
+ 获取job信息
15
+ """
16
+ if id is None:
17
+ raise Exception("id is None")
18
+
19
+ variables = {"_a": {"id": id}}
20
+
21
+ r = await graphql_request(Job.__jobQuery, variables)
22
+ if "errors" in r:
23
+ raise Exception(r["errors"])
24
+ return Job(**r["data"]["job"])
25
+
26
+ @staticmethod
27
+ def fetchMany(*args):
28
+ """
29
+ 批量获取任务信息
30
+ """
31
+ jobs = CustomAsyncIterable(Job.fetch,*args)
32
+ return jobs
33
+
34
+
35
+ @staticmethod
36
+ async def create(revisionHash, job, config, name=None, rid="", policy=None, **kwargs):
37
+ """
38
+ 创建一个运行任务
39
+
40
+ :params: revision 项目版本号
41
+ :params: job 调用仿真时使用的计算方案,为空时使用项目的第一个计算方案
42
+ :params: config 调用仿真时使用的参数方案,为空时使用项目的第一个参数方案
43
+ :params: name 任务名称,为空时使用项目的参数方案名称和计算方案名称
44
+ :params: rid 项目rid,可为空
45
+
46
+ :return: 返回一个运行实例
47
+
48
+ >>> runner = Runner.runRevision(revision,job,config,'')
49
+ """
50
+
51
+ variables=Job.__createJobVariables(job, config, revisionHash, rid, policy)
52
+ r = await graphql_request(Job.__createJobQuery, variables)
53
+ if "errors" in r:
54
+ raise Exception(r["errors"])
55
+ id = r["data"]["job"]["id"]
56
+ return await Job.fetch(id)
57
+
58
+
59
+ @staticmethod
60
+ async def abort(id, timeout):
61
+ """
62
+ 结束当前运行的算例
63
+
64
+ """
65
+ query = """mutation ($input: AbortJobInput!) {
66
+ job: abortJob(input: $input) {
67
+ id
68
+ status
69
+ }
70
+ }
71
+ """
72
+ variables = {"input": {"id": id, "timeout": timeout}}
73
+ await graphql_request(query, variables)
74
+
75
+ async def result(self, resultType:F)->F:
76
+ """
77
+ 获取当前运行实例的输出
78
+ """
79
+ receiver = await self.read()
80
+ sender = await self.write()
81
+ self._result= resultType(receiver, sender)
82
+ return self._result
83
+
84
+ async def write(self, sender=None, dev=False, **kwargs) -> MessageStreamSender:
85
+ """
86
+ 使用发送器为当前运行实例输入
87
+ """
88
+
89
+ if sender is not None:
90
+ self.__sender = sender
91
+ if self.__sender is None:
92
+ self.__sender = MessageStreamSender(self, dev)
93
+ await self.__sender.connect(**kwargs)
94
+ return self.__sender
95
+
96
+ async def read(self, receiver=None, dev=False, **kwargs)-> MessageStreamReceiver:
97
+ """
98
+ 使用接收器获取当前运行实例的输出
99
+ """
100
+ if receiver is not None:
101
+ self.__receiver = receiver
102
+ if self.__receiver is None:
103
+ self.__receiver = MessageStreamReceiver(self, dev)
104
+ await self.__receiver.connect(**kwargs)
105
+ return self.__receiver
106
+
107
+ async def status(self):
108
+ """
109
+ return: 0: 运行中 1: 运行完成 2: 运行失败
110
+ """
111
+ if self.__receiver is not None:
112
+ return await self.__receiver.status
113
+ # if self.__receiver is None:
114
+ # self.__connect()
115
+ # return 0
116
+ return 0
@@ -0,0 +1,121 @@
1
+ import logging
2
+ import os
3
+ from urllib.parse import urlparse
4
+
5
+ from aiohttp import ClientSession, WSMsgType
6
+ from cloudpss.asyncio.utils.httpAsyncRequest import websocket_connect
7
+ from cloudpss.job.jobReceiver import JobReceiver
8
+ from cloudpss.utils.IO import IO
9
+
10
+
11
+ class MessageStreamReceiver(JobReceiver):
12
+ def __init__(self, job, dev=False):
13
+ super().__init__()
14
+ self.job = job
15
+ self.dev = dev
16
+ self.origin = os.environ.get("CLOUDPSS_API_URL", "https://cloudpss.net/")
17
+
18
+ async def __receive(self):
19
+ """
20
+ 读取消息流中的数据
21
+ """
22
+ msg = await self.ws.receive()
23
+ result=None
24
+ if msg.type == WSMsgType.BINARY:
25
+ result=await self.__on_message(msg.data)
26
+ if msg.type == WSMsgType.TEXT:
27
+ result=await self.__on_message(msg.data)
28
+ elif msg.type == WSMsgType.CLOSE:
29
+ self.__on_close(msg)
30
+ elif msg.type == WSMsgType.CLOSED:
31
+ await self.__on_closed()
32
+ elif msg.type == WSMsgType.ERROR:
33
+ self.__on_error(msg.data)
34
+ return result
35
+
36
+ def __aiter__(self):
37
+ return self
38
+
39
+ async def __anext__(self):
40
+ result = await self.__receive()
41
+ if result is None:
42
+ raise StopAsyncIteration
43
+ return result
44
+
45
+ def __on_close(self, msg,*args, **kwargs):
46
+ if msg is not None and msg.startswith("CMS_NO_STREAM_ID:"):
47
+ self._status = 1
48
+ msg = {
49
+ "type": "log",
50
+ "version": 1,
51
+ "data": {
52
+ "level": "critical",
53
+ "content": "未找到任务的输出流,运行结果可能已被清理。",
54
+ },
55
+ }
56
+ self.messages.append(msg)
57
+ return
58
+
59
+ async def __on_closed(self, *args, **kwargs):
60
+ logging.debug("MessageStreamReceiver close")
61
+ self._status = 1
62
+ msg = {
63
+ "type": "log",
64
+ "verb": "create",
65
+ "version": 1,
66
+ "data": {
67
+ "level": "info",
68
+ "content": "websocket closed",
69
+ },
70
+ }
71
+ self.messages.append(msg)
72
+ await self.session.close()
73
+
74
+ async def __on_message(self, message):
75
+
76
+ data = IO.deserialize(message, "ubjson")
77
+ msg = IO.deserialize(data["data"], "ubjson")
78
+ self.messages.append(msg)
79
+ # print(msg['type'])
80
+ if(msg['type']=='terminate'):
81
+ await self.close(self.ws)
82
+ return msg
83
+
84
+ def __on_error(self, msg,*args, **kwargs):
85
+ logging.debug("MessageStreamReceiver error")
86
+ msg = {
87
+ "type": "log",
88
+ "verb": "create",
89
+ "version": 1,
90
+ "data": {
91
+ "level": "error",
92
+ "content": "websocket error",
93
+ },
94
+ }
95
+ self.messages.append(msg)
96
+
97
+ @property
98
+ async def status(self):
99
+ await self.__receive()
100
+ return self._status
101
+
102
+ async def close(self, ws):
103
+ self._status = 1
104
+ await ws.close()
105
+
106
+ async def connect(self,**kwargs):
107
+ self._status = 0
108
+
109
+ if self.job.output is None:
110
+ raise Exception("id is None")
111
+ u = list(urlparse(self.origin))
112
+ head = "wss" if u[0] == "https" else "ws"
113
+
114
+ path = head + "://" + str(u[1]) + "/api/streams/id/" + self.job.output
115
+ from_=kwargs.get("from",None)
116
+ if from_ is not None:
117
+ path = path + "&from=" + str(from_)
118
+ logging.info(f"MessageStreamReceiver data from websocket: {path}")
119
+
120
+ self.session= ClientSession()
121
+ self.ws= await self.session.ws_connect(path)
@@ -0,0 +1,45 @@
1
+
2
+ import logging
3
+ from typing import IO
4
+ from urllib.parse import urlparse
5
+ import aiohttp
6
+ from cloudpss.job.messageStreamSender import MessageStreamSender as MessageStreamSenderBase
7
+
8
+
9
+ class MessageStreamSender(MessageStreamSenderBase):
10
+
11
+
12
+ async def receive_data(self):
13
+ if self.websocket:
14
+ data = await self.websocket.receive()
15
+ if data.type == aiohttp.WSMsgType.TEXT:
16
+ self.__on_message(data.data)
17
+ elif data.type == aiohttp.WSMsgType.CLOSED:
18
+ self.__on_close()
19
+ elif data.type == aiohttp.WSMsgType.ERROR:
20
+ self.__on_error(data.data)
21
+ else:
22
+ logging.info("WebSocket connection not established")
23
+
24
+ async def connect(self):
25
+ self._status = 0
26
+ if self.job.input is None:
27
+ raise Exception("id is None")
28
+ if self.job.input == "00000000-0000-0000-0000-000000000000":
29
+ return
30
+ u = list(urlparse(self.origin))
31
+ head = "wss" if u[0] == "https" else "ws"
32
+
33
+ path = head + "://" + str(u[1]) + "/api/streams/token/" + self.job.input
34
+ logging.info(f"MessageStreamSender data from websocket: {path}")
35
+ async with aiohttp.ClientSession() as session:
36
+ self.websocket = await session.ws_connect(path)
37
+
38
+ async def write(self, message):
39
+ if self.websocket:
40
+ data = IO.serialize(message, "ubjson", None)
41
+ await self.websocket.send_bytes(data)
42
+ else:
43
+ logging.info("websocket is None")
44
+
45
+
@@ -0,0 +1,257 @@
1
+ import os
2
+ import re
3
+ from cloudpss.asyncio.job.job import Job
4
+ from cloudpss.asyncio.model.revision import ModelRevision
5
+ from cloudpss.asyncio.utils.httpAsyncRequest import graphql_request
6
+ from cloudpss.model.model import Model as ModelBase
7
+ from cloudpss.verify import userName
8
+
9
+
10
+ class Model(ModelBase):
11
+
12
+ def __init__(self, model: dict = {}):
13
+ """
14
+ 项目初始化
15
+ """
16
+ for k, v in model.items():
17
+ if k == "revision":
18
+ if "version" in v and v["version"] < 5:
19
+ self.revision = ModelRevision(v)
20
+ else:
21
+ raise Exception(
22
+ "当前SDK版本(ver 3.X.X)不兼容该项目文件,请先升级项目文件。具体方法:将该项目文件导入至XStudio 3.X.X平台后重新保存至本地后即可。"
23
+ )
24
+
25
+ else:
26
+ self.__dict__[k] = v
27
+ @staticmethod
28
+ async def fetch(rid):
29
+ """
30
+ 获取项目
31
+
32
+ :params rid: 项目 rid
33
+
34
+ :return: 返回一个项目实例
35
+
36
+ >>> model=Model.fetch('model/Demo/test')
37
+
38
+ """
39
+ data = await graphql_request(Model.__model_query, {"rid": rid})
40
+ if "errors" in data:
41
+ raise Exception(data["errors"][0]["message"])
42
+ return Model(data["data"]["model"])
43
+
44
+ async def save(self, key=None):
45
+ """
46
+ 保存/创建项目
47
+
48
+ key 不为空时如果远程存在相同的资源名称时将覆盖远程项目。
49
+ key 为空时如果项目 rid 不存在则抛异常,需要重新设置 key。
50
+ 如果保存时,当前用户不是该项目的拥有者时,将重新创建项目,重建项目时如果参数的 key 为空将使用当前当前项目的 key 作为资源的 key ,当资源的 key 和远程冲突时保存失败
51
+
52
+ :params: model 项目
53
+ :params: key 资源 id 的唯一标识符,
54
+
55
+ :return: 保存成功/保存失败
56
+
57
+ >>> model.save(model)
58
+ model.save(model,'newKey') # 另存为新的项目
59
+
60
+ """
61
+ username = userName()
62
+
63
+ if key is not None:
64
+ matchObj = re.match(r"^[-_A-Za-z0-9]+$", key, re.I | re.S)
65
+ if matchObj:
66
+ self.rid = "model/" + username + "/" + key
67
+ try:
68
+ return await Model.update(self)
69
+ except:
70
+ return await Model.create(self)
71
+ else:
72
+ raise Exception("key 能包含字母数子和下划线")
73
+ else:
74
+ t = "(?<=/)\\S+(?=/)"
75
+ owner = re.search(t, self.rid)
76
+ if owner is None:
77
+ raise Exception("rid 错误,请传入 key")
78
+ elif owner[0] != username:
79
+ rid = re.sub(t, username, self.rid)
80
+ try:
81
+ return await Model.create(self)
82
+ except:
83
+ raise Exception(rid + " 该资源已存在,无法重复创建,请修改 key")
84
+
85
+ return await Model.update(self)
86
+
87
+ @staticmethod
88
+ async def fetchMany(name=None, cursor=[]):
89
+ """
90
+ 获取用户可以运行的项目列表
91
+
92
+ :params name: 查询名称,模糊查询
93
+ :params cursor: 游标
94
+
95
+ :return: 按分页信息返回项目列表
96
+
97
+ >>> data= await Model.fetchMany()
98
+ {
99
+ items: [
100
+ {'rid': 'model/admin/share-test', 'name': '1234', 'description': '1234'}
101
+ ...
102
+ ],
103
+ cursor: ["1699353593000"],
104
+
105
+ }
106
+
107
+
108
+ """
109
+ variables = {
110
+ "cursor": cursor,
111
+ "limit": 10,
112
+ "orderBy": ["updatedAt<"],
113
+ "permissionEveryone": ["b_any", 2**16],
114
+ }
115
+ if name is not None:
116
+ variables["_search"] = name
117
+
118
+ data = await graphql_request(Model.__models_query, {"input": variables})
119
+
120
+ if "errors" in data:
121
+ raise Exception(data["errors"][0]["message"])
122
+
123
+ return data["data"]["models"]
124
+
125
+
126
+ @staticmethod
127
+ async def create(model):
128
+ """
129
+ 新建项目
130
+
131
+ :params: model 项目
132
+
133
+ :return: 保存成功/保存失败
134
+
135
+ >>> Model.create(model)
136
+ 保存成功
137
+ """
138
+ # Model.update(model)
139
+ t = "(?<=/)\\S+(?=/)"
140
+ username = userName()
141
+ owner = re.search(t, model.rid)
142
+
143
+ if owner is None:
144
+ raise Exception("rid 错误,无法保存")
145
+ elif owner[0] != username:
146
+ raise Exception("rid 错误,无法保存")
147
+
148
+ isPublic = model.context.get("auth", "") != "private"
149
+ publicRead = model.context.get("publicRead", "") != False
150
+ auth = (65539 if publicRead else 65537) if isPublic else 0
151
+ revision = await ModelRevision.create(model.revision, model.revision.hash)
152
+
153
+ return await graphql_request(
154
+ Model.__models_query,
155
+ {
156
+ "a": {
157
+ "rid": model.rid,
158
+ "revision": revision["hash"],
159
+ "context": model.context,
160
+ "configs": model.configs,
161
+ "jobs": model.jobs,
162
+ "name": model.name,
163
+ "description": model.description,
164
+ "tags": model.tags,
165
+ "permissions": {
166
+ "moderator": 1,
167
+ "member": 1,
168
+ "everyone": auth,
169
+ },
170
+ }
171
+ },
172
+ )
173
+
174
+
175
+ @staticmethod
176
+ async def update(model):
177
+ """
178
+ 更新项目
179
+
180
+ :params: model 项目
181
+
182
+ :return: 保存成功/保存失败
183
+
184
+ >>> Model.update(model)
185
+ """
186
+
187
+ t = "(?<=/)\\S+(?=/)"
188
+ username = userName()
189
+ owner = re.search(t, model.rid)
190
+
191
+ if owner is None:
192
+ raise Exception("rid 错误,无法保存")
193
+ elif owner[0] != username:
194
+ raise Exception("rid 错误,无法保存")
195
+
196
+
197
+ isPublic = model.context.get("auth", "") != "private"
198
+ isComponent = model.context.get("category", "") == "component"
199
+ publicRead = model.context.get("publicRead", "") != False
200
+ auth = (65539 if publicRead else 65537) if isPublic else 0
201
+ revision = await ModelRevision.create(model.revision, model.revision.hash)
202
+
203
+ xVersion = int(float(os.environ.get("X_CLOUDPSS_VERSION", 4)))
204
+ tags = {"replace": model.tags}
205
+ if xVersion == 3:
206
+ tags = model.tags
207
+
208
+ return await graphql_request(
209
+ Model.__update_model,
210
+ {
211
+ "a": {
212
+ "rid": model.rid,
213
+ "revision": revision["hash"],
214
+ "context": model.context,
215
+ "configs": model.configs,
216
+ "jobs": model.jobs,
217
+ "name": model.name,
218
+ "description": model.description,
219
+ "tags": tags,
220
+ "permissions": {
221
+ "moderator": 1,
222
+ "member": 1,
223
+ "everyone": auth,
224
+ },
225
+ }
226
+ },
227
+ )
228
+
229
+ async def run(self, job=None, config=None, name=None, policy=None,stop_on_entry=None, **kwargs):
230
+ """
231
+
232
+ 调用仿真
233
+
234
+ :params job: 调用仿真时使用的计算方案,不指定将使用算例保存时选中的计算方案
235
+ :params config: 调用仿真时使用的参数方案,不指定将使用算例保存时选中的参数方案
236
+ :params name: 任务名称,为空时使用项目的参数方案名称和计算方案名称
237
+
238
+ :return: 返回一个Job实例
239
+
240
+ >>> job=model.run(job,config,'')
241
+ job
242
+
243
+ """
244
+ if job is None:
245
+ currentJob = self.context["currentJob"]
246
+ job = self.jobs[currentJob]
247
+ if config is None:
248
+ currentConfig = self.context["currentConfig"]
249
+ config = self.configs[currentConfig]
250
+ revision = await self.revision.run(
251
+ job, config, name, self.rid, policy, **kwargs
252
+ )
253
+ if stop_on_entry is not None:
254
+ job['args']['stop_on_entry'] = stop_on_entry
255
+ return await Job.create(
256
+ revision["hash"], job, config, name, self.rid, policy, **kwargs
257
+ )
@@ -0,0 +1,41 @@
1
+ from cloudpss.asyncio.utils.httpAsyncRequest import graphql_request
2
+ from cloudpss.model.revision import ModelRevision as ModelRevisionBase
3
+
4
+
5
+ class ModelRevision(ModelRevisionBase):
6
+
7
+ @staticmethod
8
+ async def create(revision, parentHash=None):
9
+ """
10
+ 创建一个新版本
11
+
12
+ :params: revision 版本数据
13
+
14
+ :return: 项目版本hash
15
+
16
+ >>> ModelRevision.create(model.revision)
17
+ {hash:'4043acbddb9ce0c6174be65573c0380415bc48186c74a459f88865313743230c'}
18
+ """
19
+
20
+ r = revision.toJSON()
21
+ del r['hash']
22
+ variables = {'a': {**r, 'parent': parentHash}}
23
+ r = await graphql_request(ModelRevision.__createModelRevisionQuery, variables)
24
+ if 'errors' in r:
25
+ raise Exception(r['errors'])
26
+ return r['data']['createModelRevision']
27
+
28
+ async def run(self, job, config, name=None, rid='', policy=None, **kwargs):
29
+ """
30
+ 运行某个指定版本的项目
31
+
32
+ :params job: 调用仿真时使用的计算方案,为空时使用项目的第一个计算方案
33
+ :params config: 调用仿真时使用的参数方案,为空时使用项目的第一个参数方案
34
+ :params name: 任务名称,为空时使用项目的参数方案名称和计算方案名称
35
+ :params rid: 项目rid,可为空
36
+
37
+ :return: 返回一个ModelRevision
38
+
39
+ >>> revision.run(revision,job,config,'')
40
+ """
41
+ return await ModelRevision.create(self)
@@ -0,0 +1,34 @@
1
+ from cloudpss.asyncio.utils.httpAsyncRequest import graphql_request
2
+ from cloudpss.model.topology import ModelTopology as ModelTopologyBase
3
+
4
+
5
+ class ModelTopology(ModelTopologyBase):
6
+ @staticmethod
7
+ async def fetch(hash, implementType, config, maximumDepth=None):
8
+ """
9
+ 获取拓扑
10
+
11
+ :params: hash
12
+ :params: implementType 实现类型
13
+ :params: config 参数方案
14
+ :params: maximumDepth 最大递归深度,用于自定义项目中使用 diagram 实现元件展开情况
15
+
16
+ : return: 拓扑实例
17
+
18
+ >>> data = ModelTopology.fetch('','emtp',{})
19
+
20
+ """
21
+ args = {} if config is None else config['args']
22
+ variables = {
23
+ "a": {
24
+ 'hash': hash,
25
+ 'args': args,
26
+ 'acceptImplementType': implementType,
27
+ 'maximumDepth': maximumDepth
28
+ }
29
+ }
30
+ data = await graphql_request(ModelTopology.__modelTopologyQuery, variables)
31
+ if 'errors' in data:
32
+ raise Exception(data['errors'][0]['message'])
33
+
34
+ return ModelTopology(data['data']['modelTopology'])
@@ -0,0 +1,6 @@
1
+
2
+ from .httpAsyncRequest import graphql_request
3
+
4
+ __all__ = [
5
+ 'graphql_request'
6
+ ]
@@ -3,7 +3,7 @@ import os
3
3
  from aiohttp import ClientSession, WSMsgType
4
4
  from urllib.parse import urljoin
5
5
  import logging
6
- from ..version import __version__
6
+ from ...version import __version__
7
7
 
8
8
 
9
9
  def graphql_version_check(uri, response):
@@ -54,7 +54,7 @@ async def fetch_data(method: str, uri, data, baseUrl=None, params={}, **kwargs):
54
54
 
55
55
 
56
56
  # graphql实现方法
57
- async def graphql_fetch(query, variables=None):
57
+ async def graphql_request(query, variables=None):
58
58
  payload = {"query": query, "variables": variables}
59
59
  return await fetch_data("POST", "graphql", data=json.dumps(payload))
60
60