cloudpss 4.1.1b8__py3-none-any.whl → 4.5.0__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 -3
- cloudpss/asyncio/__init__.py +8 -0
- cloudpss/asyncio/job/__init__.py +5 -0
- cloudpss/asyncio/job/job.py +116 -0
- cloudpss/asyncio/job/messageStreamReceiver.py +121 -0
- cloudpss/asyncio/job/messageStreamSender.py +45 -0
- cloudpss/asyncio/model/__init__.py +5 -0
- cloudpss/asyncio/model/model.py +257 -0
- cloudpss/asyncio/model/revision.py +41 -0
- cloudpss/asyncio/model/topology.py +34 -0
- cloudpss/asyncio/utils/__init__.py +6 -0
- cloudpss/{utils → asyncio/utils}/httpAsyncRequest.py +2 -2
- cloudpss/function/functionExecution.py +36 -3
- cloudpss/ieslab/DataManageModel.py +131 -9
- cloudpss/ieslab/EvaluationModel.py +80 -9
- cloudpss/ieslab/IESLabOpt.py +235 -0
- cloudpss/ieslab/IESLabPlan.py +82 -4
- cloudpss/ieslab/IESLabSimulation.py +59 -32
- cloudpss/ieslab/PlanModel.py +276 -33
- cloudpss/ieslab/__init__.py +2 -1
- cloudpss/job/job.py +136 -141
- cloudpss/job/jobReceiver.py +8 -2
- cloudpss/job/messageStreamReceiver.py +42 -99
- cloudpss/job/messageStreamSender.py +5 -42
- cloudpss/job/{view/EMTView.py → result/EMTResult.py} +11 -13
- cloudpss/job/result/IESLabSimulationResult.py +5 -0
- cloudpss/job/result/IESLabTypicalDayResult.py +136 -0
- cloudpss/job/{view/IESView.py → result/IESResult.py} +2 -2
- cloudpss/job/{view/PowerFlowView.py → result/PowerFlowResult.py} +2 -2
- cloudpss/job/result/__init__.py +39 -0
- cloudpss/job/{view/view.py → result/result.py} +37 -8
- cloudpss/model/implements/diagram.py +113 -0
- cloudpss/model/jobDefinitions.py +6 -6
- cloudpss/model/model.py +232 -209
- cloudpss/model/revision.py +30 -35
- cloudpss/model/topology.py +13 -15
- cloudpss/runner/IESLabEvaluationResult.py +14 -6
- cloudpss/runner/IESLabPlanResult.py +91 -35
- cloudpss/runner/IESLabTypicalDayResult.py +62 -50
- cloudpss/runner/MessageStreamReceiver.py +5 -100
- cloudpss/runner/result.py +6 -1
- cloudpss/runner/runner.py +77 -48
- cloudpss/utils/IO.py +1 -1
- cloudpss/utils/graphqlUtil.py +3 -2
- cloudpss/utils/httprequests.py +16 -8
- cloudpss/version.py +1 -1
- {cloudpss-4.1.1b8.dist-info → cloudpss-4.5.0.dist-info}/METADATA +2 -2
- cloudpss-4.5.0.dist-info/RECORD +70 -0
- cloudpss/dslab/__init__.py +0 -2
- cloudpss/dslab/dataManageModel.py +0 -275
- cloudpss/dslab/dslab.py +0 -210
- cloudpss/dslab/files/__init__.py +0 -2
- cloudpss/dslab/files/curveData.py +0 -140229
- cloudpss/dslab/files/files.py +0 -27
- cloudpss/dslab/financialAnalysisModel.py +0 -137
- cloudpss/job/jobMachine.py +0 -11
- cloudpss/job/jobPolicy.py +0 -129
- cloudpss/job/jobQueue.py +0 -14
- cloudpss/job/jobTres.py +0 -6
- cloudpss/job/view/IESLabSimulationView.py +0 -5
- cloudpss/job/view/IESLabTypicalDayView.py +0 -27
- cloudpss/job/view/__init__.py +0 -42
- cloudpss/runner/DSLabResult.py +0 -92
- cloudpss-4.1.1b8.dist-info/RECORD +0 -71
- /cloudpss/{utils → asyncio/utils}/AsyncIterable.py +0 -0
- {cloudpss-4.1.1b8.dist-info → cloudpss-4.5.0.dist-info}/WHEEL +0 -0
- {cloudpss-4.1.1b8.dist-info → cloudpss-4.5.0.dist-info}/top_level.txt +0 -0
| @@ -9,54 +9,51 @@ class IESLabTypicalDayResult(Result): | |
| 9 9 | 
             
                    Result.__init__(self, *args, **kwargs)
         | 
| 10 10 | 
             
                    self.__plotIndex = 0
         | 
| 11 11 | 
             
                    self.__typicalIndex = 0
         | 
| 12 | 
            -
                    self.__type_list =[' | 
| 13 | 
            -
                    self. | 
| 14 | 
            -
                    for i in range(12):
         | 
| 15 | 
            -
                        self.result['TypicalMonth'].append({'月份': int, '持续天数': [],'电负荷': [], '热负荷': [],'冷负荷':[],'总辐射': [],'直射辐射': [],'散射辐射': [],'天顶角': [],
         | 
| 16 | 
            -
                                                            '环境温度': [], '土壤温度': [], '建筑物高度风速': [], '风机高度风速': [],'10m风速': [], '50m风速': [] })
         | 
| 17 | 
            -
                    
         | 
| 12 | 
            +
                    self.__type_list =['总辐射','散射辐射', '直射辐射','天顶角', '环境温度', '湿球温度','土壤温度', '10m风速', '50m风速','电负荷', '热负荷','冷负荷','氢负荷']
         | 
| 13 | 
            +
                    self.__map_load = { 'maxElectricalLoad':'电负荷', 'maxHeatLoad':'热负荷','maxCoolLoad':'冷负荷','maxHydrogenLoad':'氢负荷' }
         | 
| 14 | 
            +
                    self.result = {'TypicalMonth': [{'月份': int,'持续天数': [],**{key: [] for key in self.__type_list}} for i in range(12)],'TypicalDay': []}
         | 
| 18 15 |  | 
| 19 16 | 
             
                def __readPlotResult(self):
         | 
| 20 17 | 
             
                    length = self.db.getMessageLength()
         | 
| 21 18 | 
             
                    if (length > self.__plotIndex):
         | 
| 22 19 | 
             
                        for num in range(self.__plotIndex, length):# update TypicalMonth
         | 
| 23 20 | 
             
                            val = self.db.getMessage(num)
         | 
| 24 | 
            -
                            if val['type'] == 'plot' | 
| 25 | 
            -
                                 | 
| 26 | 
            -
                                 | 
| 27 | 
            -
                                 | 
| 28 | 
            -
                                 | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
                                 | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 21 | 
            +
                            if val['type'] == 'plot':# 每个月各类型数据的各个典型日的数据,由于部分月份可能没有电冷热负荷,某月的某个典型日可能缺少冷热负荷
         | 
| 22 | 
            +
                                key_re = re.split('-month',val['key'])#格式为:散射辐射-month1,re后分别为类型和月份
         | 
| 23 | 
            +
                                typical_month_m = self.result['TypicalMonth'][int(key_re[1])-1]
         | 
| 24 | 
            +
                                typical_month_m['月份'] = int(key_re[1])
         | 
| 25 | 
            +
                                val_data_traces = val['data']['traces']
         | 
| 26 | 
            +
                                #val['data']['traces'][i]['name']格式为:典型日1-共31天,re正则后[0]为典型日顺序,[1]为持续天数
         | 
| 27 | 
            +
                                typicalNum = int(re.findall('\d+',val_data_traces[-1]['name'])[0])
         | 
| 28 | 
            +
                                for i in range(typicalNum):#取该类型的最后一个典型日顺序,当该类型缺少后排典型日时,小于实际典型日数量
         | 
| 29 | 
            +
                                    typical_month_m[key_re[0]].append([])
         | 
| 30 | 
            +
                                    if key_re[0]  == '环境温度':#各类版本气象数据均有环境温度数据,其典型日数量为实际数量
         | 
| 31 | 
            +
                                        typical_month_m['持续天数'].append(int(re.findall('\d+',val_data_traces[i]['name'])[1]))
         | 
| 32 | 
            +
                                # 当前排典型日缺少数据时,该类型数据为空list[];当后排典型日缺少数据时,该类型数据为空
         | 
| 33 | 
            +
                                for i in range(len(val_data_traces)):
         | 
| 34 | 
            +
                                    typical_month_m[key_re[0]][int(re.findall('\d+',val_data_traces[i]['name'])[0])-1] = copy.deepcopy(val_data_traces[i]['y'])            
         | 
| 35 | 
            +
                        
         | 
| 38 36 | 
             
                        # update TypicalDay based on TypicalMonth
         | 
| 39 37 | 
             
                        for m in range(12):
         | 
| 40 | 
            -
                             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 43 | 
            -
             | 
| 44 | 
            -
                                 | 
| 45 | 
            -
                                self.result['TypicalDay'][ | 
| 46 | 
            -
                                 | 
| 47 | 
            -
                                 | 
| 48 | 
            -
             | 
| 49 | 
            -
             | 
| 50 | 
            -
             | 
| 51 | 
            -
                                    if  | 
| 52 | 
            -
                                         | 
| 53 | 
            -
                                if self.result['TypicalMonth'][m]['冷负荷']:
         | 
| 54 | 
            -
                                    if self.result['TypicalMonth'][m]['冷负荷'][i]:
         | 
| 55 | 
            -
                                        self.result['TypicalDay'][-1]['info']['maxCoolLoad'] = max(self.result['TypicalMonth'][m]['冷负荷'][i])
         | 
| 38 | 
            +
                            typical_month_m = self.result['TypicalMonth'][m]
         | 
| 39 | 
            +
                            typical_month_m_day = len(typical_month_m['持续天数'])
         | 
| 40 | 
            +
                            for i in range(typical_month_m_day):
         | 
| 41 | 
            +
                                self.result['TypicalDay'].append({'info':{'typicalDayID': int, 'name': str, 'duration': int, **{key: 0.0 for key in self.__map_load}},
         | 
| 42 | 
            +
                                'data': {**{key: [] for key in self.__type_list}}})
         | 
| 43 | 
            +
                                typical_day_index = self.result['TypicalDay'][self.__typicalIndex]
         | 
| 44 | 
            +
                                typical_day_index['info']['typicalDayID'] = self.__typicalIndex
         | 
| 45 | 
            +
                                typical_day_index['info']['name'] = str(m+1) + '月典型日' + str(i+1)
         | 
| 46 | 
            +
                                typical_day_index['info']['duration'] = typical_month_m['持续天数'][i]
         | 
| 47 | 
            +
                                for key,value in self.__map_load.items():
         | 
| 48 | 
            +
                                    # 分别处理该典型日无此类型负荷数据,缺少后序典型日,缺少前序典型日的情况
         | 
| 49 | 
            +
                                    if typical_month_m.get(value) and i <len(typical_month_m[value]) and len(typical_month_m[value][i]):
         | 
| 50 | 
            +
                                        typical_day_index['info'][key] = max(typical_month_m[value][i])
         | 
| 56 51 | 
             
                                for type_i in self.__type_list:
         | 
| 57 | 
            -
                                     | 
| 58 | 
            -
             | 
| 52 | 
            +
                                    # 某月冷热负荷可能缺少后续典型日数据
         | 
| 53 | 
            +
                                    if typical_month_m[type_i] and i < len(typical_month_m[type_i]):
         | 
| 54 | 
            +
                                        typical_day_index['data'][type_i] = typical_month_m[type_i][i]
         | 
| 59 55 | 
             
                                self.__typicalIndex += 1
         | 
| 56 | 
            +
                        self.__plotIndex = length
         | 
| 60 57 |  | 
| 61 58 | 
             
                def GetTypical(self):
         | 
| 62 59 | 
             
                    '''
         | 
| @@ -71,7 +68,7 @@ class IESLabTypicalDayResult(Result): | |
| 71 68 |  | 
| 72 69 | 
             
                def GetTypicalDayNum(self):
         | 
| 73 70 | 
             
                    '''
         | 
| 74 | 
            -
                        获取当前result | 
| 71 | 
            +
                        获取当前result的典型日总数
         | 
| 75 72 |  | 
| 76 73 | 
             
                        :return: int类型,代表典型日数量
         | 
| 77 74 | 
             
                    '''
         | 
| @@ -82,25 +79,33 @@ class IESLabTypicalDayResult(Result): | |
| 82 79 | 
             
                    '''
         | 
| 83 80 | 
             
                        获取dayID对应典型日的基础信息
         | 
| 84 81 |  | 
| 85 | 
            -
                        :params: dayID int类型,表示典型日的ID,数值位于 0 | 
| 82 | 
            +
                        :params: dayID int类型,表示典型日的ID,数值位于 [0,典型日总数-1] 中
         | 
| 86 83 |  | 
| 87 84 | 
             
                        :return: dict类型,代表典型日的基础信息,包括典型日所代表的日期范围、典型日的名称等
         | 
| 88 85 | 
             
                    '''
         | 
| 89 86 | 
             
                    self.__readPlotResult()
         | 
| 90 | 
            -
                     | 
| 87 | 
            +
                    try:
         | 
| 88 | 
            +
                        return self.result['TypicalDay'][dayID]['info']
         | 
| 89 | 
            +
                    except:
         | 
| 90 | 
            +
                        raise Exception('未查询到该数据')
         | 
| 91 91 |  | 
| 92 92 |  | 
| 93 93 | 
             
                def GetTypicalDayCurve(self,dayID, dataType):
         | 
| 94 94 | 
             
                    '''
         | 
| 95 95 | 
             
                        获取dayID对应典型日下dataType参数的时序曲线
         | 
| 96 96 |  | 
| 97 | 
            -
                        :params: dayID int类型,表示典型日的ID,数值位于 0 | 
| 98 | 
            -
                        :params: dataType enum | 
| 97 | 
            +
                        :params: dayID int类型,表示典型日的ID,数值位于 [0,典型日总数-1] 中
         | 
| 98 | 
            +
                        :params: dataType enum类型,标识典型场景的数据类型
         | 
| 99 | 
            +
                        有总辐射、直射辐照、散射辐照、环境温度、湿球温度、土壤温度、10m风速、50m风速、电负荷、热负荷、冷负荷和氢负荷等类型,以该典型场景实际包含的类型为准
         | 
| 99 100 |  | 
| 100 101 | 
             
                        :return: list<float>类型,代表以1h为时间间隔的该参数的日内时序曲线
         | 
| 101 102 | 
             
                    '''
         | 
| 102 103 | 
             
                    self.__readPlotResult()
         | 
| 103 | 
            -
                     | 
| 104 | 
            +
                    try:
         | 
| 105 | 
            +
                        return self.result['TypicalDay'][dayID]['data'][dataType]
         | 
| 106 | 
            +
                    except:
         | 
| 107 | 
            +
                        raise Exception('未查询到该数据')
         | 
| 108 | 
            +
                    
         | 
| 104 109 |  | 
| 105 110 |  | 
| 106 111 | 
             
                def GetTypicalMonth(self):
         | 
| @@ -114,11 +119,11 @@ class IESLabTypicalDayResult(Result): | |
| 114 119 | 
             
                    self.__readPlotResult()
         | 
| 115 120 | 
             
                    return self.result['TypicalMonth']
         | 
| 116 121 |  | 
| 117 | 
            -
                def  | 
| 122 | 
            +
                def GetTypicalMonthID(self,monthID):
         | 
| 118 123 | 
             
                    '''
         | 
| 119 124 | 
             
                        获取第monthID月各类型的典型日数据
         | 
| 120 125 |  | 
| 121 | 
            -
                        >>> result. | 
| 126 | 
            +
                        >>> result.GetTypicalMonthID()
         | 
| 122 127 |  | 
| 123 128 | 
             
                        :params: monthID int类型,表示典型月的ID,数值位于 1-12 之间
         | 
| 124 129 |  | 
| @@ -126,17 +131,24 @@ class IESLabTypicalDayResult(Result): | |
| 126 131 | 
             
                        {...}
         | 
| 127 132 | 
             
                    '''
         | 
| 128 133 | 
             
                    self.__readPlotResult()
         | 
| 129 | 
            -
                     | 
| 134 | 
            +
                    try:
         | 
| 135 | 
            +
                        return self.result['TypicalMonth'][monthID-1]
         | 
| 136 | 
            +
                    except:
         | 
| 137 | 
            +
                        raise Exception('未查询到该数据')
         | 
| 130 138 |  | 
| 131 139 |  | 
| 132 140 | 
             
                def GetTypicalMonthCurve(self,monthID, dataType):
         | 
| 133 141 | 
             
                    '''
         | 
| 134 | 
            -
                        获取 | 
| 142 | 
            +
                        获取monthID对应典型日下dataType参数的时序曲线
         | 
| 135 143 |  | 
| 136 144 | 
             
                        :params: monthID int类型,表示典型月的ID,数值位于 1-12 之间
         | 
| 137 | 
            -
                        :params: dataType enum | 
| 145 | 
            +
                        :params: dataType enum类型,标识典型场景的数据类型
         | 
| 146 | 
            +
                        有总辐射、直射辐照、散射辐照、环境温度、湿球温度、土壤温度、10m风速、50m风速、电负荷、热负荷、冷负荷和氢负荷等类型,以该典型场景实际包含的类型为准
         | 
| 138 147 |  | 
| 139 148 | 
             
                        :return: list<list>类型,代表以1h为时间间隔的该参数的典型日内时序曲线
         | 
| 140 149 | 
             
                    '''
         | 
| 141 150 | 
             
                    self.__readPlotResult()
         | 
| 142 | 
            -
                     | 
| 151 | 
            +
                    try:
         | 
| 152 | 
            +
                        return self.result['TypicalMonth'][monthID-1][dataType]
         | 
| 153 | 
            +
                    except:
         | 
| 154 | 
            +
                        raise Exception('未查询到该数据')        
         | 
| @@ -19,7 +19,7 @@ class Message(object): | |
| 19 19 | 
             
            class MessageStreamReceiver(object):
         | 
| 20 20 | 
             
                """消息流读取函数结果"""
         | 
| 21 21 |  | 
| 22 | 
            -
                def __init__(self, id, db):
         | 
| 22 | 
            +
                def __init__(self, id, db, **kwargs):
         | 
| 23 23 | 
             
                    self.origin = os.environ.get('CLOUDPSS_API_URL',
         | 
| 24 24 | 
             
                                                 'https://cloudpss.net/')
         | 
| 25 25 | 
             
                    self.id = id
         | 
| @@ -28,102 +28,6 @@ class MessageStreamReceiver(object): | |
| 28 28 | 
             
                    self.error = None
         | 
| 29 29 | 
             
                    self.isOpen = False
         | 
| 30 30 |  | 
| 31 | 
            -
                def create(self, type, comment=None, durability=1):
         | 
| 32 | 
            -
                    """
         | 
| 33 | 
            -
                    创建消息流
         | 
| 34 | 
            -
                    type: 消息流类型 'object' or 'binary'
         | 
| 35 | 
            -
                    comment: 消息流描述
         | 
| 36 | 
            -
                    durability: 消息流的数据将在多少天后被删除,其取值范围从 0 ~ MAX_DURABILITY
         | 
| 37 | 
            -
                    MAX_DURABILITY 默认为20
         | 
| 38 | 
            -
                    """
         | 
| 39 | 
            -
                    param = {}
         | 
| 40 | 
            -
                    if type != 'object' and type != 'binary':
         | 
| 41 | 
            -
                        raise Exception('type must be object or binary')
         | 
| 42 | 
            -
                    param['type'] = type
         | 
| 43 | 
            -
                    param['comment'] = comment
         | 
| 44 | 
            -
                    param['durability'] = durability
         | 
| 45 | 
            -
                    r = requests.post(self.origin + 'api/streams', json=param)
         | 
| 46 | 
            -
                    r.raise_for_status()
         | 
| 47 | 
            -
                    res = r.json()
         | 
| 48 | 
            -
                    print(res)
         | 
| 49 | 
            -
                    message = Message(res['id'], res['token'])
         | 
| 50 | 
            -
                    return message
         | 
| 51 | 
            -
             | 
| 52 | 
            -
                def createBulk(self, param):
         | 
| 53 | 
            -
                    """
         | 
| 54 | 
            -
                    批量创建消息流
         | 
| 55 | 
            -
                    param: [{ "type": "{{type}}", "comment": "{{comment}}" , "durability": {{durability}}, "volume": {{volume}} }, ... ]
         | 
| 56 | 
            -
                    type: 消息流类型 'object' or 'binary'
         | 
| 57 | 
            -
                    comment: 消息流描述
         | 
| 58 | 
            -
                    durability: 消息流的数据将在多少天后被删除,其取值范围从 0 ~ MAX_DURABILITY
         | 
| 59 | 
            -
                    MAX_DURABILITY 默认为20
         | 
| 60 | 
            -
             | 
| 61 | 
            -
                    状态码说明:
         | 
| 62 | 
            -
                    201 返回流信息数组
         | 
| 63 | 
            -
                    400 不支持的 type,或其他输入错误
         | 
| 64 | 
            -
                    """
         | 
| 65 | 
            -
                    r = requests.post(self.origin + 'api/streams/bulk', json=param)
         | 
| 66 | 
            -
                    r.raise_for_status()
         | 
| 67 | 
            -
                    res = r.json()
         | 
| 68 | 
            -
                    messages = []
         | 
| 69 | 
            -
                    for item in res:
         | 
| 70 | 
            -
                        message = Message(item['id'], item['token'])
         | 
| 71 | 
            -
                        messages.append(message)
         | 
| 72 | 
            -
                    return messages
         | 
| 73 | 
            -
             | 
| 74 | 
            -
                def info(self, id):
         | 
| 75 | 
            -
                    """
         | 
| 76 | 
            -
                    获取消息流信息
         | 
| 77 | 
            -
                    """
         | 
| 78 | 
            -
                    if id is None:
         | 
| 79 | 
            -
                        raise Exception('id is None')
         | 
| 80 | 
            -
                    r = requests.get(self.origin + 'api/streams/id/' + id + '/info')
         | 
| 81 | 
            -
                    r.raise_for_status()
         | 
| 82 | 
            -
                    return r.json()
         | 
| 83 | 
            -
             | 
| 84 | 
            -
                def infoByToken(self, token):
         | 
| 85 | 
            -
                    """
         | 
| 86 | 
            -
                    获取消息流信息
         | 
| 87 | 
            -
                    相较于id获取消息流信息,token能够额外获取到handler的信息
         | 
| 88 | 
            -
                    """
         | 
| 89 | 
            -
                    if token is None:
         | 
| 90 | 
            -
                        raise Exception('token is None')
         | 
| 91 | 
            -
                    r = requests.get(self.origin + 'api/streams/token/' + token + '/info')
         | 
| 92 | 
            -
                    r.raise_for_status()
         | 
| 93 | 
            -
                    return r.json()
         | 
| 94 | 
            -
             | 
| 95 | 
            -
                def freeze(self, token):
         | 
| 96 | 
            -
                    """
         | 
| 97 | 
            -
                    冻结消息流
         | 
| 98 | 
            -
             | 
| 99 | 
            -
                    状态码说明:
         | 
| 100 | 
            -
                    201 冻结成功
         | 
| 101 | 
            -
                    204 流已经被冻结
         | 
| 102 | 
            -
                    409 流正在活动中
         | 
| 103 | 
            -
                    404 未找到对应流
         | 
| 104 | 
            -
                    """
         | 
| 105 | 
            -
                    if token is None:
         | 
| 106 | 
            -
                        raise Exception('token is None')
         | 
| 107 | 
            -
                    r = requests.put(self.origin + 'api/streams/token/' + token +
         | 
| 108 | 
            -
                                     '/freeze')
         | 
| 109 | 
            -
                    r.raise_for_status()
         | 
| 110 | 
            -
                    return r.status_code
         | 
| 111 | 
            -
             | 
| 112 | 
            -
                def delete(self, token):
         | 
| 113 | 
            -
                    """
         | 
| 114 | 
            -
                    删除消息流
         | 
| 115 | 
            -
             | 
| 116 | 
            -
                    状态码说明:
         | 
| 117 | 
            -
                    204 删除成功
         | 
| 118 | 
            -
                    409 流正在活动中
         | 
| 119 | 
            -
                    404 未找到对应流
         | 
| 120 | 
            -
                    """
         | 
| 121 | 
            -
                    if token is None:
         | 
| 122 | 
            -
                        raise Exception('token is None')
         | 
| 123 | 
            -
                    r = requests.delete(self.origin + 'api/streams/token/' + token)
         | 
| 124 | 
            -
                    r.raise_for_status()
         | 
| 125 | 
            -
                    return r.status_code
         | 
| 126 | 
            -
             | 
| 127 31 | 
             
                def receive(self, id, fr0m, on_open, on_message, on_error, on_close):
         | 
| 128 32 | 
             
                    """
         | 
| 129 33 | 
             
                    读取消息流中的数据
         | 
| @@ -142,13 +46,13 @@ class MessageStreamReceiver(object): | |
| 142 46 | 
             
                    path = head + '://' + str(u[1]) + '/api/streams/id/' + id
         | 
| 143 47 | 
             
                    if fr0m is not None:
         | 
| 144 48 | 
             
                        path = path + '&from=' + str(fr0m)
         | 
| 145 | 
            -
                    ws = websocket.WebSocketApp(path,
         | 
| 49 | 
            +
                    self.ws = websocket.WebSocketApp(path,
         | 
| 146 50 | 
             
                                                on_open=on_open,
         | 
| 147 51 | 
             
                                                on_message=on_message,
         | 
| 148 52 | 
             
                                                on_error=on_error,
         | 
| 149 53 | 
             
                                                on_close=on_close)
         | 
| 150 | 
            -
                    ws.run_forever()
         | 
| 151 | 
            -
                    return ws
         | 
| 54 | 
            +
                    self.ws.run_forever()
         | 
| 55 | 
            +
                    return self.ws
         | 
| 152 56 |  | 
| 153 57 | 
             
                ###下面是兼容Receiver部分功能实现
         | 
| 154 58 | 
             
                def on_message(self, ws, message):
         | 
| @@ -182,6 +86,7 @@ class MessageStreamReceiver(object): | |
| 182 86 |  | 
| 183 87 | 
             
                def close(self, ws):
         | 
| 184 88 | 
             
                    ws.close()
         | 
| 89 | 
            +
                    self._status = 1
         | 
| 185 90 |  | 
| 186 91 | 
             
                def status(self):
         | 
| 187 92 | 
             
                    return self._status
         | 
    
        cloudpss/runner/result.py
    CHANGED
    
    | @@ -84,8 +84,13 @@ class Result(object): | |
| 84 84 | 
             
                def __deepModify(self, dict1, dict2):
         | 
| 85 85 |  | 
| 86 86 | 
             
                    for key, val in dict1.items():
         | 
| 87 | 
            +
                        
         | 
| 88 | 
            +
                            
         | 
| 87 89 | 
             
                        if type(val) is dict:
         | 
| 88 | 
            -
                             | 
| 90 | 
            +
                            if type(dict2) is dict and dict2.get(key, None) is None:
         | 
| 91 | 
            +
                                dict2[key] = val
         | 
| 92 | 
            +
                            else:
         | 
| 93 | 
            +
                                self.__deepModify(val, dict2[key])
         | 
| 89 94 | 
             
                        else:
         | 
| 90 95 | 
             
                            dict2[key] = val
         | 
| 91 96 |  | 
    
        cloudpss/runner/runner.py
    CHANGED
    
    | @@ -10,13 +10,12 @@ from cloudpss.utils.graphqlUtil import graphql_request | |
| 10 10 | 
             
            from .receiver import Receiver
         | 
| 11 11 | 
             
            from .MessageStreamReceiver import MessageStreamReceiver
         | 
| 12 12 | 
             
            from .result import IESLabSimulationResult, PowerFlowResult, EMTResult, Result, IESResult
         | 
| 13 | 
            -
            from .IESLabPlanResult import IESLabPlanResult
         | 
| 14 | 
            -
            from .IESLabEvaluationResult import IESLabEvaluationResult
         | 
| 13 | 
            +
            from .IESLabPlanResult import IESLabPlanResult, IESLabOptResult
         | 
| 14 | 
            +
            from .IESLabEvaluationResult import IESLabEvaluationResult, IESLabPlanEvaluationResult, IESLabOptEvaluationResult
         | 
| 15 15 | 
             
            from .IESLabTypicalDayResult import IESLabTypicalDayResult
         | 
| 16 16 | 
             
            from .storage import Storage
         | 
| 17 17 | 
             
            from ..utils import request
         | 
| 18 | 
            -
            from typing import | 
| 19 | 
            -
            from .DSLabResult import DSLabResult
         | 
| 18 | 
            +
            from typing import TypeVar, Generic
         | 
| 20 19 | 
             
            import re
         | 
| 21 20 |  | 
| 22 21 | 
             
            RECEIVER = {
         | 
| @@ -28,11 +27,12 @@ T = TypeVar('T', Result, EMTResult, PowerFlowResult, IESResult, | |
| 28 27 |  | 
| 29 28 | 
             
            IES_LAB_RESULT = {
         | 
| 30 29 | 
             
                'function/ieslab/plan': IESLabPlanResult,
         | 
| 31 | 
            -
                'function/ieslab/evaluation':  | 
| 30 | 
            +
                'function/ieslab/evaluation': IESLabPlanEvaluationResult,
         | 
| 32 31 | 
             
            }
         | 
| 33 32 |  | 
| 34 | 
            -
             | 
| 35 | 
            -
                'function/ieslab/ | 
| 33 | 
            +
            IES_LAB_OPT_RESULT = {
         | 
| 34 | 
            +
                'function/ieslab/plan': IESLabOptResult,
         | 
| 35 | 
            +
                'function/ieslab/evaluation': IESLabOptEvaluationResult,
         | 
| 36 36 | 
             
            }
         | 
| 37 37 |  | 
| 38 38 | 
             
            RESULT_DB = {
         | 
| @@ -48,12 +48,12 @@ RESULT_DB = { | |
| 48 48 | 
             
                'function/ies/ies-gmm':IESLabTypicalDayResult,
         | 
| 49 49 | 
             
                'function/CloudPSS/ieslab-simulation': IESLabSimulationResult,
         | 
| 50 50 | 
             
                'function/CloudPSS/ieslab-gmm':IESLabTypicalDayResult,
         | 
| 51 | 
            +
                'function/CloudPSS/ieslab-gmm-opt':IESLabTypicalDayResult,
         | 
| 51 52 | 
             
                'function/CloudPSS/ieslab-optimization': IESResult,
         | 
| 52 53 | 
             
            }
         | 
| 53 54 |  | 
| 54 55 | 
             
            @deprecated(version='4.0', reason="该类将在 6.0 版本移除,请使用 Job 类代替")
         | 
| 55 56 | 
             
            class Runner(Generic[T]):
         | 
| 56 | 
            -
             | 
| 57 57 | 
             
                def __init__(self, id,taskId, name, job, config, revision, modelRid, policy,
         | 
| 58 58 | 
             
                             **kwargs):
         | 
| 59 59 | 
             
                    self.id = id
         | 
| @@ -81,6 +81,7 @@ class Runner(Generic[T]): | |
| 81 81 | 
             
                    """
         | 
| 82 82 | 
             
                    if self.receiver is None:
         | 
| 83 83 | 
             
                        raise Exception('not find receiver')
         | 
| 84 | 
            +
                    time.sleep(0)
         | 
| 84 85 | 
             
                    return self.receiver.status()
         | 
| 85 86 |  | 
| 86 87 | 
             
                def __listen(self, **kwargs):
         | 
| @@ -103,7 +104,6 @@ class Runner(Generic[T]): | |
| 103 104 |  | 
| 104 105 | 
             
                    """
         | 
| 105 106 | 
             
                    self.abort(0)
         | 
| 106 | 
            -
                
         | 
| 107 107 | 
             
                def abort(self,timeout=3):
         | 
| 108 108 | 
             
                    """
         | 
| 109 109 | 
             
                    结束当前运行的算例
         | 
| @@ -125,6 +125,55 @@ class Runner(Generic[T]): | |
| 125 125 | 
             
                    graphql_request(query, variables)
         | 
| 126 126 |  | 
| 127 127 |  | 
| 128 | 
            +
                @staticmethod
         | 
| 129 | 
            +
                def __createJobVariables(job, config, revisionHash, rid, policy, **kwargs):
         | 
| 130 | 
            +
                    # 处理policy字段
         | 
| 131 | 
            +
                    if policy is None:
         | 
| 132 | 
            +
                        policy = {}
         | 
| 133 | 
            +
                        if policy.get("tres", None) is None:
         | 
| 134 | 
            +
                            policy["tres"] = {}
         | 
| 135 | 
            +
                        policy["queue"] = job["args"].get("@queue", 1)
         | 
| 136 | 
            +
                        policy["priority"] = job["args"].get("@priority", 0)
         | 
| 137 | 
            +
                        tres = {"cpu": 1, "ecpu": 0, "mem": 0}
         | 
| 138 | 
            +
                        tresStr = job["args"].get("@tres", "")
         | 
| 139 | 
            +
                        for t in re.split("\s+", tresStr):
         | 
| 140 | 
            +
                            if t == "":
         | 
| 141 | 
            +
                                continue
         | 
| 142 | 
            +
                            k, v = t.split("=")
         | 
| 143 | 
            +
                            tres[k] = float(v)  # type: ignore
         | 
| 144 | 
            +
                        policy["tres"] = tres
         | 
| 145 | 
            +
                    function = job["rid"].replace("job-definition/cloudpss/", "function/CloudPSS/")
         | 
| 146 | 
            +
                    implement = kwargs.get("implement", None)
         | 
| 147 | 
            +
                    debug = job["args"].get("@debug", None )
         | 
| 148 | 
            +
                    debugargs={}
         | 
| 149 | 
            +
                    if debug is not None:
         | 
| 150 | 
            +
                        t= [ i.split('=') for i in re.split(r'\s+',debug) if i.find('=')>0]
         | 
| 151 | 
            +
                        for i in t:
         | 
| 152 | 
            +
                            debugargs[i[0]]=i[1]
         | 
| 153 | 
            +
                    
         | 
| 154 | 
            +
                    context= [
         | 
| 155 | 
            +
                        function,
         | 
| 156 | 
            +
                        rid,
         | 
| 157 | 
            +
                        f"model/@sdk/{str(int(time.time() * random.random()))}",
         | 
| 158 | 
            +
                    ]
         | 
| 159 | 
            +
                    
         | 
| 160 | 
            +
                    PARENT_JOB_ID =kwargs.get("PARENT_JOB_ID",None)
         | 
| 161 | 
            +
                    if PARENT_JOB_ID is not None:
         | 
| 162 | 
            +
                        context.append(f"job/parent/{PARENT_JOB_ID}")
         | 
| 163 | 
            +
                    variables = {
         | 
| 164 | 
            +
                        "input": {
         | 
| 165 | 
            +
                            "args": {
         | 
| 166 | 
            +
                                **job["args"],
         | 
| 167 | 
            +
                                "_ModelRevision": revisionHash,
         | 
| 168 | 
            +
                                "_ModelArgs": config["args"],
         | 
| 169 | 
            +
                                "implement":implement
         | 
| 170 | 
            +
                            },
         | 
| 171 | 
            +
                            "context": context,
         | 
| 172 | 
            +
                            "policy": policy,
         | 
| 173 | 
            +
                            "debug":debugargs
         | 
| 174 | 
            +
                        }
         | 
| 175 | 
            +
                    }
         | 
| 176 | 
            +
                    return variables
         | 
| 128 177 | 
             
                @staticmethod
         | 
| 129 178 | 
             
                def create(revisionHash,
         | 
| 130 179 | 
             
                           job,
         | 
| @@ -147,41 +196,9 @@ class Runner(Generic[T]): | |
| 147 196 | 
             
                        >>> runner = Runner.runRevision(revision,job,config,'')
         | 
| 148 197 | 
             
                    '''
         | 
| 149 198 |  | 
| 150 | 
            -
                    #处理policy字段
         | 
| 151 | 
            -
                    if policy is None:
         | 
| 152 | 
            -
                        policy = {}
         | 
| 153 | 
            -
                        if policy.get('tres', None) is None:
         | 
| 154 | 
            -
                            policy['tres'] = {}
         | 
| 155 | 
            -
                        policy['queue'] = job['args'].get('@queue', 1)
         | 
| 156 | 
            -
                        policy['priority'] = job['args'].get('@priority', 0)
         | 
| 157 | 
            -
                        tres = {'cpu': 1, 'ecpu': 0, 'mem': 0}
         | 
| 158 | 
            -
                        tresStr = job['args'].get('@tres', '')
         | 
| 159 | 
            -
                        for t in re.split('\s+', tresStr):
         | 
| 160 | 
            -
                            if t == '':
         | 
| 161 | 
            -
                                continue
         | 
| 162 | 
            -
                            k, v = t.split('=')
         | 
| 163 | 
            -
                            tres[k] = float(v)  #type: ignore
         | 
| 164 | 
            -
                        policy['tres'] = tres
         | 
| 165 199 |  | 
| 166 200 | 
             
                    query = '''mutation($input:CreateJobInput!){job:createJob(input:$input){id input output status position}}'''
         | 
| 167 | 
            -
                     | 
| 168 | 
            -
                                                  'function/CloudPSS/')
         | 
| 169 | 
            -
                    variables = {
         | 
| 170 | 
            -
                        'input': {
         | 
| 171 | 
            -
                            "args":
         | 
| 172 | 
            -
                            {
         | 
| 173 | 
            -
                                **job['args'],
         | 
| 174 | 
            -
                                '_ModelRevision' : revisionHash,
         | 
| 175 | 
            -
                                '_ModelArgs' : config['args']
         | 
| 176 | 
            -
                            },
         | 
| 177 | 
            -
                            "context": [
         | 
| 178 | 
            -
                                function,
         | 
| 179 | 
            -
                                f"model/@sdk/{str(int(time.time() * random.random()))}"
         | 
| 180 | 
            -
                            ],
         | 
| 181 | 
            -
                            "policy":
         | 
| 182 | 
            -
                            policy,
         | 
| 183 | 
            -
                        }
         | 
| 184 | 
            -
                    }
         | 
| 201 | 
            +
                    variables = Runner.__createJobVariables(job, config, revisionHash, rid,policy, **kwargs)
         | 
| 185 202 | 
             
                    r = graphql_request(query, variables)
         | 
| 186 203 | 
             
                    if 'errors' in r:
         | 
| 187 204 | 
             
                        raise Exception(r['errors'])
         | 
| @@ -223,14 +240,26 @@ class HttpRunner(Runner[T]): | |
| 223 240 | 
             
                    if self.__taskId is None:
         | 
| 224 241 | 
             
                        return False
         | 
| 225 242 | 
             
                    return self.result.status()  # type: ignore
         | 
| 226 | 
            -
             | 
| 227 | 
            -
             | 
| 243 | 
            +
             | 
| 244 | 
            +
             | 
| 245 | 
            +
            class HttpOPTRunner(Runner[T]):
         | 
| 246 | 
            +
             | 
| 228 247 | 
             
                def __init__(self, job, simulationId, **kwargs):
         | 
| 229 248 | 
             
                    self.simulationId = simulationId
         | 
| 230 249 | 
             
                    self.job = job
         | 
| 231 | 
            -
                     | 
| 232 | 
            -
                     | 
| 250 | 
            +
                    self.__taskId = self.__getLastTask()
         | 
| 251 | 
            +
                    result = IES_LAB_OPT_RESULT.get(job.get('rid', ''), IESLabOptResult)
         | 
| 252 | 
            +
                    self.result: T = result(self.simulationId, self.__taskId,
         | 
| 253 | 
            +
                                            **kwargs)  # type: ignore
         | 
| 233 254 |  | 
| 234 | 
            -
                def  | 
| 235 | 
            -
                     | 
| 255 | 
            +
                def __getLastTask(self):
         | 
| 256 | 
            +
                    r = request('GET',
         | 
| 257 | 
            +
                                'api/ieslab-opt/taskmanager/getSimuLastTasks',
         | 
| 258 | 
            +
                                params={'simuid': self.simulationId})
         | 
| 259 | 
            +
                    result = json.loads(r.text)
         | 
| 260 | 
            +
                    return result['data'].get('task_id', None)
         | 
| 236 261 |  | 
| 262 | 
            +
                def status(self):
         | 
| 263 | 
            +
                    if self.__taskId is None:
         | 
| 264 | 
            +
                        return False
         | 
| 265 | 
            +
                    return self.result.status()  # type: ignore
         | 
    
        cloudpss/utils/IO.py
    CHANGED
    
    | @@ -104,7 +104,7 @@ class IO(object): | |
| 104 104 | 
             
                    if format == 'ubjson':
         | 
| 105 105 | 
             
                        return ubjson.loadb(byt)
         | 
| 106 106 | 
             
                    if format == 'yaml':
         | 
| 107 | 
            -
                        return yaml.load(io.BytesIO(byt), yaml. | 
| 107 | 
            +
                        return yaml.load(io.BytesIO(byt), Loader=yaml.BaseLoader)
         | 
| 108 108 | 
             
                    assert False, 'format not support'
         | 
| 109 109 |  | 
| 110 110 | 
             
                @staticmethod
         | 
    
        cloudpss/utils/graphqlUtil.py
    CHANGED
    
    | @@ -3,8 +3,9 @@ import json | |
| 3 3 | 
             
            from cloudpss.utils import request
         | 
| 4 4 |  | 
| 5 5 |  | 
| 6 | 
            -
            def graphql_request(query, variables=None):
         | 
| 6 | 
            +
            def graphql_request(query, variables=None, **kwargs):
         | 
| 7 7 | 
             
                payload = {'query': query, 'variables': variables}
         | 
| 8 | 
            -
                 | 
| 8 | 
            +
                
         | 
| 9 | 
            +
                r = request('POST', 'graphql', data=json.dumps(payload), **kwargs)
         | 
| 9 10 |  | 
| 10 11 | 
             
                return json.loads(r.text)
         | 
    
        cloudpss/utils/httprequests.py
    CHANGED
    
    | @@ -13,16 +13,23 @@ def request(method, uri, baseUrl=None, params={}, token=None, **kwargs): | |
| 13 13 | 
             
                    baseUrl = os.environ.get('CLOUDPSS_API_URL', 'https://cloudpss.net/')
         | 
| 14 14 | 
             
                url = requests.compat.urljoin(baseUrl,uri)
         | 
| 15 15 | 
             
                token = os.environ.get('CLOUDPSS_TOKEN', None)
         | 
| 16 | 
            +
                
         | 
| 16 17 | 
             
                if token:
         | 
| 17 18 | 
             
                    headers = {
         | 
| 18 19 | 
             
                        'Authorization': 'Bearer ' + token,
         | 
| 19 | 
            -
                        'Content-Type': 'application/json; charset=utf-8'
         | 
| 20 | 
            +
                        'Content-Type': 'application/json; charset=utf-8',
         | 
| 21 | 
            +
                       
         | 
| 20 22 | 
             
                    }
         | 
| 21 23 | 
             
                else:
         | 
| 22 24 | 
             
                    raise Exception('token undefined')
         | 
| 23 | 
            -
             | 
| 24 | 
            -
                 | 
| 25 | 
            +
             | 
| 26 | 
            +
                xToken =kwargs.get('xToken',None)
         | 
| 27 | 
            +
                if xToken:
         | 
| 28 | 
            +
                    headers['x-Authorization'] = 'Bearer ' +xToken
         | 
| 29 | 
            +
                    del kwargs['xToken']
         | 
| 25 30 |  | 
| 31 | 
            +
                r = requests.request(method, url, params=params, headers=headers, **kwargs)
         | 
| 32 | 
            +
             | 
| 26 33 | 
             
                if (uri.startswith('graphql')):
         | 
| 27 34 | 
             
                    if 'X-Cloudpss-Version' not in r.headers:
         | 
| 28 35 | 
             
                        raise Exception(
         | 
| @@ -33,12 +40,13 @@ def request(method, uri, baseUrl=None, params={}, token=None, **kwargs): | |
| 33 40 | 
             
                                        r.headers['X-Cloudpss-Version'] +
         | 
| 34 41 | 
             
                                        '.X.X)不兼容,请更换服务器地址或更换SDK版本(pip 使用 pip install -U cloudpss 命令更新, conda 使用 conda update cloudpss 命令更新)。')
         | 
| 35 42 |  | 
| 36 | 
            -
                if r.ok:
         | 
| 37 | 
            -
             | 
| 38 | 
            -
                logging.debug(r.text)
         | 
| 39 | 
            -
                if r.text =="":
         | 
| 40 | 
            -
             | 
| 43 | 
            +
                # if r.ok:
         | 
| 44 | 
            +
                #     return r
         | 
| 45 | 
            +
                # logging.debug(r.text)
         | 
| 46 | 
            +
                # if r.text =="":
         | 
| 47 | 
            +
                r.raise_for_status()
         | 
| 41 48 | 
             
                if "statusCode" in r.text:
         | 
| 42 49 | 
             
                    t = json.loads(r.text)
         | 
| 43 50 | 
             
                    raise  Exception(str(t['statusCode']) + " "+t['message'])
         | 
| 51 | 
            +
                return r
         | 
| 44 52 |  | 
    
        cloudpss/version.py
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            __version__ = '4. | 
| 1 | 
            +
            __version__ = '4.5.0'
         | 
| @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            Metadata-Version: 2.1
         | 
| 2 2 | 
             
            Name: cloudpss
         | 
| 3 | 
            -
            Version: 4. | 
| 3 | 
            +
            Version: 4.5.0
         | 
| 4 4 | 
             
            Summary: cloudpss sdk
         | 
| 5 5 | 
             
            Home-page: https://www.cloudpss.net
         | 
| 6 6 | 
             
            Author: cloudpss
         | 
| @@ -18,7 +18,7 @@ Requires-Dist: PyJWT | |
| 18 18 | 
             
            Requires-Dist: numpy
         | 
| 19 19 | 
             
            Requires-Dist: PyYAML
         | 
| 20 20 | 
             
            Requires-Dist: requests
         | 
| 21 | 
            -
            Requires-Dist: websocket-client
         | 
| 21 | 
            +
            Requires-Dist: websocket-client (>=1.4.0)
         | 
| 22 22 | 
             
            Requires-Dist: pytz
         | 
| 23 23 | 
             
            Requires-Dist: deprecated
         | 
| 24 24 | 
             
            Requires-Dist: py-ubjson
         |