ABAQUS内核及GUI方法的代理接口

概述

随着 CAE 的广泛应用,CAE 用户的水平日渐提高,新需求日渐增多,CAE 软件的二次开发逐渐成为工程师的必备技能。Python 语言简单易懂、开源包众多,是非常流行的编程语言。Abaqus 作为一款以 Python 语言为前后处理内核的 CAE 软件,兼具 CAD 软件基于特征建模的方法,还提供了内核与 GUI 二次开发接口,所以基于 Abaqus 进行二次开发的自由度非常大。

Abaqus 的内核脚本二次开发可以从学习日志文件 abaqus.rpy 起步,GUI 脚本二次开发可以从 GUI 用户手册起步。熟悉之后,简单问题可以直接用脚本编写。但是 Abaqus 毕竟不是专业的集成开发环境(IDE),代码补全、参数提示功能较弱,借助专业 IDE 可提高开发效率。由于 Abaqus 的 Python 解释器无法被专业 IDE 直接调用,需要创建代理模块模拟 Abaqus 各种方法的接口。

本文从学习研究的角度探讨了创建 Abaqus 代理接口的方法,提供了有关脚本及生成的代理文件下载链接(欢迎打赏下载币)。

Abaqus内核及GUI代理的应用效果

在pyCharm中,内核脚本的快捷文档(光标在方法后、括号前,按Ctrl+Q)如下:
内核脚本的快捷文档
在 pyCharm 中,GUI 脚本的方法提示如下:
GUI脚本的成员提示
在 pyCharm 中,内核脚本的参数提示(Ctrl+P)如下:
内核脚本的方法参数提示

pyCharm 配置说明

  1. 下载上述文件,从“推荐使用的代理组合”目录下,复制 abaqus.py, abaqusConstants.py, abaqusGui.py 复制到 Python 解释器的 Lib/site-packages目录下,例如: C:\ProgramData\Anaconda2\Lib\site-packages
  2. 修改 pyCharm 设置,Help–>Edit Custom Properties,在 idea.properties 文件中添加一行
    idea.max.intellisense.filesize=99999【#默认是2500kb】,解决 pyCharm 中 File size exceeds configured limit 文件大小不够的问题。原文链接
  3. 重启 pyCharm即可

开发相关背景

Abaqus 自身的 CLI (command line interface) 窗口具有代码补全功能,补全快捷键为 Tab,其核心模块为 completerABQ.pyc(实现自动补全功能) 和 docstringLookup.pyc(多个字典,保存了方法的路径、参数及说明)。自动补全只支持 CLI 窗口的内核脚本,不支持 GUI 脚本。

Abaqus 的 GUI 二次开发较为繁琐,无法直接调试,查找方法非常不方便。pyCham 的代码补全、参数提示功能很棒,Ctrl+P 参数提示, Ctrl+Q 查看函数、方法文档,很方便。Abaqus 的 python 2.x 解释器经过订制,无法(未找到方法)用于 pyCharm 调试 Abaqus 脚本。

通过生成 Abaqus 代理模块,模拟 Abaqus 各种方法的接口定义,可在通用 Python 解释器中“简单调试”(参数提示、查看文档、语法检查) Abaqus 内核脚本及 GUI 脚本。

开发脚本说明

1. gen_Abaqus_Agent_from_2020_docs.py
运行环境:Python3
脚本说明:通过解析 htm 文件,将 Abauqs 2020 的脚本参考手册转化为代理模块 abaqus.py,输入参数、返回值都有类型及说明。因为部分 htm 文件的编码为 utf-8,为便于处理,选用 python3。
2. gen_AbaqusConstants_Agent.py
运行环境:Abaqus CAE
脚本说明:将 abaqusConstants 模块转为代理模型 abaqusConstants.py。调用内置模块,必须在 Abaqus 环境执行。
3. getAbaquStructure.py
运行环境:Abaqus CAE
脚本说明:(不推荐)借助 docstringLookup 模块生成代理 abaqus.py, xyPlot.py 等,输入参数无类型,无返回值。 调用内置模块,必须在 Abaqus 环境执行。
4. transferAbaquGUIFunctionFromDocumentation.py
运行环境:Python
脚本说明:GUI 参考手册的结构比较复杂(或者说比较混乱),很多类型没有介绍,无法程序自动识别。此脚本只起辅助作用,从 GUI 参考手册的网页中手动复制内容到文本文件,然后用脚本解析文本文件,生成单个类型,然后手动添加到 abaqusGui.py 中,需要注意类型的创建顺序。

脚本内容

1.gen_Abaqus_Agent_from_2020_docs.py

#-*- coding:gbk -*-
from bs4 import BeautifulSoup
import re,os,pickle
'''This script transfers "Abaqus 2020 Scripting Reference Documentatation" to an Agent Model File : abaqus.py

The generated agent "abaqus.py" can be used in pycham for code completion 

1.replace pathDir in __main__   eg:
    pathDir = r'C:\Program Files\Dassault Systemes\SIMULIA2020doc\English\SIMACAEKERRefMap'

2. run this scipt in python3  get "abaqus.py"

3. run gen_AbaqusConstants_Agent.py in abaqus to get 'abaqusConstants.py'

by alienwxy 2020-05-05

'''

def cutInfo(info):
    info = info.strip()
    return  info
    cutLen = 50
    rst = re.findall('[A-Z][A-Z_0-9]+',info)
    if rst and info.startswith('A SymbolicConstant'):
        return ', '.join(rst)
    else:
        if len(info)>cutLen*2:
            return info[:cutLen]+' ... '+info[-cutLen:]
        else:
            return info
#解析目录所有htm文件
def partseDir(dirPath):
    modules = {} #'moduleName': methods, constructs, members
    objects = {}
    failed = []

    # 先更新所有方法
    for fname in os.listdir(dirPath):
        if fname.endswith('.pkl'):
            try:
                with open(os.path.join(dirPath, fname), 'rb') as fp:
                    titleList, methodDict, constructDict, memberList = pickle.load(fp)

                titletype,titlename,titleintro = titleList
                if titletype == 'object':
                    if titlename in objects: #对象已经存在,忽略标题,合并方法,合并成员变量
                        dic =objects[titlename] #对象字典
                        if methodDict:
                            mtddic = dic['methodDict']
                            for name,body in methodDict.items():
                                if name in mtddic: #方法名已存在
                                    if mtddic[name] == body:
                                        continue
                                    else:
                                        pname = name[:-1] if name[-1].isdigit() else name #不含结尾数字的名称
                                        name = pname+str(len([n for n in mtddic.keys() if n.startswith(pname)])) #新名称
                                mtddic[name] = body
                        if memberList:
                            mmblst = dic['memberList']
                            mmblst.extend(memberList)
                    else: #对象不存在,创建标题,方法字典、成员变量列表
                        objects[titlename] = {
                            'intro':titleintro, #''
                            'methodDict':methodDict,#intro reqargs, optArgs, returns
                            'memberList':memberList, #[[n,i,v],[n,i,v]]  []
                        }

                elif titletype =='module':
                    if titlename in modules:  # 对象已经存在,忽略标题,合并方法,合并成员变量
                        dic = modules[titlename]  # 对象字典
                        if methodDict:
                            mtddic = dic['methodDict']
                            for name, body in methodDict.items():
                                if name in mtddic:  # 方法名已存在
                                    if mtddic[name] == body:
                                        continue
                                    else:
                                        pname = name[:-1] if name[-1].isdigit() else name  # 不含结尾数字的名称
                                        name = pname + str(len([n for n in mtddic.keys() if n.startswith(pname)]))  # 新名称
                                mtddic[name] = body
                        if memberList:
                            mmblst = dic['memberList']
                            mmblst.extend(memberList)
                    else:  # 对象不存在,创建标题,方法字典、成员变量列表
                        modules[titlename] = {
                            'intro': titleintro,  # ''
                            'methodDict': methodDict,  # intro reqargs, optArgs, returns
                            'memberList': memberList,  # [[n,i,v],[n,i,v]]  []
                        }
                else:
                    continue

            except:
                print(fname)
                failed.append(os.path.join(dirPath,fname))

    # 更新所有构造器--只针对 objects
    for fname in os.listdir(dirPath):
        if fname.endswith('.pkl'):
            # try:
            with open(os.path.join(dirPath, fname), 'rb') as fp:
                titleList, methodDict, constructDict, memberList = pickle.load(fp)

            titletype, titlename, titleintro = titleList

            if constructDict:
                for name,body in constructDict.items():
                    if body['paths']:
                        for path in body['paths']:
                            objectName = recoverObjectFromPathString(path)
                            if not objectName: continue
                            if objectName in objects:  # 对象已经存在,添加方法
                                dic = objects[objectName]  # 对象字典
                                mtddic = dic['methodDict']
                                if name in mtddic: # 方法名已存在
                                    if mtddic[name] == body:
                                        pass
                                    else:
                                        pname = name[:-1] if name[-1].isdigit() else name  # 不含结尾数字的名称
                                        name = pname + str(len([n for n in mtddic.keys() if n.startswith(pname)]))  # 新名称
                                mtddic[name] = body

                            else:  # 对象不存在,创建标题,方法字典、成员变量列表
                                objects[objectName] = {
                                    'intro': '',  # ''
                                    'methodDict': {name:body},  # intro reqargs, optArgs, returns
                                    'memberList': [],  # [[n,i,v],[n,i,v]]  []
                                }
            # except:
            #     pass

    modules = list(modules.items())
    objects = list(objects.items())
    modules.sort()
    objects.sort()

    writeObjects(objects)
    # writeModules(modules)

    if failed:
        with open('failed.txt','w') as fp:
            for i in failed:
                fp.write('%s\n' % i)

#写入函数
def writeFunction2file(fp, funcName,funcBody):
    intro = funcBody['intro']
    reqArgs = funcBody['reqArgs']
    optArgs = funcBody['optArgs']
    returns = funcBody['returns']

    if reqArgs:
        reqstr = ', '.join([i[0] for i in reqArgs])
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = ', '.join([reqstr, optstr])
        else:
            argstr = reqstr
    else:
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = optstr
        else:
            argstr = ''

    if funcName in ('print','import','class','def'):
        funcName = funcName + '_'
    fp.write('def %s(%s):\n' % (funcName, argstr))
    fp.write('    """\n')
    fp.write('    %s\n\n' % cutInfo(intro))
    if reqArgs:
        for arg, info in reqArgs:
            fp.write('    :param %s: %s\n' % (arg, cutInfo(info)))
    if optArgs:
        for arg, info, value in optArgs:
            fp.write('    :param %s: %s\n' % (arg, cutInfo(info)))
    if returns:
        value, info = returns
        fp.write('    :return %s: %s\n' % (value, cutInfo(info)))

    fp.write('    """\n')

    if returns:
        value, info = returns
        fp.write('    return %s\n' % (value,))
#写入方法
def writeMethod2file(fp,funcName,funcBody):
    intro = funcBody['intro']
    reqArgs = funcBody['reqArgs']
    optArgs = funcBody['optArgs']
    returns = funcBody['returns']

    if reqArgs:
        reqstr = ', '.join([i[0] for i in reqArgs])
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = ', '.join(['self',reqstr, optstr])
        else:
            argstr = ', '.join(['self',reqstr])
    else:
        if optArgs:
            optstr = ', '.join(['%s=%s' % (i[0], i[2]) for i in optArgs])
            argstr = ', '.join(['self', optstr])
        else:
            argstr = 'self'
    if funcName in ('print','import','class','def'):
        funcName = funcName + '_'
    fp.write('    def %s(%s):\n' % (funcName, argstr))
    fp.write('        """\n')
    fp.write('        %s\n\n' % cutInfo(intro))
    if reqArgs:
        for arg, info in reqArgs:
            fp.write('        :param %s: %s\n' % (arg, cutInfo(info)))
    if optArgs:
        for arg, info, value in optArgs:
            fp.write('        :param %s: %s\n' % (arg, cutInfo(info)))
    if returns:
        value, info = returns
        fp.write('        :return %s: %s\n' % (value, cutInfo(info)))

    fp.write('        """\n')

    if returns:
        value, info = returns
        fp.write('        return %s\n' % (value,))
def _writeRepositoryClass2file(fp,className,classBody,objects):
    intro = classBody['intro']
    methodDict = classBody['methodDict']
    memberList = classBody['memberList']
    fp.write('class %s(tuple):\n' % className)
    fp.write('    def __init__(self, rtype="", *args, **kwargs):\n')
    fp.write('        tuple.__init__(self,*args,**kwargs)\n')
    fp.write('        self.rtype=rtype\n')
    fp.write('    def items(self):\n')
    fp.write('        return (("key",self.__getitem__(0)),)\n')
    fp.write('    def keys(self):\n')
    fp.write('        return ("key",)\n')
    fp.write('    def values(self):\n')
    fp.write('        return (self.__getitem__(0),)\n')
    fp.write('    def __getitem__(self,key):\n')
    fp.write('        if not self.rtype:\n')
    fp.write('            return None\n')
    for name, dic in objects:
        fp.write('        elif rtype=="%s":\n' % (name,))
        fp.write('            return %s()\n' % (name,))
    funcNames = list(methodDict.keys())
    funcNames.sort()
    for funName in funcNames:
        funBody = methodDict[funName]
        writeMethod2file(fp,funName,funBody)
def _writeArrayClass2file(fp,className,classBody):
    intro = classBody['intro']
    methodDict = classBody['methodDict']
    memberList = classBody['memberList']
    fp.write('class %s(tuple):\n' % className)
    fp.write('    def __init__(self, *args, **kwargs):\n')
    fp.write('        tuple.__init__(self,*args,**kwargs)\n')
    fp.write('        """%s"""\n' % cutInfo(intro))
    fp.write('    def __getitem__(self,key):\n')
    fp.write('        return %s()\n' % className[:-5])
    if memberList:
        memberList.sort()
        for name,info,value in memberList:
            fp.write('        self.%s = %s # %s\n' % (name.strip(),value,cutInfo(info)))
    funcNames = list(methodDict.keys())
    funcNames.sort()
    for funName in funcNames:
        funBody = methodDict[funName]
        writeMethod2file(fp,funName,funBody)
#写入类
def writeClass2file(fp,className,classBody):
    intro = classBody['intro']
    methodDict = classBody['methodDict']
    memberList = classBody['memberList']
    fp.write('class %s(object):\n' % className)
    fp.write('    def __init__(self, *args, **kwargs):\n')
    fp.write('        """%s"""\n' % cutInfo(intro))
    if memberList:
        memberList.sort()
        for name,info,value in memberList:
            fp.write('        self.%s = %s # %s\n' % (name.strip(),value,cutInfo(info)))
    funcNames = list(methodDict.keys())
    funcNames.sort()
    for funName in funcNames:
        funBody = methodDict[funName]
        writeMethod2file(fp,funName,funBody)



#写入abauqs对象
def writeObjects(objects,subdir='agent'):
    if not os.path.exists(subdir):
        os.mkdir(subdir)
    with open(os.path.join(subdir,'abaqus.py'),'w',encoding='utf-8') as fp:
        fp.write('# -*- coding:utf-8 -*-\n')
        fp.write('from abaqusConstants import *\n')
        for objectName, objectDict in objects:
            if objectName == 'Abaqus':
                methodDict = objectDict['methodDict']
                funNames = list(methodDict.keys())
                funNames.sort()
                for funName in funNames:
                    if funName[0].islower():
                        writeFunction2file(fp, funName, methodDict[funName])
            elif objectName == 'Repository':
                _writeRepositoryClass2file(fp,objectName,objectDict,objects)
            elif objectName.endswith('Array'):
                _writeArrayClass2file(fp,objectName,objectDict)
            else:
                writeClass2file(fp,objectName,objectDict)
        fp.write('mdb = Mdb()\n')
        fp.write('session = Session()\n')
#写入模块
def writeModules(modules,subdir='agent'):
    if not os.path.exists(subdir):
        os.mkdir(subdir)
    for modulename,modulebody in modules:
        with open(os.path.join(subdir,modulename+'.py'),'w',encoding='utf-8') as fp:
            fp.write('# -*- coding:utf-8 -*-\n')
            info = modulebody['intro']
            fp.write('"""\n%s\n"""\n' % cutInfo(info))
            methodDict =modulebody['methodDict']
            funNames = list(methodDict.keys())
            funNames.sort()
            for funName in funNames:
                writeFunction2file(fp, funName, methodDict[funName])
            #无成员
            pass
#解析单个html文件
def parseHtmlFile(fileName):
    soup = BeautifulSoup(open(fileName,'r',encoding='utf-8'), 'lxml')

    titleList = getTitle(soup)
    methodDict = getMethods(soup)
    constructDict = getConstructs(soup)
    memberList = getMembers(soup)

    return  titleList, methodDict, constructDict, memberList

#写入单个文件--调试
def writeHtmlFile(fileName):
    titleList, methodDict, constructDict, memberList = parseHtmlFile(fileName)
    if not titleList[0]: return

    with open(fileName+'.txt','w',encoding='utf-8') as fp:
        fp.write('===========================titleList:\n')
        fp.write('titletype:%s\n' % titleList[0])
        fp.write('titlename:%s\n' % titleList[1])
        fp.write('titleintro:%s\n' % titleList[2])

        fp.write('===========================methodDict:\n')
        if methodDict:
            for methodName,body in methodDict.items():
                fp.write('--------------%s--------------\n' % methodName)
                fp.write('intro:%s\n' % body['intro'])
                fp.write('++++reqArgs:\n')
                if body['reqArgs']:
                    for arg,info in body['reqArgs']:
                        fp.write('%-20s  %s\n' % (arg,info))
                fp.write('++++optArgs:\n')
                if body['optArgs']:
                    for arg,info,value in body['optArgs']:
                        fp.write('%-20s = %-20s  %s\n' % (arg,value,info))
                fp.write('++++returns\n')
                fp.write('%s  %s\n' % tuple(body['returns']))
        fp.write('===========================constructDict:\n')
        if constructDict:
            for name,body in constructDict.items():
                fp.write('--------------%s--------------\n' % name)
                fp.write('intro:%s\n' % body['intro'])
                fp.write('++++paths:\n')
                if body['paths']:
                    for path in body['paths']:
                        fp.write('%s\n' % path)
                fp.write('++++reqArgs:\n')
                if body['reqArgs']:
                    for arg,info in body['reqArgs']:
                        fp.write('%-20s  %s\n' % (arg,info))
                fp.write('++++optArgs:\n')
                if body['optArgs']:
                    for arg,info,value in body['optArgs']:
                        fp.write('%-20s = %s  %s\n' % (arg,value,info))
                fp.write('++++returns\n')
                value,info = body['returns']
                fp.write('%s  %s\n' % (value,info))
        fp.write('===========================members:\n')
        if memberList:
            for name,info,value in memberList:
                fp.write('%-20s  %s  %s\n' % (name, value, info))
    with open(fileName+'.pkl','wb') as fp:
        pickle.dump([titleList, methodDict, constructDict, memberList], fp)
#写入文件夹--调试
def writeDir(dirPath):
    cnt = 0
    for fname in os.listdir(dirPath):
        lfname = fname.lower()
        if lfname.endswith('cpp.htm') or lfname.endswith('cpp.html'):
            continue
        if lfname.endswith('htm') or lfname.endswith('html'):
            cnt+=1
            if cnt%10 == 0: print('%d' % cnt)
            try:
                writeHtmlFile(os.path.join(dirPath,fname))
            except:
                print(os.path.join(dirPath,fname))
                raise
#查看所有路径
def writePaths(dirPath):
    paths = []
    titles = []
    for fname in os.listdir(dirPath):
        if fname.endswith('.pkl'):
            with open(os.path.join(dirPath,fname),'rb') as fp:
                titleList, methodDict, constructDict, memberList = pickle.load(fp)
                titles.append(titleList[:2])
            if constructDict:
                for name,body in constructDict.items():
                    if body['paths']:
                        paths.extend(body['paths'])

    upaths=list(set(paths))
    upaths.sort()
    with open('paths.txt', 'w') as fp:
        for path in upaths:
            fp.write('%s\n' % path)

    with open('paths.remap.txt','w') as fp:
        for path in upaths:
            fp.write('%s   %s\n' % (recoverObjectFromPathString(path),path))
    with open('titles.txt','w') as fp:
        for t,n in titles:
            fp.write('type:%s - name:%s\n' % (t,n))
#从访问路径恢复对象类型
def recoverObjectFromPathString(path):
    if ' ' in path: #模块
        return  'Abaqus'
    if '.' not in path: #单个对象,全部归入 abaqus 模块,自身就是构造器
        #Leaf displayGrooupMDBToolset
        #Leaf displayGrooupODBToolset
        #ElemType mesh
        #Region regiontoolset
        # caePrefsAccess caePrefsAccess
        return 'Abaqus'
    txt = path.split('.')[-2].strip()
    txt = re.search('\w+',txt).group() #清理中括号
    # hes -->h
    # les --> le
    # des --> de
    # mes --> me
    # ses -> s
    # ies --> y
    # res --> re
    if txt == 'iterations': return 'AdaptivityIteration'
    if txt == 'viscous': return 'Viscous'
    if txt == 'eos': return 'Eos'
    if txt == 'odbAccess': return 'OdbAccess'
    if txt == 'sketches': return  'ConstrainedSketch'
    if txt.endswith('hes'): return txt[0].upper() + txt[1:-2]
    if txt.endswith('les'): return txt[0].upper() + txt[1:-1]
    if txt.endswith('des'): return txt[0].upper() + txt[1:-1]
    if txt.endswith('mes'): return txt[0].upper() + txt[1:-1]
    if txt.endswith('ses'): return txt[0].upper() + txt[1:-2]
    if txt.endswith('ies'): return txt[0].upper() + txt[1:-3] + 'y'
    if txt.endswith('res'): return txt[0].upper() + txt[1:-1]
    if txt.endswith('s'): return txt[0].upper() + txt[1:-1]

    if txt == 'rootAssembly': return 'Assembly'
    return txt[0].upper()+txt[1:]
    # print(path)
    # return txt




#获取标题
def getTitle(soup): #'', '',''    type,name,intro
    # title = soup.title.text
    try:
        title = soup.h1.text
        if not title: return '','',''
    except:
        return '', '', ''

    if 'object' in title:
        titleType = 'object'
        titleName = re.search('\w+', title).group()
    elif 'module' in title:
        titleType = 'module'
        titleName = re.search('\w+', title).group()
    else:
        titleType = ''
        titleName = ''

    a = soup.find(name='table', class_='DocThemeIntro')
    # titleIntro = re.sub('\s+', ' ', a.text) if a else ''
    lst = []
    for i in a.strings:
        if 'topics' in i:
            break
        else:
            lst.append(i)
    txt = '\n'.join(lst)
    titleIntro = re.sub('\s+', ' ', txt)

    return titleType, titleName, titleIntro
#获取返回值
def getRtnArgs(rtndiv): #value, valueinfo
    if rtndiv.attrs['class'][-1] == 'nopyreturnsect':
        return [None, '']
    else: #pyreturnsect
        lst = []
        for i in rtndiv.contents:
            if i.name != 'h3':
                try:
                    lst.append(i.text)
                except:
                    pass

        valueinfo = '\n'.join(lst)
        if valueinfo:
            valueinfo = re.sub('\s+',' ',valueinfo)
            return [getMemberType(valueinfo), valueinfo ]
        else:
            return [None, '']
#获得变量类型
def getMemberType(instr): #变量或成员的说明
    # 默认值的表述方式
    # The whole assembly is queried by default.
    # The default value is LOW.
    # The default value is False.
    # The default value is an integer.
    # The user-specified density should be greater than 0.
    # By default if the moments of inertia are not being evaluated about the center of mass, they will be evaluated about the origin.

    # 参数类型的说明
    # A MeshElementArray, CellArray, FaceArray, Ed
    # A SymbolicConstant specifying     符号
    # A String specifying the name      字符串
    # A Boolean specifying whether      布尔值
    # A positive Integer specifying     正整数
    # An Int specifying that feature    整数
    # A Float specifying which gives a  浮点数
    # A double value specifying the     浮点数

    # A tuple of three floats specifying th   浮点数元组   list  List  Tuple
    # A tuple of dictionary objects           字典元组

    # A sequence of Ints.                    序列
    # A sequence of Strings
    # A sequence of PartInstance objects
    # A sequence of PartInstance objects

    # A ConnectorOrientationArray object.
    # A Dictionary object with the following items  字典
    # A VertexArray object specifyi
    # An EdgeArray object specifyin
    # A MeshElementArray object spe
    # A MeshNodeArray object specif
    # A PartInstance object specify
    # An EngineeringFeature object.
    # A ConnectorOrientationArray o
    # A SectionAssignmentArray obje

    # A repository of PartInstance objects
    # A repository of Datum objects
    # A repository of Feature objec
    # A repository of Surface objec
    # A repository of Set objects.
    # A repository of Skin objects
    # A repository of Stringer obje
    # A repository of ReferencePoin
    # A repository of ModelInstance

    instr = re.sub('\s+',' ',instr)

    # 有默认值的情况,直接返回取值
    rst = ''
    if 'Possible values' in instr:
        r = re.findall('Possible values are (\w+)', instr)
        if r: rst = r[0]
    if 'The default value is' in instr:
        r = re.findall('The default value is (\w+)', instr)
        if r: rst = r[0]
    if rst.isupper() or rst.isdigit(): #符号常量 数字
        return rst
    try:
        eval(rst)
        return rst
    except:
        # return None #抑制定义顺序不同导致的出错
        pass

    ptn = re.compile('\w+')
    rst = ptn.findall(instr)
    if len(rst) < 2:
        # print(instr)
        # raise(ValueError, instr)
        return  None

    #无默认值或无法识别默认值,用对象表示
    mType = rst[1]
    lmType = mType.lower()

    #内建类型
    if lmType in ('int',): return 0
    if lmType in ('float', 'double'): return 0.0
    if lmType in ('string', ): return 'str()'
    if lmType in ('boolean', 'bool','abaqusboolean'): return True
    if lmType in ('dictionary', 'dict'): return 'dict()'
    if lmType in ('tuple', 'list', 'sequence'): return 'tuple()'
    if lmType in ('positive', 'negative'):
        if rst[2] == 'Integer' :
            return 1
        else:
            return  0.0

    #Abaqus类型
    if mType[0].isupper():
        return mType+'()'
    elif lmType == 'repository':
        return 'Repository("%s")' % rst[3]
        # return 'Repository(%s)' % rst[3]
    else:
        # print mType, instr
        # raise TypeError
        return  None
#获取所有方法
def getMethods(soup): #{}  {xxx}
    methodDict = {}

    for mtd in soup.find_all(class_="pymethodsect"):
        #方法名称
        methodName = re.search('\w+',mtd.h2.text).group() #方法名及参数

        #方法主体
        # methodBody = mtd.div #pymethodsect-body
        methodBody = mtd.find(class_='pymethodsect-body') #pymethodsect-body
        if not methodBody:
            print('Method %s is invalid!' % methodName)
            # for parent in soup.parents:
            #     print(parent.text)
            # raise
            continue

        #方法介绍
        lst = []
        for i in methodBody.contents:
            if i.name != 'div':
                try:
                    lst.append(i.text)
                except:
                    pass
            else:
                break
        methodIntro = '\n'.join(lst)
        methodIntro = re.sub('\s+', ' ', methodIntro)

        #无参数
        # rst = methodBody.find(class_='nopymethodarglist')
        # rst = methodBody.find(class_=['nopymethodarglistreq', 'pymethodarglistreq', 'nopymethodarglistopt', 'pymethodarglistopt'])
        # if rst:
        reqArgs = []
        optArgs = []
        #必须参数
        #无 nopymethodarglistreq
        #有 pymethodarglistreq
        reqdiv = methodBody.find(class_='nopymethodarglistreq')
        if reqdiv: reqArgs = []
        reqdiv = methodBody.find(class_='pymethodarglistreq')
        if reqdiv:
            dl = reqdiv.dl
            if dl:
                names = [i.text.strip() for i in dl.find_all(name='dt')]
                infos = [re.sub('\s+', ' ', i.text) for i in dl.find_all(name='dd')]
                reqArgs = list(zip(names, infos))

        #可选参数
        #无 nopymethodarglistopt
        #有 pymethodarglistopt
        optdiv = methodBody.find(class_='nopymethodarglistopt')
        if optdiv: optArgs = []
        optdiv = methodBody.find(class_='pymethodarglistopt')
        if optdiv:
            dl = optdiv.dl
            if dl:
                names = [i.text.strip() for i in dl.find_all(name='dt')]
                infos = [re.sub('\s+', ' ', i.text) for i in dl.find_all(name='dd')]
                values = [getMemberType(v) for v in infos]  # 默认值
                optArgs = list(zip(names, infos, values))

        #返回值
        # 有 pyreturnsect
        # 无 nopyreturnsect
        rtndiv = methodBody.find(class_='pyreturnsect')
        if rtndiv:
            returns = getRtnArgs(rtndiv)
        else:  # nopyreturnsect
            returns = [None, '']  # value, info

        if methodName in methodDict:
            print('%s already exists' % methodName)
            lst = [key for key in methodDict.keys() if key.startswith(methodName)]
            methodDict[methodName + str(len(lst))] = {
                'intro': methodIntro,  # 方法介绍 str
                'reqArgs': reqArgs,  # 必须参数表 []  [[arg1,info1],[arg2,info2]]
                'optArgs': optArgs,  # 可选参数表 []  [[arg1,info1,value1],[arg2,info2,value2]]
                'returns': returns,  # 返回值列表 [None, '']   [Value, intor]
            }
        else:
            methodDict[methodName] = {
                'intro': methodIntro,  # 方法介绍 str
                'reqArgs': reqArgs,  # 必须参数表 []  [[arg1,info1],[arg2,info2]]
                'optArgs': optArgs,  # 可选参数表 []  [[arg1,info1,value1],[arg2,info2,value2]]
                'returns': returns,  # 返回值列表 [None, '']   [Value, intor]
            }
    return methodDict
#获取构造器
def getConstructs(soup): #{}  {xxx}
    constructDict = {}

    for mtd in soup.find_all(class_="pyconstructsect"):
        #构造器名称
        constructName = re.search('\w+',mtd.h2.text).group() #方法名及参数

        #构造器主体
        # constructBody = mtd.div #pyconstructsect-body
        constructBody = mtd.find(class_='pyconstructsect-body') #pyconstructsect-body
        if not constructBody:
            print('Construct %s is invalid!' % constructName)
            continue
        #构造器介绍
        lst = []
        for i in constructBody.contents:
            if i.name != 'div':
                try:
                    lst.append(i.text)
                except:
                    pass
            else:
                break
        structIntro = '\n'.join(lst)
        structIntro = re.sub('\s+', ' ', structIntro)

        #构造器访问路径 列表
        path = constructBody.find(class_='pypath')
        try:
            paths = []
            for ppre in path.find_all(name='pre'):
                if ppre is None: continue
                txt = re.sub('\\\\\n','',ppre.text)
                # paths = re.findall('[\.\[\]\w]+',txt)
                paths.extend([i.strip() for i in txt.split('\n')])
            for ppre in path.find_all(name='p'):
                if ppre is None: continue
                txt = re.sub('\\\\\n','',ppre.text)
                # paths = re.findall('[\.\[\]\w]+',txt)
                paths.append(txt)
        except:
            paths = []


        #无参数
        # rst = constructBody.find(class_='nopyctorarglist')
        # rst = constructBody.find(class_=['nopyctorarglistreq', 'pyctorarglistreq', 'nopyctorarglistopt', 'pyctorarglistopt'])
        # if rst:
        reqArgs = []
        optArgs = []

        #必须参数
        # 无参数 nopyctorarglistreq
        # 1个   pyctorarglistreq
        # 多个   pyctorarglistreq
        reqdiv = constructBody.find(class_='nopyctorarglistreq')
        if reqdiv: reqArgs = []
        reqdiv = constructBody.find(class_='pyctorarglistreq')
        if reqdiv:
            dl = reqdiv.dl
            if dl:
                names = [i.text.strip() for i in dl.find_all(name='dt')]
                infos = [re.sub('\s+', ' ', i.text) for i in dl.find_all(name='dd')]
                reqArgs = list(zip(names, infos))
        #可选参数
        # 无参数 nopyctorarglistopt
        # 1个   pyctorarglistopt
        # 多个  pyctorarglistopt
        optdiv = constructBody.find(class_='nopyctorarglistopt')
        if optdiv: optArgs = []
        optdiv = constructBody.find(class_='pyctorarglistopt')
        if optdiv:
            dl = optdiv.dl
            if dl:
                names = [i.text.strip() for i in dl.find_all(name='dt')]
                infos = [re.sub('\s+', ' ', i.text) for i in dl.find_all(name='dd')]
                values = [getMemberType(v) for v in infos] #默认值
                optArgs = list(zip(names, infos, values))

        # 返回值
        # 有 pyreturnsect
        # 无 nopyreturnsect
        rtndiv = constructBody.find(class_='pyreturnsect')
        if rtndiv:
            returns = getRtnArgs(rtndiv)
        else: #nopyreturnsect
            returns = [None,''] #value, info

        if constructName in constructDict:
            print('%s already exists' % constructName)
            # print(str(paths))
            lst = [key for key in constructDict.keys() if key.startswith(constructName)]
            constructDict[constructName+str(len(lst))] = {
                'intro': structIntro,  # 构造器介绍 str
                'paths': paths,  # 路径列表 [path1, path2]  []
                'reqArgs': reqArgs,  # 必须参数表 []  [[arg1,info1],[arg2,info2]]
                'optArgs': optArgs,  # 可选参数表 []  [[arg1,info1,value1],[arg2,info2,value2]]
                'returns': returns,  # 返回值列表 [None, '']   [Value, intor]
            }
        else:
            constructDict[constructName] = {
                'intro':structIntro, #构造器介绍 str
                'paths':paths, #路径列表 [path1, path2]
                'reqArgs':reqArgs, #必须参数表 []  [[arg1,info1],[arg2,info2]]
                'optArgs':optArgs, #可选参数表 []  [[arg1,info1,value1],[arg2,info2,value2]]
                'returns':returns, #返回值列表 [None, '']   [Value, intor]
            }
    return constructDict
#获取所有成员
def getMembers(soup): #[]  [[name,info,value],[name,info,value]]
    mmb = soup.find(class_="pymembersect")
    if mmb is None: return  []

    body = mmb.find(class_='pymembersect-body')
    if body is None: return []

    dl = body.find(class_='pymemberdatalist')
    if dl is None: return []

    names = [i.text for i in dl.find_all(name='dt')]
    infos = [re.sub('\s+', ' ', i.text) for i in dl.find_all(name='dd')]
    values = [getMemberType(s) for s in infos]
    return list(zip(names, infos, values))

#清理临时文件
def clean(pathDir):
    for fname in os.listdir(pathDir):
        lfname = fname.lower()
        if lfname.endswith('.htm.txt') or lfname.endswith('.html.txt') or lfname.endswith('.pkl'):
            os.remove(os.path.join(pathDir,fname))
    for fname in ('failed.txt', 'paths.txt','titles.txt', 'paths.remap.txt'):
        if os.path.exists(fname):
            os.remove(fname)

if __name__ == '__main__':
    pathDir = r'C:\Program Files\Dassault Systemes\SIMULIA2020doc\English\SIMACAEKERRefMap'
    writeDir(pathDir)
    writePaths(pathDir)
    partseDir(pathDir)
    clean(pathDir)

2. gen_AbaqusConstants_Agent.py

# -*- coding:utf-8 -*-
'''
run this file in abaqus cae or abaqus python ,generate abaqusConstants agent.

by alienwxy 2020-05-05
'''
import types,os
import abaqusConstants
subdir = 'agent'
if not os.path.exists(subdir):
    os.mkdir(subdir)
with file(os.path.join(subdir,'abaqusConstants.py'),'w') as fp:
    fp.write('class SymbolicConstant(object):\n')
    fp.write('    def __init__(self,instr=""):\n')
    fp.write('        self.text = instr\n')
    for name in dir(abaqusConstants):
        if name.isupper():
            fp.write('%s = SymbolicConstant("%s")\n' % (name,name))
    fp.write('NO = OFF = False\n')
    fp.write('ON = YES = True\n')

3. getAbaquStructure.py

# -*- coding:utf-8 -*-
'''
        abaqus class method agent for pyCharm
                
1. run this file in abaqus cae
2. copy  the files in abaqusAgent folder to xxx/Lib/site-packages
3. enjoy!

by alienwxy 2020-04-27  

Usage:

from abaqus import *
from abaqusConstants import *
import mesh
'''
import types,os
import abaqusConstants

def getMethodObjectList():
    import docstringLookup as dlk
    methodDict = {}
    objectDict = {}
    
    #get diction
    for name in dir(dlk):
        module = getattr(dlk,name)
        if type(module) is types.ModuleType:
            if hasattr(module,'objectDocstringTable'):
                dic = getattr(module,'objectDocstringTable')
                objectDict.update(dic)
            if hasattr(module,'methodDocstringTable'):
                dic = getattr(module,'methodDocstringTable')
                methodDict.update(dic)
    methodList = [(k,v) for k,v in methodDict.items()]
    objectList = [(k,v) for k,v in objectDict.items()]
    methodList.sort()
    objectList.sort()
    return methodList,objectList

def write2Txt(methodList,objectList,subDir='abaqusAgent'):
    if not os.path.exists(subDir):
        os.mkdir(subDir)
    with file(os.path.join(subDir,'abaqusMethodList.txt'),'w') as fp:
        for k,v in methodList:
            fp.write('%-60s\t%s\n' % (k,v))
    with file(os.path.join(subDir,'abaqusObjectList.txt'),'w') as fp:
        for k,v in objectList:
            fp.write('%-60s\t%s\n' % (k,v))
                    

def getMethodArgs(argstr):
    # 'name, edges <, startPoint, flipDirection, pointCreationMethod>'
    # 'stepName <, loadCaseNames, magnitude, amplitude>'
    # 'stepName <, allowGrowth>'
    # '<useCut, printResults>'
    # '<useCut>'
    # 'center, radius'
    # 'mask'
    # 'keyword argument not implemented'
    # ''
    argstr = argstr.strip()
    if argstr == '' or 'not implemented' in argstr:
        return ''
    if '<' not in argstr:
        return argstr
    #optional
    if argstr.startswith('<'):
        optargs =  argstr.lstrip('<').rstrip('>').strip()
        return ', '.join(['%s=None' % (arg.strip(),) for arg in optargs.split(',')])
    keyargs,optargs = argstr.split('<,')
    keyargs = keyargs.strip()
    optargs = optargs.strip().rstrip('>').strip()
    if ',' in optargs: #multi 
        optargs = ', '.join(['%s=None' % (arg.strip(),) for arg in optargs.split(',')])
    else:
        optargs = '%s=None' % optargs
    return '%s, %s' % (keyargs,optargs)
def selfMethodArgs(argstr):
    s = getMethodArgs(argstr)
    if s:
        return 'self, ' + s
    else:
        return 'self'

def write2Python(methodList,subDir='abaqusAgent'):
    # XYPlot.previous
    # sys.modules['odbAccess'].openOdb   odbAccess 的函数
    # Abaqus.Mdb      abaqus 模块函数
    # Odb.Part        odbAccess 模块 的类 以Odb开头
    # OdbStep.setDefaultField
    modules      = {} #moduleName: [ [functionName,functionArgs] ]
    abaqusFunctions = [] #[ [functionName,functionArgs]]
    odbAccesFunctions = [] #[ [functionName,functionArgs]]
    abaqusConstantsFunctions = []#[ [functionName,functionArgs]]
    
    odbAccesClasses = {} #className: [[methodName,methodArgs]]
    classes      = {} #className: [[methodName,methodArgs]]
    for name,lst in methodList:
        if 'modules' in name:
            if 'odbAccess' in name:
                odbAccesFunctions.append([name.split('.')[-1], getMethodArgs(lst[0])])
            elif 'abaqusConstants' in name:
                abaqusConstantsFunctions.append([name.split('.')[-1], getMethodArgs(lst[0])])
            else:
                modName = name.split("'")[1]
                if modName not in modules:
                    modules[modName] = []
                modules[modName].append([name.split('.')[-1], getMethodArgs(lst[0])])
        elif name.startswith('Odb'): #odbAccesClasses
            clsName,methodName = name.split('.')
            if clsName not in odbAccesClasses:
                odbAccesClasses[clsName] = []
            odbAccesClasses[clsName].append([methodName, selfMethodArgs(lst[0])])
        elif name.startswith('Abaqus'): #abaqusFunctions
            funcName = name.split('.')[-1]
            if funcName != 'Mdb': #Mbd('<pathName>')
                abaqusFunctions.append([name.split('.')[-1], getMethodArgs(lst[0])])
        else:
            clsName,methodName = name.split('.')
            if clsName not in classes:
                classes[clsName] = []
            classes[clsName].append([methodName, selfMethodArgs(lst[0])])
    
    if not os.path.exists(subDir):
        os.mkdir(subDir)
        
    def writeAbaqusConstants():
        with file(os.path.join(subDir,'abaqusConstants.py'),'w') as fp:
            for fname,fargs in abaqusConstantsFunctions:
                fp.write('def %s(%s):\n' % (fname,fargs))
                fp.write('    pass\n')  
            for name in dir(abaqusConstants):
                if name.isupper():
                    fp.write('%s = "%s"\n' % (name,name))
    def writeOdbAccess():
        with file(os.path.join(subDir,'odbAccess.py'),'w') as fp:
            writeClasses(fp,odbAccesClasses)
            for fn,fa in odbAccesFunctions:
                writeFunction(fp,fn,fa)
    def writeModules():
        for module in modules.keys():
            with file(os.path.join(subDir,module+'.py'),'w') as fp:
                for n,a in modules[module]:
                    writeFunction(fp,n,a)
    def writeAbaqus():
        with file(os.path.join(subDir,'abaqus.py'),'w') as fp:
            writeClasses(fp,classes)
            writeClasses(fp,odbAccesClasses)
            for n,a in abaqusFunctions:
                writeFunction(fp,n,a)
            fp.write('mdb = Mdb()\n')
            fp.write('session = Session()\n')
    
    writeAbaqusConstants()
    writeOdbAccess()
    writeModules()
    writeAbaqus()
    with file(os.path.join(subDir,'__init__.py'),'w') as fp:
        fp.write('\n')
    with file(os.path.join(subDir,'deleteAbaqusAgent.bat'),'w') as fp:
        for name in modules.keys():
            fp.write('del %s.py; %s.pyc\n' % (name,name))
        fp.write('del abaqus.py;abaqus.pyc;abaqusConstants.py;abaqusConsta.pyc;odbAccess.py;odbAccess.pyc\n')
        fp.write('del deleteAbaqusAgent.bat\n')
def writeFunction(fp,functionName,functionArgs):
    if functionName in ('print','as','if','class','def','None','True','False','for'):
        functionName += '_confilictWithPythonReserveVars'
    fp.write('def %s(%s):\n' % (functionName,functionArgs))
    fp.write('    pass\n')
def writeClass(fp,clsName,clsMethods):
    fp.write('class %s(object):\n' % clsName)
    fp.write('    def __init__(self, *args, **kwargs): pass\n')
    for mtdname,mtdarg in clsMethods:
        if mtdname in ('print','as','if','elif','else','class','def','None','True','False','for','while'):
            mtdname += '_confilictWithPythonReserveVars'
        fp.write('    def %s(%s):\n' % (mtdname, mtdarg))
        fp.write('        return %s(%s)\n' % (mtdname, mtdarg))
    fp.write('    pass\n')
def writeClasses(fp,classesDict):
    keys = classesDict.keys()
    keys.sort()
    for key in keys:
        value = classesDict[key]
        writeClass(fp,key,value)

if __name__ == '__main__':
    m,o = getMethodObjectList()
    write2Txt(m,o)
    write2Python(m)

4.transferAbaquGUIFunctionFromDocumentation.py

# -*- coding:gbk -*-
import re
def handleFlags(fileName='flags.txt'):
    ''' 
    DEF_SWATCH_CURSOR 
    Color swatch drag cursor.
     
    DEF_MOVE_CURSOR 
    Move cursor.
     
    DEF_DRAGH_CURSOR 
    Resize horizontal edge.
     
    DEF_DRAGV_CURSOR 
    Resize vertical edge.
     
    DEF_DRAGTL_CURSOR 
    Resize upper-leftcorner.
     
    DEF_DRAGBR_CURSOR 
    Resize bottom-right corner.
     
    DEF_DRAGTR_CURSOR 
    Resize upper-right corner.
    '''
    with file(fileName,'r') as fp:
        dat = [l.strip() for l in fp.readlines() if len(l.strip()) > 0]
        
    nums = int(len(dat)/2)
    with file(fileName+'.py','w') as fp:
        for i in range(nums):
            fp.write('%-40s = %2d # %s\n' % (dat[2*i], i, dat[2*i+1]))
            
            
def handleFunctions(fileName='temp.txt'):
    '''不含尾部flags
        
    AFXApp
      

     
     


     
    This class is responsible forproviding some high-level GUI controlmethods.
     
     

     







    AFXApp(appName=Abaqus/CAE, vendorName=SIMULIA,productName='', majorNumber=-1, minorNumber=-1,updateNumber=-1, prerelease=False)


    Constructor.

    Argument Type Default Description 
    appName String Abaqus/CAE Application registry key. 
    vendorName String SIMULIA Vendor registry key. 
    productName String '' Product name. 
    majorNumber Int -1 Version number. 
    minorNumber Int -1 Release number. 
    updateNumber Int -1 Update number. 
    prerelease Bool False Official/Prerelease flag. 

     







    create()


    Creates windows for theapplication.

    Reimplemented fromFXApp.

     







    getAFXMainWindow()


    Returns a pointer to theAFXMainWindow.

     







    getBasePrerelease()


    Returns True if the base product isa prerelease.

     







    getBaseProductName()


    Returns the base productname.

     







    getBaseVersionNumbers(majorNumber, minorNumber,updateNumber)


    Returns the base product's major,minor, and update numbers.

    Argument Type Default Description 
    majorNumber Int   Version number. 
    minorNumber Int   Release number. 
    updateNumber Int   Update number. 

     







    getKernelInitializationCommand()


    Returns the command string thatwill be issued upon application startup.

     







    getPrerelease()


    Returns True if this is aprerelease.

     







    getProductName()


    Returns the productname.

     







    getVersionNumbers()


    Returns the major, minor, andupdate numbers.

     







    init(argc,argv)


    Initializes the application andconnects to the kernel.

    Argument Type Default Description 
    argc Int     
    argv String     

     







    isLocked()


    Returns True if the GUI is lockedor False if otherwise.

    Reimplemented fromFXApp.

     







    isProductCAE()


    Returns True if the base product isAbaqus/CAE.

     







    isProductViewer()


    Returns True if the base product isAbaqus/Viewer.

     







    isStudentEdition()


    Returns True if the base product isa student edition.

     







    lock()


    Locks the GUI (normally used duringcommand and mode processing).

     







    run()


    Runs the main application eventloop until stop() is called,.

    Reimplemented fromFXApp.

     







    runUntil(condition)


    Run an event loop till some flagbecomes non-zero.

    Reimplemented fromFXApp.

    Argument Type Default Description 
    condition Int     

     







    unlock()


    Unlocks theGUI.

     




    '''
    #清理空行
    with file(fileName,'r') as fp:
        dat = [l.strip() for l in fp.readlines() if len(l.strip())>0]
    
    def isMethodDefinitionLine(instr):
        if instr.endswith(')'):
            return True
        else:
            return False
    with file(fileName+'.py','w') as fp:
        isWritingFunction = False
        isAddParam = False
        fp.write('class %s(object):\n' % dat[0])
        fp.write('    """\n')
        fp.write('    %s\n' % dat[1])
        fp.write('    """\n')
        for l in dat[2:]:
            if isMethodDefinitionLine(l):
                isAddParam = False
                if isWritingFunction: 
                    fp.write('        """\n')
                isWritingFunction = True
                
                id = l.index('(')
                name = l[:id]
                arg = l[id+1:]
                # name,arg = l.split('(')
                if arg == ')':
                    fp.write('    def %s(self):\n' % (name,))
                else:
                    fp.write('    def %s(self, %s:\n' % (name,arg))
                fp.write('        """\n')
            else:
                if isWritingFunction:
                    if l.startswith('Argument'):
                        isAddParam = True
                        fp.write('        %s\n\n' % (l,))
                        continue
                    if isAddParam:
                        fp.write('        @param %s\n\n' % (l,))
                        continue
                    fp.write('        %s\n\n' % (l,))
                else:
                    fp.write('%s\n' % (l,))
        fp.write('        """\n')
# handleFunctions()
# handleFlags()

def getUltiMate():
    import re
    with file('abaqusGui.py','r') as fp:
        d = fp.read()
    ptn = re.compile('[A-Z]\w+')
    rst = ptn.findall(d)
    rs = [r for r in rst if r.isupper()]
    rs = list(set(rs))
    rs.sort()
    # with file('consts.txt','w') as fp:
        # for i,r in enumerate(rs):
            # fp.write('%-40s = %4d\n' % (r,i))
    return set(rs)
# getUltiMate()

def getConstants2():
    import re
    with file('abaqusGui.py','r') as fp:
        d = fp.readlines()
    lsts = [] #name, value, info
    
    for l in d:
        if '=' in l and '#' in l and l.startswith('    '):
            lsts.append(l.lstrip())
    
    ptn = re.compile('[A-Z]\w+')
    
    clst = set([ptn.findall(l)[0] for l in lsts])
    aset = getUltiMate()
    aset = aset.difference(clst)
    
    with file('consts.txt','w') as fp:
        for i,v in enumerate(list(aset)):
            if len(v) >1:
                fp.write('%-40s = %4d\n' % (v,i))
        fp.write('\n'*4)
        for i,r in enumerate(lsts):
            fp.write(r)
# getConstants2()


def transferParam():
    '''    @param owner	FXWindow
    改为 
        :param owner:   FXWindow'''
    with file('abaqusGui.py','r') as fp:
        d = fp.readlines()
   
    ptn = re.compile('\w+')
    
    with file('abaqusGui_new.py','w') as fp:
        for l  in d:
            if '@param' in l:
                l = l.replace('@',':')
                varName = ptn.findall(l)[1]
                l = l.replace(varName,varName+':')
            fp.write(l)
# transferParam()
  • 2
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值