azsaprfc 0.0.1__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.
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.1
2
+ Name: azsaprfc
3
+ Version: 0.0.1
4
+ Summary: SAP Tools for python
5
+ Author: AndyZhu
6
+ Author-email: andyzhu@live.com
@@ -0,0 +1 @@
1
+
@@ -0,0 +1,767 @@
1
+ import json
2
+ import os
3
+ import re
4
+ import pyrfc
5
+ import sys
6
+ import pandas
7
+ from dataclasses import dataclass,field,asdict
8
+
9
+ @dataclass(frozen=True)
10
+ class ServerParameters:
11
+ hostname:str
12
+ client:str
13
+ user:str
14
+ password:str
15
+ sysnr:str
16
+ language:str
17
+ router:str
18
+
19
+
20
+ class SapServer:
21
+ '''SAP RFC 连接服务器的相关基类'''
22
+ # 连接参数样例
23
+ CONNECT_PARAMETERS = {
24
+ 'ASHOST': '', # 'XXX.XXX.XX.XX'
25
+ 'CLIENT': '', # '800'
26
+ 'SYSNR': '', # '00'
27
+ 'USER': '',
28
+ 'PASSWD': '',
29
+ 'LANG': 'ZH',
30
+ 'SAPROUTER': '', # '/H/XXX.XX.XX.XX/H/XXX.XX.XXX.XXX/H/'
31
+ }
32
+
33
+ def __init__(self, hostname, client, user='', password='', sysnr='00', language='ZH', router='') -> None:
34
+ self.conParameters = {
35
+ 'ASHOST': hostname,
36
+ 'CLIENT': client, # '800'
37
+ 'SYSNR': sysnr, # '00'
38
+ 'USER': user,
39
+ 'PASSWD': password,
40
+ 'LANG': language,
41
+ 'SAPROUTER': router,
42
+ }
43
+ self.sapObject = None
44
+
45
+ def connect(self) -> bool:
46
+ '''调用RFC前需要调用此方法'''
47
+ # 连接SAP
48
+ self.sapObject = pyrfc.Connection(**self.conParameters)
49
+ if self.sapObject:
50
+ if self.sapObject.alive:
51
+ return True
52
+ else:
53
+ return False
54
+ else:
55
+ return False
56
+
57
+ def disconnect(self):
58
+ '''调用RFC后调用此方法断开连接'''
59
+ if self.sapObject:
60
+ if self.sapObject.alive:
61
+ self.sapObject.close
62
+
63
+ def callRFC(self, functionName, **parameters):
64
+ """ 调用RFC函数
65
+ 参数说明:
66
+ :functionName: RFC函数名称,如:ZFM_RTR_GET_MESSAGE
67
+ :parameters: 字典形式
68
+ 调用样例:
69
+ parameters = {'IM_MSG' : sqlStatement,
70
+ 'IM_SOURCE': sourcelist }
71
+ functionName = 'ZFM_RTR_GET_MESSAGE'
72
+ resultList = []
73
+ try:
74
+ self.connect()
75
+ returnResult = self.callRFC(functionName,**parameters)
76
+ self.disconnect()
77
+ resultBinaryString = returnResult['EV_RESULT']
78
+ resultRows = returnResult['EV_ROWS']
79
+ returnMesage = returnResult['EV_MESSAGE']
80
+ except Exception as e:
81
+ str(e)
82
+ finally:
83
+ self.disconnect()
84
+ """
85
+ try:
86
+ result = self.sapObject.call(functionName, **parameters)
87
+ return result
88
+ except Exception as e:
89
+ raise e
90
+
91
+ # call function:RFC_READ_TABLE
92
+ def readTable(self, tableName, conds: list = [], fields: list = [], DELIMITER='|'):
93
+ '''调用READ_TABLE函数获取表内容
94
+
95
+ 如:readTable('SPFLI',[{"TEXT": "COUNTRYFR EQ 'US' "} ],['CARRID','CITYFROM'])
96
+ '''
97
+ parameters = {'QUERY_TABLE': tableName,
98
+ 'DELIMITER': DELIMITER,
99
+ 'OPTIONS': conds,
100
+ 'FIELDS': fields,
101
+ }
102
+ functionName = 'RFC_READ_TABLE'
103
+ try:
104
+ self.connect()
105
+ returnResult = self.callRFC(functionName, **parameters)
106
+ self.disconnect()
107
+ fieldsList = returnResult['FIELDS']
108
+ fieldsnameList = []
109
+ resultData = []
110
+ for field in fieldsList:
111
+ fieldsnameList.append(field.get('FIELDNAME'))
112
+ for dat in returnResult['DATA']:
113
+ waList = dat['WA'].split(DELIMITER)
114
+ wa1 = [wa.strip() for wa in waList] # 删除文本空格
115
+ rowDict = dict(zip(fieldsnameList, wa1))
116
+ resultData.append(rowDict)
117
+ except Exception as e:
118
+ resultData.append({'info': str(e)})
119
+ finally:
120
+ self.disconnect()
121
+ return resultData
122
+
123
+ # import pandas
124
+ # sap.readTable('excelfile.xls','SPFLI',[{"TEXT": "COUNTRYFR EQ 'US' "} ],['CARRID','CITYFROM'])
125
+ def readTableToEXCEL(self,filename,tableName,conds:list = [],fields:list=[],DELIMITER = '|'):
126
+ fullfilename = filename +'.xlsx'
127
+ parameters = {'QUERY_TABLE':tableName,
128
+ 'DELIMITER':DELIMITER,
129
+ 'OPTIONS':conds,
130
+ 'FIELDS':fields,
131
+ }
132
+ functionName = 'RFC_READ_TABLE'
133
+ returnResult = self.callRFC(functionName,**parameters)
134
+ result = pandas.DataFrame([[x.strip() for x in returnResult['DATA'][n]['WA'].split(DELIMITER)] for n in range(len(returnResult['DATA']))],
135
+ columns=[x['FIELDNAME'] for x in returnResult['FIELDS']] )
136
+ result.to_excel(fullfilename,index=False)
137
+
138
+ def restExecuteSql(self, sqlStatement):
139
+ '''通过ADT SQL 执行SQL 查询语句
140
+
141
+ sqlStatement:SQL 语句
142
+ 有ADT 开发权限
143
+ call function:SADT_REST_RFC_ENDPOINT
144
+ '''
145
+ import xml.etree.ElementTree as ET
146
+ request_line = {'METHOD': 'POST',
147
+ 'URI': '/sap/bc/adt/datapreview/freestyle?rowNumber=100&dataAging=true',
148
+ 'VERSION': 'HTTP/1.1',
149
+ }
150
+ headers = [{'NAME': 'Content-Type',
151
+ 'VALUE': 'text/plain',
152
+ },
153
+ {'NAME': 'Accept',
154
+ 'VALUE': 'application/xml, application/vnd.sap.adt.datapreview.table.v1+xml',
155
+ },
156
+ {'NAME': 'User-Agent',
157
+ 'VALUE': 'Eclipse/4.28.0.v20230605-0440 (win32; x86_64; Java 17.0.7) ADT/3.36.0 (devedition)',
158
+ },
159
+ {'NAME': 'X-sap-adt-profiling',
160
+ 'VALUE': 'server-time',
161
+ },
162
+ ]
163
+ request = {'REQUEST_LINE': request_line,
164
+ 'HEADER_FIELDS': headers,
165
+ 'MESSAGE_BODY': bytes(sqlStatement, 'utf-8'),
166
+ }
167
+ parameters = {'REQUEST': request}
168
+ functionName = 'SADT_REST_RFC_ENDPOINT'
169
+ try:
170
+ self.connect()
171
+ returnResult = self.callRFC(functionName, **parameters)
172
+ self.disconnect()
173
+ response = returnResult['RESPONSE']
174
+ body = response['MESSAGE_BODY']
175
+ bodyString = str(body, encoding='utf8')
176
+ # xlm to list
177
+ content = ET.fromstring(bodyString)
178
+ root = content
179
+ NS = {"dataPreview": r"http://www.sap.com/adt/dataPreview"}
180
+ resultList = []
181
+ resultRow = {}
182
+ columnData = []
183
+ rowCount = 0
184
+ columCount = 0
185
+ # print(root.attrib['xmlns:dataPreview']) #.get('dataPreview'))
186
+ for column in root.findall('dataPreview:columns', namespaces=NS):
187
+ columCount += 1
188
+ col = {'name': None,
189
+ 'data': []}
190
+ for field in column.findall('dataPreview:metadata', namespaces=NS):
191
+ col['name'] = field.attrib.get(
192
+ '{'+NS['dataPreview']+'}description')
193
+
194
+ # print(field.attrib.get('{'+NS['dataPreview']+'}description'))
195
+ for dataset in column.findall('dataPreview:dataSet', namespaces=NS):
196
+ for node in dataset.iter():
197
+ col['data'].append(node.text)
198
+ if columCount == 1:
199
+ rowCount += 1
200
+ columnData.append(col)
201
+
202
+ for i in range(rowCount):
203
+ resultRow = {}
204
+ for dat in columnData:
205
+ resultRow[dat.get('name')] = dat.get('data')[i]
206
+ resultList.append(resultRow)
207
+ except Exception as e:
208
+ resultList.append({'info': str(e)})
209
+ finally:
210
+ self.disconnect()
211
+ return resultList
212
+
213
+
214
+ def restReadSourceBatch(self,filePath,objList:list):
215
+ """_summary_
216
+
217
+ Args:
218
+ filePath (string): 路径
219
+ objList (list): 对象列表 'objType' : CLASS,PROG,FUNC,TABL
220
+ objList = [ {'objType':'CLASS', 'objName':'ZTEST'},
221
+ {'objType':'PROG', 'objName':'YTEST001'},
222
+ ]
223
+ """
224
+ resultList = []
225
+ # contList = [
226
+ # # {'objType':'CLASS', #CLASS,PROG,FUNC,TABL
227
+ # # 'objName':'ZTEST',
228
+ # # },
229
+ # {'objType':'PROG',
230
+ # 'objName':'YTEST001',
231
+ # },
232
+ # ]
233
+ # paraServer = ConnParams.S4D
234
+ # sapServer = SapServer(**asdict(paraServer))
235
+ if objList == None:
236
+ print('objList is None')
237
+ return None
238
+ for cnt in objList:
239
+ resultDict={}
240
+ rest = self.restReadSource(cnt.get('objType'),cnt.get('objName'))
241
+ fullFile = os.path.join(filePath,cnt.get('objName')+'.txt')
242
+ with open(fullFile,'w',encoding='UTF-8') as f:
243
+ f.write(rest)
244
+ resultDict = {
245
+ 'objType' : cnt.get('objType'),
246
+ 'objName': cnt.get('objName'),
247
+ 'fileName':fullFile,
248
+ }
249
+ resultList.append(resultDict)
250
+ print( f'{ fullFile },Done!')
251
+ return resultList
252
+
253
+
254
+ def restReadSource(self, objType,objName):
255
+ ulr = None
256
+ urltxtsymbol=None
257
+ urltxtselection=None
258
+ retString = None
259
+ if objName == '':
260
+ return None
261
+ if objType == 'CLASS':
262
+ ulr = f'/sap/bc/adt/oo/classes/{objName.lower().strip()}/source/main'
263
+ urltxtsymbol = f'/sap/bc/adt/textelements/classes/{objName.lower().strip()}/source/symbols'
264
+
265
+ elif objType == "PROG":
266
+ ulr = f'/sap/bc/adt/programs/programs/{objName.lower().strip()}/source/main'
267
+ urltxtsymbol = f'/sap/bc/adt/textelements/programs/{objName.lower().strip()}/source/symbols'
268
+ urltxtselection = f'/sap/bc/adt/textelements/programs/{objName.lower().strip()}/source/selections'
269
+
270
+ elif objType == 'FUNC':
271
+ cond = [{"TEXT": f"FUNCNAME EQ '{objName.upper()}'"} ]
272
+ funcs = self.readTable('TFDIR',cond,['PNAME'])
273
+ funcgrp = funcs[0].get('PNAME')[4:]
274
+ ulr = f'/sap/bc/adt/functions/groups/{funcgrp.lower().strip()}/fmodules/{objName.lower().strip()}/source/main'
275
+ urltxtsymbol = f'/sap/bc/adt/textelements/functiongroups/{funcgrp.lower().strip()}/source/symbols'
276
+ urltxtselection = f'/sap/bc/adt/textelements/functiongroups/{funcgrp.lower().strip()}/source/selections'
277
+ elif objType == 'TABL':
278
+ retString = self.restReadStructure(objName)
279
+ elif objType == 'INFO':
280
+ retString = self.restReadObjectList(objName)
281
+
282
+ if ulr != None:
283
+ retString = self.restCallURL(ulr)
284
+
285
+ retString += '\n\n"=====以下是相关文本信息=====\n\n'
286
+ if urltxtsymbol !=None:
287
+ # text symbols
288
+ retTxtSymbol = self.restCallURL(urltxtsymbol,Accepttype='application/vnd.sap.adt.textelements.symbols.v1')
289
+ txtList=retTxtSymbol.split('\r')
290
+ retString += '\n\n"=====以下是文本元素=====\n'
291
+ for txt in txtList:
292
+ if txt and txt[:1] != '@':
293
+ retString += '\n' + txt
294
+ if urltxtselection !=None:
295
+ # text symbols
296
+ retTxtSymbol = self.restCallURL(urltxtselection,Accepttype='application/vnd.sap.adt.textelements.selections.v1')
297
+ txtList=retTxtSymbol.split('\r')
298
+ retString += '\n\n"=====以下是Selection文本=====\n'
299
+ for txt in txtList:
300
+ if txt :
301
+ retString += '\n' + txt
302
+ return retString
303
+
304
+
305
+ # property
306
+ # Accept : application/vnd.sap.adt.repository.objproperties.result.v1+xml
307
+ # GET /sap/bc/adt/repository/informationsystem/objectproperties/values?
308
+ # uri=/sap/bc/adt/functions/groups/zfg_rtr_f0007/fmodules/zfm_rtr_int_017_process&facet=package&facet=appl
309
+ # /sap/bc/adt/programs/programs/zrtrrf0140&facet=package&facet=appl
310
+ # /sap/bc/adt/oo/classes/zcl_abap_utilities&facet=package&facet=appl
311
+ # <?xml version="1.0" encoding="UTF-8"?>
312
+ # +<opr:object expandable="true" type="CLAS/OC" package="ZRTR" name="ZCL_ABAP_UTILITIES" text="工具">
313
+
314
+ # structure
315
+ # /sap/bc/adt/ddic/elementinfo?path=zscud_info
316
+ # Accept : application/vnd.sap.adt.elementinfo+xml
317
+ # adtcore:name="zrtrsf00100" adtcore:type="TABL/DS" adtcore:uri="/sap/bc/adt/ddic/structures/zrtrsf00100">
318
+
319
+ # abap URL list 代码
320
+ # DATA(lr_inst) = cl_adt_tools_core_factory=>get_instance( ).
321
+ # DATA(lr_urlmapper) = lr_inst->get_uri_mapper( ).
322
+ # " CL_ADT_URI_TEMPLATES_SHM_ROOT->BUILD_TEMPLATES
323
+ # DATA(type_provider) = cl_wb_registry=>get_objtype_provider( ).
324
+ # type_provider->get_objtypes( IMPORTING p_objtype_data = DATA(wbobjtype_data) ).
325
+ # LOOP AT wbobjtype_data->mt_wbobjtype ASSIGNING FIELD-SYMBOL(<type>) WHERE pgmid = 'R3TR'
326
+ # AND is_main_subtype_wb = abap_true.
327
+ # DATA ls_type TYPE wbobjtype.
328
+ # ls_type-objtype_tr = <type>-objecttype.
329
+ # ls_type-subtype_wb = <type>-subtype_wb.
330
+ # *<type>-description
331
+ # DATA(lv_type) = |{ <type>-objecttype }{ <type>-subtype_wb }|.
332
+ # DATA(uri) = cl_adt_tools_core_factory=>get_instance( )->get_uri_mapper( )->get_adt_object_ref_uri(
333
+ # name = 'ZCL_RTR_COMMON'
334
+ # type = ls_type ).
335
+ # ENDLOOP.
336
+
337
+ def restCallURL(self, url,Accepttype='text/plain'):
338
+ '''通过ADT 获取代码
339
+ 有ADT 开发权限
340
+ call function:SADT_REST_RFC_ENDPOINT
341
+ url:
342
+ class source:/sap/bc/adt/oo/classes/{classname.lower().strip()}/source/main
343
+ report source: /sap/bc/adt/programs/programs/{programname.lower().strip()}/source/main source
344
+ report text: /sap/bc/adt/textelements/programs/{programname.lower().strip()/source/selections?version=workingArea
345
+ /sap/bc/adt/textelements/programs/{programname.lower().strip()/source/symbols?version=workingArea
346
+ funct source: /sap/bc/adt/functions/groups/{funcgrp.lower().strip()}/fmodules/{objName.lower().strip()}/source/main
347
+ /sap/bc/adt/ddic/tables/mara/source/main
348
+ '''
349
+ request_line = {'METHOD': 'GET',
350
+ 'URI': url,
351
+ 'VERSION': 'HTTP/1.1',
352
+ }
353
+ headers = [
354
+
355
+ {'NAME': 'Cache-Control',
356
+ 'VALUE': 'no-cache',
357
+ },
358
+ {'NAME': 'Accept',
359
+ 'VALUE': Accepttype,
360
+ },
361
+ {'NAME': 'User-Agent',
362
+ 'VALUE': 'Eclipse/4.28.0.v20230605-0440 (win32; x86_64; Java 17.0.7) ADT/3.38.2 (devedition)',
363
+ },
364
+ {'NAME': 'X-sap-adt-profiling',
365
+ 'VALUE': 'server-time',
366
+ },
367
+ ]
368
+ request = {'REQUEST_LINE': request_line,
369
+ 'HEADER_FIELDS': headers,
370
+ # 'MESSAGE_BODY': bytes(sqlStatement, 'utf-8'),
371
+ }
372
+ parameters = {'REQUEST': request}
373
+ functionName = 'SADT_REST_RFC_ENDPOINT'
374
+ try:
375
+ self.connect()
376
+ returnResult = self.callRFC(functionName, **parameters)
377
+ self.disconnect()
378
+ response = returnResult['RESPONSE']
379
+ body = response['MESSAGE_BODY']
380
+ # print(body)
381
+ bodyString1 = str(body, encoding='utf8')
382
+ # bodyString = str(body, encoding='utf8')
383
+ bodyString = str(body, encoding='utf8').replace('\n','')
384
+ # print(bodyString1)
385
+ except Exception as e:
386
+ pass
387
+ finally:
388
+ self.disconnect()
389
+ return bodyString
390
+
391
+ def restReadStructure(self,objName):
392
+ url = f'/sap/bc/adt/ddic/elementinfo?path={objName.lower().strip()}'
393
+ resultXmlString=self.restCallURL(url ,Accepttype='application/vnd.sap.adt.elementinfo+xml')
394
+ lines = 0
395
+ import xml.etree.ElementTree as ET
396
+ xmlroot = ET.fromstring(resultXmlString)
397
+ NS = {'abapsource':r'http://www.sap.com/adt/abapsource',
398
+ 'adtcore':r'http://www.sap.com/adt/core'}
399
+ tabdesc = xmlroot.find("abapsource:documentation",namespaces= NS).text
400
+ fieldstring = f'Talble/Structure:{objName}, Description:{tabdesc}\n'
401
+ # tabdesc = xmlroot.find('{'+NS['abapsource']+'}documentation').text
402
+ resultList=[]
403
+ columns = xmlroot.findall('abapsource:elementInfo' , namespaces= NS )
404
+ for column in columns:
405
+ lines +=1
406
+ if column.attrib.get('{'+NS['adtcore']+'}type') != "TABL/DTF":
407
+ continue
408
+ field={}
409
+ field['fieldName'] = column.attrib.get('{'+NS['adtcore']+'}name')
410
+ field['fieldDesc'] = column.find('abapsource:documentation' , namespaces= NS).text
411
+ # field['fieldDesc'] = column.findall('abapsource:documentation' , namespaces= NS)[0].text
412
+ fieldinfos = column.findall('abapsource:properties' , namespaces= NS)
413
+ for info in fieldinfos[0].findall('abapsource:entry' , namespaces= NS):
414
+ if info.attrib.get('{'+NS['abapsource']+'}key') == 'ddicDataElement':
415
+ field['dtlElement'] = info.text
416
+ elif info.attrib.get('{'+NS['abapsource']+'}key') == 'ddicDataType':
417
+ field['dataType'] = info.text
418
+ elif info.attrib.get('{'+NS['abapsource']+'}key') == 'ddicLength':
419
+ field['dataLen'] = info.text
420
+ elif info.attrib.get('{'+NS['abapsource']+'}key') == 'ddicDecimals':
421
+ field['dataDecimals'] = info.text
422
+ elif info.attrib.get('{'+NS['abapsource']+'}key') == 'ddicIsKey':
423
+ field['isKey'] = info.text
424
+ elif info.attrib.get('{'+NS['abapsource']+'}key') == 'parentName':
425
+ field['parentName'] = info.text
426
+ if lines == 1:
427
+ fieldstring += '\n' + '\t'.join(field.keys())
428
+ fieldstring += '\n=====================================================\n'
429
+ fieldstring += '\n' + '\t'.join(field.values())
430
+ resultList.append(field)
431
+ return fieldstring
432
+
433
+ def restReadObjectList(self,objName):
434
+ url = f'/sap/bc/adt/repository/informationsystem/search?operation=quickSearch&query={objName.lower().strip()}*&maxResults=51'
435
+ resultXmlString=self.restCallURL(url ,Accepttype='application/xml')
436
+ lines = 0
437
+ import xml.etree.ElementTree as ET
438
+ xmlroot = ET.fromstring(resultXmlString)
439
+ NS = { 'adtcore':r'http://www.sap.com/adt/core'}
440
+ # tabdesc = xmlroot.find('{'+NS['abapsource']+'}documentation').text
441
+ fieldstring = f'Searching:{objName}:\n'
442
+ resultList=[]
443
+ objlists = xmlroot.findall('adtcore:objectReference' , namespaces= NS )
444
+ for obj in objlists:
445
+ lines +=1
446
+ result={}
447
+ result['name'] = obj.attrib.get('{'+NS['adtcore']+'}name')
448
+ result['type'] = obj.attrib.get('{'+NS['adtcore']+'}type')
449
+ result['description'] = obj.attrib.get('{'+NS['adtcore']+'}description')
450
+ result['uri'] = obj.attrib.get('{'+NS['adtcore']+'}uri')
451
+ result['packageName'] = obj.attrib.get('{'+NS['adtcore']+'}packageName')
452
+ if lines == 1:
453
+ fieldstring += '\n' + '\t'.join(result.keys())
454
+ fieldstring += '\n=====================================================\n'
455
+ fieldstring += '\n' + '\t'.join(result.values())
456
+ resultList.append(result)
457
+ return fieldstring
458
+ # return resultList
459
+
460
+
461
+ def executeProgramDynamic(self, codeFileName,funcID, para1, para2='', para3='', para4=''):
462
+ '''通过函数 ECATT_REMOTE_MODULE_EXECUTE 动态执行各种语句
463
+
464
+ 需要权限对象S_DEVELOP:
465
+ OBJTYPE:'SCAT', 'ACTVT' '16'.
466
+ 或 'OBJTYPE' , 'ECSC' 'ACTVT' '16'.
467
+ 执行代码在文件:sapdynamicprogram.abap
468
+ '''
469
+
470
+ abapsource = ''
471
+ resultJson = ''
472
+ result = {}
473
+ resultList = []
474
+ current_file_path = os.path.abspath(__file__) # 当前文件绝对路径
475
+ current_path = os.path.dirname(current_file_path) # 文件所在的路径
476
+ filenamewithpath = os.path.join(current_path, 'sapdynamicprogram.abap')
477
+ sourcelist = []
478
+ inputPara = []
479
+ filenamewithpath = codeFileName
480
+ with open(filenamewithpath, 'r', encoding='UTF-8') as f:
481
+ abapsource = f.readline()
482
+ source = {'LINE': abapsource.replace("\n", "")}
483
+ sourcelist.append(source)
484
+ while abapsource:
485
+ abapsource = f.readline()
486
+ source = {}
487
+ source = {'LINE': abapsource.replace("\n", "")}
488
+ sourcelist.append(source)
489
+ inputParaDict = {'FUNCTIONID': funcID,
490
+ 'PARA1': para1,
491
+ 'PARA2': para2,
492
+ 'PARA3': para3,
493
+ 'PARA4': para4,
494
+ }
495
+ inputParaJson = json.dumps(inputParaDict, ensure_ascii=False)
496
+ # 30长度拆分字符到List
497
+ inputParaList = re.findall('.{'+str(30)+'}', inputParaJson)
498
+ inputParaList.append(inputParaJson[(len(inputParaList)*30):])
499
+
500
+ for para in inputParaList:
501
+ paradict = {'FLAG': '', 'VALUE': para}
502
+ inputPara.append(paradict)
503
+ parameters = {'PROGRAM': sourcelist,
504
+ 'ECATT_TRANSFER_DATA_CONTAINER': inputPara}
505
+ functionName = 'ECATT_REMOTE_MODULE_EXECUTE'
506
+ resultList = []
507
+ try:
508
+ self.connect()
509
+ returnResult = self.callRFC(functionName, **parameters)
510
+ self.disconnect()
511
+ returnMsg = returnResult.get('FUN_MESSAGE').get('MSGTEXT')
512
+ if returnResult.get('SY_SUBRC') == 0:
513
+ returnCode = '200'
514
+ else:
515
+ returnCode = '201'
516
+ resultTable = returnResult.get('ECATT_TRANSFER_DATA_CONTAINER')
517
+ for res in resultTable:
518
+ resultJson += res.get('VALUE')
519
+ print(resultJson)
520
+ if resultJson:
521
+ resultList = json.loads(resultJson)
522
+ result = {
523
+ 'ResultList': resultList,
524
+ 'Rows': 0,
525
+ 'Code': returnCode,
526
+ 'Message': returnMsg,
527
+ }
528
+ except Exception as e:
529
+ # print(str(e))
530
+ result = {
531
+ 'ResultList': [],
532
+ 'Rows': 0,
533
+ 'Code': '201',
534
+ 'Message': str(e),
535
+ }
536
+ finally:
537
+ self.disconnect()
538
+ return result
539
+
540
+
541
+ def getFunctionParameters(self,imFunctionName):
542
+ resultList=[]
543
+ try:
544
+ self.connect()
545
+ func_desc = self.sapObject.get_function_description(imFunctionName)
546
+ for parameter in func_desc.parameters:
547
+ para = {
548
+ "direction":parameter["direction"],
549
+ "name":parameter["name"],
550
+ "parameter_text":parameter["parameter_text"],
551
+ "parameter_type":parameter["parameter_type"],
552
+ "nuc_length":parameter["nuc_length"],
553
+ "uc_length":parameter["uc_length"],
554
+ "decimals":parameter["decimals"],
555
+ "default_value":parameter["default_value"],
556
+ "optional":parameter["optional"],
557
+ "type_name":None ,
558
+ }
559
+ if parameter["type_description"] != None:
560
+ para['type_name'] = parameter["type_description"].name
561
+ resultList.append(para)
562
+ # print(para)
563
+ except:
564
+ pass
565
+ finally:
566
+ self.disconnect()
567
+ return resultList
568
+
569
+ def getFunctionParameterType(self,imFunctionName,imParameter):
570
+ resultDict={}
571
+ resultFieldList = []
572
+ try:
573
+ self.connect()
574
+ func_desc = self.sapObject.get_function_description(imFunctionName)
575
+ for parameter in func_desc.parameters:
576
+ if parameter.get("name") == imParameter and parameter["type_description"] != None:
577
+
578
+ for itm in parameter["type_description"].fields:
579
+ # print(itm)
580
+ fields ={
581
+ # 'FieldType':itm['type']
582
+ 'name':itm['name'],
583
+ 'field_type':itm['field_type'],
584
+ 'nuc_offset':itm['nuc_offset'],
585
+ 'nuc_length':itm['nuc_length'],
586
+ 'uc_length':itm['uc_length'],
587
+ 'uc_offset':itm['uc_offset'],
588
+ 'decimals':itm['decimals'],
589
+ 'type_name':itm['type_description'].name if itm['type_description'] !=None else "",
590
+ }
591
+ resultFieldList.append(fields)
592
+ resultDict={
593
+ 'para_name':imParameter,
594
+ 'type_name':parameter["type_description"].name,
595
+ 'fields':resultFieldList
596
+ }
597
+ except:
598
+ pass
599
+ finally:
600
+ self.disconnect()
601
+ return resultDict
602
+
603
+
604
+ def getTableStructure(self,imTableName):
605
+ resultList=[]
606
+ if imTableName == None or imTableName == "" :
607
+ return None
608
+ try:
609
+ self.connect()
610
+ parameter={
611
+ "TABNAME": imTableName,
612
+ "ALL_TYPES": "X",
613
+ }
614
+ functionName = "DDIF_FIELDINFO_GET"
615
+ tabstru = self.callRFC(functionName,**parameter)
616
+ if tabstru.get("DDOBJTYPE") == "TTYP":
617
+ print(tabstru.get("DFIES_WA").get("ROLLNAME"))
618
+ resultList = self.getTableStructure(tabstru.get("DFIES_WA").get("ROLLNAME"))
619
+ return resultList
620
+ for field in tabstru.get("DFIES_TAB"):
621
+ fields ={
622
+ 'FieldName': field["FIELDNAME"],
623
+ 'Position': field["POSITION"],
624
+ 'DataType': field["DATATYPE"],
625
+ 'FieldText': field["FIELDTEXT"],
626
+ 'OffSet': field["OFFSET"],
627
+ 'RollName': field["ROLLNAME"],
628
+ 'Leng':field["LENG"],
629
+ 'Decimals':field["DECIMALS"],
630
+ 'FieldTitle': field["SCRTEXT_L"],
631
+ }
632
+ resultList.append(fields)
633
+
634
+ except:
635
+ pass
636
+ finally:
637
+ self.disconnect()
638
+ return resultList
639
+
640
+ def printTableStructure(self,imTableName):
641
+ resultList = self.getTableStructure(imTableName)
642
+ for result in resultList:
643
+ print(result)
644
+
645
+ def printFunctionParameterType(self,imFunctionName,imParameter):
646
+ resultList = self.getFunctionParameterType(imFunctionName,imParameter)
647
+ print(resultList['type_name'])
648
+ for result in resultList['fields']:
649
+ print(result)
650
+
651
+ def printFunctionParameters(self,imFunctionName):
652
+ resultList = self.getFunctionJsonParameters(imFunctionName)
653
+ for result in resultList:
654
+ print(result)
655
+
656
+ def getFunctionJsonParameters(self,imFunctionName):
657
+ resultDict = {}
658
+ funcParams = self.getFunctionJsonParameters(imFunctionName)
659
+ importPara = {}
660
+ # importPara = {fp['name']:fp.get('default_value',None) for fp in funcParams if fp['direction'] == 'RFC_IMPORT'}
661
+ for fp in funcParams:
662
+ if fp['direction'] == 'RFC_IMPORT':
663
+ if fp['type_description'] != None:
664
+ fieldsdict = {field['name']:None for field in fp['type_description']['structure']}
665
+ importPara.update({fp['name']:fieldsdict })
666
+ else:
667
+ importPara.update({fp['name']:fp.get('default_value',None)})
668
+ tablePara = {fp['name']:[{field['name']:None for field in fp['type_description']['structure']}] for fp in funcParams if fp['direction'] == 'RFC_TABLES'}
669
+ for dt in [importPara, tablePara]:
670
+ resultDict.update(dt)
671
+ return json.dumps(resultDict)
672
+
673
+ class SAPUILandscape:
674
+ def __init__(self,file_name ) :
675
+ import xml.etree.ElementTree as ET
676
+ self.content = ET.parse(file_name)
677
+ self.Items = []
678
+ self.Services = []
679
+ self.Routers = []
680
+ self.Messageservers= []
681
+ self.ServerList = []
682
+
683
+ import xml.etree.ElementTree as ET
684
+ self.content = ET.parse(file_name)
685
+ root = self.content.getroot()
686
+ # root[0].tag
687
+ # root[0].text
688
+ for item in root.iter('Item'): # root.findall('Item'):
689
+ itm= {
690
+ 'uuid':item.get('uuid'),
691
+ 'serviceid':item.get('uuid')
692
+ }
693
+
694
+
695
+ for item in root.iter('Item'): # root.findall('Item'):
696
+ itm= {
697
+ 'uuid':item.get('uuid'),
698
+ 'serviceid':item.get('uuid')
699
+ }
700
+ self.Items.append(itm)
701
+
702
+ for Route in root.iter('Router'): # root.findall('Router'):
703
+ dict = {
704
+ 'uuid':Route.get('uuid'),
705
+ 'name':Route.get('name'),
706
+ 'description':Route.get('description'),
707
+ 'router':Route.get('router')
708
+ }
709
+ self.Routers.append(dict)
710
+
711
+ for Service in root.iter('Service'): #root.findall('Service'):
712
+ dict = {
713
+ 'type':Service.get('type'),
714
+ 'uuid':Service.get('uuid'),
715
+ 'name':Service.get('name'),
716
+ 'systemid':Service.get('systemid'),
717
+ 'msid':Service.get('msid'),
718
+ 'server':Service.get('server'),
719
+ 'routerid':Service.get('routerid'),
720
+ 'dcpg':Service.get('dcpg'),
721
+ 'sncname':Service.get('sncname'),
722
+ }
723
+ if dict['type'] == 'SAPGUI':
724
+ self.Services.append(dict)
725
+
726
+ for MSService in root.iter('Messageserver'): # root.findall('Messageserver'):
727
+ dict = {
728
+ 'uuid':MSService.get('uuid'),
729
+ 'name':MSService.get('name'),
730
+ 'description':MSService.get('description'),
731
+ 'host':MSService.get('host'),
732
+ 'port':MSService.get('port'),
733
+ }
734
+ self.Messageservers.append(dict)
735
+
736
+ for service in self.Services:
737
+ dict = {
738
+ 'name':service.get('name'),
739
+ 'system':service.get('systemid'),
740
+ 'systemNo':''
741
+ }
742
+ server = service.get('server')
743
+ if server :
744
+ serveraddress = server.split(':')
745
+ dict['serverGroup'] = serveraddress[0]
746
+ if len(serveraddress) > 1:
747
+ dict['systemNo'] = serveraddress[1][2:4]
748
+ if service['msid'] in [dict1.get('uuid') for dict1 in self.Messageservers ]:
749
+ dict1 = sorted( self.Messageservers,key = lambda dicts:dicts['uuid'] != service['msid'])[0]
750
+ dict['messageServer'] = dict1.get('host')
751
+
752
+ if service['routerid'] in [dict1.get('uuid') for dict1 in self.Routers ]:
753
+ dict1 = sorted( self.Routers,key = lambda dicts:dicts['uuid'] != service['routerid'])[0]
754
+ dict['router'] = dict1.get('router')
755
+
756
+ dict['dcpg'] = service.get('dcpg')
757
+ dict['sncname'] = service.get('sncname')
758
+ self.ServerList.append(dict)
759
+
760
+
761
+ # df1 = pandas.DataFrame(self.ServerList)
762
+ # df1.to_excel('saspconfig.xlsx',index=False)
763
+
764
+
765
+
766
+ if __name__ == '__main__':
767
+ pass
@@ -0,0 +1,6 @@
1
+ Metadata-Version: 2.1
2
+ Name: azsaprfc
3
+ Version: 0.0.1
4
+ Summary: SAP Tools for python
5
+ Author: AndyZhu
6
+ Author-email: andyzhu@live.com
@@ -0,0 +1,7 @@
1
+ setup.py
2
+ azsaprfc/__init__.py
3
+ azsaprfc/saprfc.py
4
+ azsaprfc.egg-info/PKG-INFO
5
+ azsaprfc.egg-info/SOURCES.txt
6
+ azsaprfc.egg-info/dependency_links.txt
7
+ azsaprfc.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ azsaprfc
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,10 @@
1
+ from setuptools import setup, find_packages
2
+ setup(
3
+ name = 'azsaprfc',
4
+ version = '0.0.1',
5
+ author = 'AndyZhu',
6
+ author_email = 'andyzhu@live.com', # 作者邮箱
7
+ description='SAP Tools for python', # 描述
8
+ # packages = ['azpysaprfc'],
9
+ packages=find_packages(),
10
+ )