/** * Tencent is pleased to support the open source community by making Tars available. * * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved. * * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * https://opensource.org/licenses/BSD-3-Clause * * Unless required by applicable law or agreed to in writing, software distributed * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ #include "tars2python.h" // begin modify #include "util/tc_md5.h" #include "util/tc_file.h" #include "util/tc_common.h" #include // end modify #define TAB g_parse->getTab() #define INC_TAB g_parse->incTab() #define DEL_TAB g_parse->delTab() const string MAP_PREFIX = "mapcls_"; const string VEC_PREFIX = "vctcls_"; string Tars2Python::generatePython(const EnumPtr &pPtr, const std::string &sNamespace) { std::ostringstream s; s << TAB << "class " << pPtr->getId() << ":" << endl; INC_TAB; int nenum = -1; vector& member = pPtr->getAllMemberPtr(); for (size_t i = 0; i < member.size(); i++) { if (member[i]->hasDefault()) { nenum = tars::TC_Common::strto(member[i]->def()); } else { nenum++; } s << TAB << member[i]->getId()<< " = " << tars::TC_Common::tostr(nenum) << ";" << endl; } DEL_TAB; return s.str(); } std::string Tars2Python::toFunctionName(const TypeIdPtr & pPtr, const string & sName) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); if (bPtr) { switch (bPtr->kind()) { case Builtin::KindBool : return "tarscore.boolean"; case Builtin::KindString: return "tarscore.string"; case Builtin::KindByte: return "tarscore.int8"; case Builtin::KindShort: return "tarscore." + string((bPtr->isUnsigned()?"uint8":"int16")); case Builtin::KindInt: return "tarscore." + string((bPtr->isUnsigned()?"uint16":"int32")); case Builtin::KindLong: return "tarscore." + string((bPtr->isUnsigned()?"uint32":"int64")); case Builtin::KindFloat: return "tarscore.float"; case Builtin::KindDouble: return "tarscore.double"; default: assert(false); } } StructPtr sPtr = StructPtr::dynamicCast(pPtr->getTypePtr()); if (sPtr) { return sPtr->getId(); } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr()); if (ePtr) { return "tarscore.int32"; } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr()); if (vPtr) { BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); if (vbPtr && vbPtr->kind() == Builtin::KindByte) { return "tarscore.bytes"; } return "value." + VEC_PREFIX + sName; } MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr()); if (mPtr) { return "value." + MAP_PREFIX + sName; } assert(false); return ""; } string Tars2Python::getDefault(const TypeIdPtr & pPtr, const std::string &sDefault, const std::string & sCurStruct) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); if (bPtr) { switch (bPtr->kind()) { case Builtin::KindBool : return sDefault.empty()?"True": (sDefault == "true"?"True":"False"); case Builtin::KindString : return "\"" + tars::TC_Common::replace(sDefault, "\"", "\\\"") + "\""; case Builtin::KindByte : case Builtin::KindShort : case Builtin::KindInt : case Builtin::KindLong : return sDefault.empty()?"0":sDefault; case Builtin::KindFloat : case Builtin::KindDouble : return sDefault.empty()?"0.0":sDefault; default : assert(false); } } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr()); if (vPtr) { BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); if (vbPtr && vbPtr->kind() == Builtin::KindByte) { return "bytes()"; } return sCurStruct + "." + VEC_PREFIX + pPtr->getId() + "()"; } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr()); if (ePtr) { string sid = ePtr->getSid(); size_t pos = sid.find_last_of(":"); return sDefault.empty()?"0":(sid.substr((pos == string::npos)?0:pos + 1) + "." + sDefault); } StructPtr sPtr = StructPtr::dynamicCast(pPtr->getTypePtr()); if (sPtr) { return sPtr->getId() + "()"; } MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr()); if (mPtr) { return sCurStruct + "." + MAP_PREFIX + pPtr->getId() + "()"; } assert(false); return sDefault; } string Tars2Python::tostrEnum(const EnumPtr &pPtr) { return "tarscore.int8"; } string Tars2Python::makeDataType(const TypePtr & pPtr) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr); if (bPtr) { switch (bPtr->kind()) { case Builtin::KindBool : return "tarscore.boolean"; case Builtin::KindString: return "tarscore.string"; case Builtin::KindByte: return "tarscore.int8"; case Builtin::KindShort: return "tarscore." + string((bPtr->isUnsigned()?"uint8":"int16")); case Builtin::KindInt: return "tarscore." + string((bPtr->isUnsigned()?"uint16":"int32")); case Builtin::KindLong: return "tarscore." + string((bPtr->isUnsigned()?"uint32":"int64")); case Builtin::KindFloat: return "tarscore.float"; case Builtin::KindDouble: return "tarscore.double"; default: assert(false); } } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr); if (vPtr) { BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); if (vbPtr && vbPtr->kind() == Builtin::KindByte) { return "tarscore.bytes"; } return "tarscore.vctclass(" + makeDataType(vPtr->getTypePtr()) + ")"; } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr); if(ePtr) return tostrEnum(ePtr); StructPtr sPtr = StructPtr::dynamicCast(pPtr); if (sPtr) { return sPtr->getId(); } MapPtr mPtr = MapPtr::dynamicCast(pPtr); if (mPtr) { return "tarscore.mapclass(" + makeDataType(mPtr->getLeftTypePtr()) + ", " + makeDataType(mPtr->getRightTypePtr()) + ")"; } assert(false); return ""; } string Tars2Python::generatePython(const StructPtr & pPtr, const NamespacePtr & nPtr) { std::ostringstream s; vector key = pPtr->getKey(); vector & member = pPtr->getAllMemberPtr(); s << TAB << "class " << pPtr->getId() << "(tarscore.struct):"<< endl; INC_TAB; s << TAB << "__tars_class__ = \"" << nPtr->getId() << "." << pPtr->getId() << "\";" << endl; for (size_t i = 0, len = member.size(); i < len; i++) { VectorPtr vPtr = VectorPtr::dynamicCast(member[i]->getTypePtr()); if (vPtr) { BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); if (vbPtr && vbPtr->kind() == Builtin::KindByte) continue; string st = makeDataType(member[i]->getTypePtr()); s << TAB << VEC_PREFIX << member[i]->getId() << " = " << st << ";" << endl; } MapPtr mPtr = MapPtr::dynamicCast(member[i]->getTypePtr()); if (mPtr) { string st = makeDataType(member[i]->getTypePtr()); s << TAB << MAP_PREFIX << member[i]->getId() << " = " << st << ";" << endl; } } s << TAB << endl; s << TAB << "def __init__(self):" << endl; INC_TAB; for (size_t i = 0; i < member.size(); i++) { s << TAB << "self." << member[i]->getId() << " = " << getDefault(member[i], member[i]->def(), pPtr->getId()) << ";" << endl; } DEL_TAB; s << TAB << endl; s << TAB << "@staticmethod" << endl; s << TAB << "def writeTo(oos, value):" << endl; INC_TAB; for (size_t i = 0; i < member.size(); i++) { std::string sFuncName = toFunctionName(member[i], member[i]->getId()); s << TAB << "oos.write(" << sFuncName << ", " << member[i]->getTag() << ", value." << member[i]->getId() << ");" << endl; } DEL_TAB; s << TAB << endl; s << TAB << "@staticmethod" << endl; s << TAB << "def readFrom(ios):" << endl; INC_TAB; s << TAB << "value = " << pPtr->getId() << "();" << endl; for (size_t i = 0; i < member.size(); i++) { std::string sFuncName = toFunctionName(member[i], member[i]->getId()); s << TAB << "value." << member[i]->getId() << "= ios.read(" << sFuncName << ", " << member[i]->getTag() << ", " << (member[i]->isRequire()?"True":"False") << ", value." << member[i]->getId() << ");" << endl; } s << TAB << "return value;" << endl; DEL_TAB; DEL_TAB; return s.str(); } string Tars2Python::makeParams(const OperationPtr &pPtr) { ostringstream str; vector& vParamDecl = pPtr->getAllParamDeclPtr(); for (size_t i = 0; i < vParamDecl.size(); i++) { if (vParamDecl[i]->isOut()) continue; str << vParamDecl[i]->getTypeIdPtr()->getId() << ", "; } str << "context = ServantProxy.mapcls_context()"; return str.str(); } #if 0 std::string Tars2Python::innerDataType(const TypeIdPtr & pPtr) { BuiltinPtr bPtr = BuiltinPtr::dynamicCast(pPtr->getTypePtr()); if (bPtr) { switch (bPtr->kind()) { case Builtin::KindBool : return "tarscore.boolean"; case Builtin::KindString: return "tarscore.string"; case Builtin::KindByte: return "tarscore.int8"; case Builtin::KindShort: return "tarscore." + string((bPtr->isUnsigned()?"uint8":"int16")); case Builtin::KindInt: return "tarscore." + string((bPtr->isUnsigned()?"uint16":"int32")); case Builtin::KindLong: return "tarscore." + string((bPtr->isUnsigned()?"uint32":"int64")); case Builtin::KindFloat: return "tarscore.float"; case Builtin::KindDouble: return "tarscore.double"; default: assert(false); } } StructPtr sPtr = StructPtr::dynamicCast(pPtr->getTypePtr()); if (sPtr) { return sPtr->getId(); } EnumPtr ePtr = EnumPtr::dynamicCast(pPtr->getTypePtr()); if (ePtr) { return "tarscore.int32"; } VectorPtr vPtr = VectorPtr::dynamicCast(pPtr->getTypePtr()); if (vPtr) { BuiltinPtr vbPtr = BuiltinPtr::dynamicCast(vPtr->getTypePtr()); if (vbPtr && vbPtr->kind() == Builtin::KindByte) { return "tarscore.bytes"; } return "tarscore.vctclass(" + innerDataType(vPtr->getTypePtr()) + ")"; } MapPtr mPtr = MapPtr::dynamicCast(pPtr->getTypePtr()); if (mPtr) { return "tarscore.mapclass(" + innerDataType() + ")"; } assert(false); return ""; } #endif string Tars2Python::makeOperations(const OperationPtr &pPtr) { ostringstream str; vector& vParamDecl = pPtr->getAllParamDeclPtr(); str << TAB << "oos = tarscore.TarsOutputStream();" << endl; for(size_t i = 0; i < vParamDecl.size(); i++) { if(vParamDecl[i]->isOut()) continue; str << TAB << "oos.write(" << makeDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ", " << (i + 1) << ", " << vParamDecl[i]->getTypeIdPtr()->getId() << ");" << endl; } str << endl; str << TAB << "rsp = self.tars_invoke(ServantProxy.TARSNORMAL, \"" << pPtr->getId() << "\", oos.getBuffer(), context, None);" << endl << endl; if(vParamDecl.size() > 0 || pPtr->getReturnPtr()->getTypePtr()) { str << TAB << "ios = tarscore.TarsInputStream(rsp.sBuffer);" << endl; string ret; if (pPtr->getReturnPtr()->getTypePtr()) { str << TAB << "ret = ios.read(" << makeDataType(pPtr->getReturnPtr()->getTypePtr()) << ", 0, True);" << endl; ret += "ret, "; } for(size_t i = 0; i < vParamDecl.size(); i++) { if(!vParamDecl[i]->isOut()) continue; str << TAB << vParamDecl[i]->getTypeIdPtr()->getId() << " = ios.read(" << makeDataType(vParamDecl[i]->getTypeIdPtr()->getTypePtr()) << ", " << (i + 1) << ", True);" << endl; ret += vParamDecl[i]->getTypeIdPtr()->getId() + ", "; } str << endl; if (!ret.empty()) { str << TAB << "return (" << ret.substr(0, ret.find_last_of(",")) << ");" << endl; } } return str.str(); } string Tars2Python::generatePython(const InterfacePtr &pPtr) { std::ostringstream str; str << "#proxy for client" << endl; str << TAB << "class " << pPtr->getId() << "Proxy(ServantProxy):" << endl; INC_TAB; vector& vOperation = pPtr->getAllOperationPtr(); for(size_t i = 0; i < vOperation.size(); i++) { str << TAB << "def " << vOperation[i]->getId() << "(self, " << makeParams(vOperation[i]) << "):" << endl; INC_TAB; str << makeOperations(vOperation[i]) << endl; DEL_TAB; } DEL_TAB; return str.str(); } string Tars2Python::generatePython(const NamespacePtr &pPtr) { std::ostringstream str; /* vector &cs = pPtr->getAllConstPtr(); for (size_t i = 0; i < cs.size(); i++) { str << generatePython(cs[i], pPtr->getId()) << endl; } str << endl; */ vector & es = pPtr->getAllEnumPtr(); for (size_t i = 0; i < es.size(); i++) { str << generatePython(es[i], pPtr->getId()) << endl; } vector & ss = pPtr->getAllStructPtr(); for (size_t i = 0; i < ss.size(); i++) { str << generatePython(ss[i], pPtr) << endl; } vector & is = pPtr->getAllInterfacePtr(); for(size_t i = 0; i < is.size(); i++) { str << generatePython(is[i]) << endl << endl; } return str.str(); } void Tars2Python::generatePython(const ContextPtr &pPtr) { vector namespaces = pPtr->getNamespaces(); for(size_t i = 0; i < namespaces.size(); i++) { std::ostringstream str; str << "from tars.core import tarscore;" << endl; str << "from tars.__rpc import ServantProxy;" << endl; vector include = pPtr->getIncludes(); for(size_t j = 0; j < include.size(); j++) { set vec; getNamespace(tars::TC_File::excludeFileExt(include[j]) + ".tars", vec); for (set::iterator it = vec.begin(); it != vec.end(); it++) { str << "from " << _packagePrefix << *it << "." << tars::TC_File::excludeFileExt(include[j]) << " import *;" << endl; } } str << endl << endl; str << generatePython(namespaces[i]) << endl; string sPath = getFilePath() + FILE_SEP + namespaces[i]->getId() + FILE_SEP; string sFileName = sPath + tars::TC_File::excludeFileExt(tars::TC_File::extractFileName(pPtr->getFileName())) + ".py"; tars::TC_File::makeDirRecursive(sPath); tars::TC_File::save2file(sFileName, str.str()); } makePackages(); } void Tars2Python::getNamespace(const string & sFile, set & vec) { g_parse->parse(sFile); vector contexts = g_parse->getContexts(); for (size_t i = 0; i < contexts.size(); i++) { if(sFile != contexts[i]->getFileName()) continue; vector namespaces = contexts[i]->getNamespaces(); for (size_t j = 0; j < namespaces.size(); j++) vec.insert(namespaces[j]->getId()); } } void Tars2Python::createFile(const string &file) { std::vector contexts = g_parse->getContexts(); for(size_t i = 0; i < contexts.size(); i++) { if(file == contexts[i]->getFileName()) { generatePython(contexts[i]); } } } void Tars2Python::makePackages() { string root = _packagePrefix.substr(0, _packagePrefix.find(".")); vector files; tars::TC_File::listDirectory(_baseDir + "/" + root, files, true); files.push_back(_baseDir + "/" + root); for (size_t i = 0; i < files.size(); i++) { if (tars::TC_File::isFileExist(files[i], S_IFDIR) == true) { tars::TC_File::save2file(files[i] + FILE_SEP + "__init__.py", ""); } } } string Tars2Python::getFilePath() const { return _baseDir + FILE_SEP + tars::TC_Common::replace(_packagePrefix, ".", FILE_SEP); }