From 930ab855e3eb4cb9cdf253f96e8b0cc18b178272 Mon Sep 17 00:00:00 2001 From: tvannoy Date: Wed, 12 Oct 2016 15:00:15 -0700 Subject: [PATCH 01/13] initial creation of python client stub generator --- .../client/python_client_stub_generator.cpp | 170 ++++++++++++++++++ .../client/python_client_stub_generator.h | 24 +++ 2 files changed, 194 insertions(+) create mode 100644 src/stubgenerator/client/python_client_stub_generator.cpp create mode 100644 src/stubgenerator/client/python_client_stub_generator.h diff --git a/src/stubgenerator/client/python_client_stub_generator.cpp b/src/stubgenerator/client/python_client_stub_generator.cpp new file mode 100644 index 00000000..32f0bdd9 --- /dev/null +++ b/src/stubgenerator/client/python_client_stub_generator.cpp @@ -0,0 +1,170 @@ +#include "python_client_stub_generator.h" + +#define TEMPLATE_PYTHON_CLIENT_SIGCLASS "class (client.Client):" + +#define TEMPLATE_PYTHON_CLIENT_SIGCONSTRUCTOR "def __init__(self, connector, version='2.0'):\n super(, self).__init__(connector, version)" + +#define TEMPLATE_PYTHON_CLIENT_SIGMETHOD "def ()" + +#define TEMPLATE_NAMED_ASSIGNMENT "parameters[\'\'] = ;" +#define TEMPLATE_POSITION_ASSIGNMENT "parameters.append();" + +#define TEMPLATE_METHODCALL "result = self.callMethod(\'\', parameters);" +#define TEMPLATE_NOTIFICATIONCALL "self.callNotification(\'\', parameters);" + +// #define TEMPLATE_RETURNCHECK "if (result)" +#define TEMPLATE_RETURN "return result;" + +using namespace std; +using namespace jsonrpc; + + +PythonClientStubGenerator::PythonClientStubGenerator(const string &stubname, std::vector &procedures, std::ostream& outputstream) : + StubGenerator(stubname, procedures, outputstream) +{ +} + +PythonClientStubGenerator::PythonClientStubGenerator(const string &stubname, std::vector &procedures, const string filename) : + StubGenerator(stubname, procedures, filename) +{ +} + +void PythonClientStubGenerator::generateStub() +{ + // vector classname = PythonHelper::splitPackages(this->stubname); + // PythonHelper::prolog(*this, this->stubname); + this->writeLine("import client"); + this->writeNewLine(); + + // int depth = PythonHelper::namespaceOpen(*this, stubname); + + // this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCLASS, "", classname.at(classname.size()-1))); + this->write(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCLASS, "", this->stubname)); + this->writeLine(":"); + this->increaseIndentation(); + + // this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCONSTRUCTOR, "", classname.at(classname.size()-1))); + this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCONSTRUCTOR, "", this->stubname)); + this->writeNewLine(); + + for (unsigned int i=0; i < procedures.size(); i++) + { + this->generateMethod(procedures[i]); + } + + this->decreaseIndentation(); + this->writeNewLine(); +} + +void PythonClientStubGenerator::generateMethod(Procedure &proc) +{ + string procsignature = TEMPLATE_PYTHON_CLIENT_SIGMETHOD; + // string returntype = PythonHelper::toCppReturntype(proc.GetReturnType()); + // if (proc.GetProcedureType() == RPC_NOTIFICATION) + // returntype = "void"; + + // replaceAll2(procsignature, "", returntype); + replaceAll2(procsignature, "", proc.GetProcedureName()); + + // generate parameters string + string params = generateParameterDeclarationList(proc); + replaceAll2(procsignature, "", params); + + this->write(procsignature); + this->writeLine(":"); + this->increaseIndentation(); + + // this->writeLine("Json::Value p;"); + if (proc.GetParameterDeclarationType() == PARAMS_BY_NAME) + { + this->writeLine("parmeters = {}"); + } + else if(proc.GetParameterDeclarationType() == PARAMS_BY_POSITION) + { + this->writeLine("parameters = []"); + } + + generateAssignments(proc); + this->writeNewLine(); + generateProcCall(proc); + this->writeNewLine(); + + this->decreaseIndentation(); + + +} + +string PythonClientStubGenerator::generateParameterDeclarationList(Procedure &proc) +{ + stringstream param_string; + parameterNameList_t list = proc.GetParameters(); + + for (parameterNameList_t::iterator it = list.begin(); it != list.end();) + { + param_string << it->first; + if(++it != list.end()) + { + param_string << ", "; + } + } + + return param_string.str(); +} + +void PythonClientStubGenerator::generateAssignments(Procedure &proc) +{ + string assignment; + parameterNameList_t list = proc.GetParameters(); + if(list.size() > 0) + { + for (parameterNameList_t::iterator it = list.begin(); it != list.end(); ++it) + { + + if(proc.GetParameterDeclarationType() == PARAMS_BY_NAME) + { + assignment = TEMPLATE_NAMED_ASSIGNMENT; + } + else + { + assignment = TEMPLATE_POSITION_ASSIGNMENT; + } + replaceAll2(assignment, "", it->first); + this->writeLine(assignment); + } + } + else + { + this->writeLine("parameters = None"); + } + +} + +void PythonClientStubGenerator::generateProcCall(Procedure &proc) +{ + string call; + if (proc.GetProcedureType() == RPC_METHOD) + { + call = TEMPLATE_METHODCALL; + this->writeLine(replaceAll(call, "", proc.GetProcedureName())); + // call = TEMPLATE_RETURNCHECK; + // replaceAll2(call,"", PythonHelper::isCppConversion(proc.GetReturnType())); + // this->writeLine(call); + // this->increaseIndentation(); + // call = TEMPLATE_RETURN; + // replaceAll2(call,"", PythonHelper::toCppConversion(proc.GetReturnType())); + // this->writeLine(call); + // this->decreaseIndentation(); + // this->writeLine("else"); + // this->increaseIndentation(); + // this->writeLine("throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());"); + // this->decreaseIndentation(); + this->writeLine("return result"); + } + else + { + call = TEMPLATE_NOTIFICATIONCALL; + replaceAll2(call, "", proc.GetProcedureName()); + this->writeLine(call); + } + +} diff --git a/src/stubgenerator/client/python_client_stub_generator.h b/src/stubgenerator/client/python_client_stub_generator.h new file mode 100644 index 00000000..0d862914 --- /dev/null +++ b/src/stubgenerator/client/python_client_stub_generator.h @@ -0,0 +1,24 @@ +#ifndef PYTHON_CLIENT_STUB_GENERATOR_H +#define PYTHON_CLIENT_STUB_GENERATOR_H + +#include "../stubgenerator.h" + +namespace jsonrpc +{ + class PythonClientStubGenerator : public StubGenerator + { + public: + + + PythonClientStubGenerator(const std::string& stubname, std::vector &procedures, std::ostream& outputstream); + PythonClientStubGenerator(const std::string& stubname, std::vector &procedures, const std::string filename); + + virtual void generateStub(); + + void generateMethod(Procedure& proc); + void generateAssignments(Procedure& proc); + void generateProcCall(Procedure &proc); + std::string generateParameterDeclarationList(Procedure &proc); + }; +} +#endif // PYTHON_CLIENT_STUB_GENERATOR_H From ba56f0f9a842d555320c0ea65ae0f2645663c706 Mon Sep 17 00:00:00 2001 From: tvannoy Date: Thu, 13 Oct 2016 09:36:09 -0700 Subject: [PATCH 02/13] added class2Filename and prolog --- .../client/python_client_stub_generator.cpp | 12 ++++++++++++ .../client/python_client_stub_generator.h | 1 + 2 files changed, 13 insertions(+) diff --git a/src/stubgenerator/client/python_client_stub_generator.cpp b/src/stubgenerator/client/python_client_stub_generator.cpp index 32f0bdd9..f48af3e9 100644 --- a/src/stubgenerator/client/python_client_stub_generator.cpp +++ b/src/stubgenerator/client/python_client_stub_generator.cpp @@ -1,4 +1,5 @@ #include "python_client_stub_generator.h" +#include #define TEMPLATE_PYTHON_CLIENT_SIGCLASS "class (client.Client):" @@ -33,6 +34,10 @@ void PythonClientStubGenerator::generateStub() { // vector classname = PythonHelper::splitPackages(this->stubname); // PythonHelper::prolog(*this, this->stubname); + this->writeLine("#"); + this->writeLine("# This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!"); + this->writeLine("#"); + this->writeNewLine(); this->writeLine("import client"); this->writeNewLine(); @@ -168,3 +173,10 @@ void PythonClientStubGenerator::generateProcCall(Procedure &proc) } } + +string PythonClientStubGenerator::class2Filename(const string &classname) +{ + string result = classname; + std::transform(result.begin(), result.end(), result.begin(), ::tolower); + return result + ".py"; +} diff --git a/src/stubgenerator/client/python_client_stub_generator.h b/src/stubgenerator/client/python_client_stub_generator.h index 0d862914..fd028c19 100644 --- a/src/stubgenerator/client/python_client_stub_generator.h +++ b/src/stubgenerator/client/python_client_stub_generator.h @@ -19,6 +19,7 @@ namespace jsonrpc void generateAssignments(Procedure& proc); void generateProcCall(Procedure &proc); std::string generateParameterDeclarationList(Procedure &proc); + static std::string class2Filename(const std::string &classname); }; } #endif // PYTHON_CLIENT_STUB_GENERATOR_H From 99d602bf2ce1e62ab5ccad3bb87fb8d3f9b0e89e Mon Sep 17 00:00:00 2001 From: tvannoy Date: Thu, 13 Oct 2016 09:36:24 -0700 Subject: [PATCH 03/13] added pyclient to factory --- src/stubgenerator/stubgeneratorfactory.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/stubgenerator/stubgeneratorfactory.cpp b/src/stubgenerator/stubgeneratorfactory.cpp index a1c963af..c95f8930 100644 --- a/src/stubgenerator/stubgeneratorfactory.cpp +++ b/src/stubgenerator/stubgeneratorfactory.cpp @@ -15,6 +15,7 @@ #include "helper/cpphelper.h" #include "client/cppclientstubgenerator.h" #include "client/jsclientstubgenerator.h" +#include "client/python_client_stub_generator.h" #include "server/cppserverstubgenerator.h" using namespace jsonrpc; @@ -32,10 +33,13 @@ bool StubGeneratorFactory::createStubGenerators(int argc, char **argv, vector", "name of the C++ client stub file"); struct arg_str *jsclient = arg_str0(NULL, "js-client", "", "name of the JavaScript client stub class"); struct arg_str *jsclientfile = arg_str0(NULL, "js-client-file", "", "name of the JavaScript client stub file"); + struct arg_str *pyclient = arg_str0(NULL, "python-client", "", "name of the Python client stub class"); + struct arg_str *pyclientfile = arg_str0(NULL, "python-client-file", "", "name of the Python client stub file"); + struct arg_end *end = arg_end(20); - void* argtable[] = {inputfile, help, version, verbose, cppserver, cppserverfile, cppclient, cppclientfile, jsclient, jsclientfile,end}; + void* argtable[] = {inputfile, help, version, verbose, cppserver, cppserverfile, cppclient, cppclientfile, jsclient, jsclientfile, pyclient, pyclientfile, end}; if (arg_parse(argc,argv,argtable) > 0) { @@ -121,6 +125,19 @@ bool StubGeneratorFactory::createStubGenerators(int argc, char **argv, vectorsval[0], procedures, filename)); } + + if (pyclient->count > 0) + { + string filename; + if (pyclientfile->count > 0) + filename = pyclientfile->sval[0]; + else + filename = PythonClientStubGenerator::class2Filename(pyclient->sval[0]); + + if (verbose->count > 0) + fprintf(stdout, "Generating Python Clientstub to: %s\n", filename.c_str()); + stubgenerators.push_back(new PythonClientStubGenerator(pyclient->sval[0], procedures, filename)); + } } catch (const JsonRpcException &ex) { From 664037a91be228a0deed6f919ac40f98788a5696 Mon Sep 17 00:00:00 2001 From: tvannoy Date: Thu, 13 Oct 2016 11:18:58 -0700 Subject: [PATCH 04/13] Fixed python syntax; Misc. code cleanup --- .../client/python_client_stub_generator.cpp | 75 ++++++------------- 1 file changed, 21 insertions(+), 54 deletions(-) diff --git a/src/stubgenerator/client/python_client_stub_generator.cpp b/src/stubgenerator/client/python_client_stub_generator.cpp index f48af3e9..b8832aca 100644 --- a/src/stubgenerator/client/python_client_stub_generator.cpp +++ b/src/stubgenerator/client/python_client_stub_generator.cpp @@ -3,18 +3,15 @@ #define TEMPLATE_PYTHON_CLIENT_SIGCLASS "class (client.Client):" -#define TEMPLATE_PYTHON_CLIENT_SIGCONSTRUCTOR "def __init__(self, connector, version='2.0'):\n super(, self).__init__(connector, version)" +#define TEMPLATE_PYTHON_CLIENT_SIGCONSTRUCTOR "def __init__(self, connector, version='2.0'):\n super(, self).__init__(connector, version)" -#define TEMPLATE_PYTHON_CLIENT_SIGMETHOD "def ()" +#define TEMPLATE_PYTHON_CLIENT_SIGMETHOD "def (self):" -#define TEMPLATE_NAMED_ASSIGNMENT "parameters[\'\'] = ;" -#define TEMPLATE_POSITION_ASSIGNMENT "parameters.append();" +#define TEMPLATE_NAMED_ASSIGNMENT "parameters[\'\'] = " +#define TEMPLATE_POSITION_ASSIGNMENT "parameters.append()" -#define TEMPLATE_METHODCALL "result = self.callMethod(\'\', parameters);" -#define TEMPLATE_NOTIFICATIONCALL "self.callNotification(\'\', parameters);" - -// #define TEMPLATE_RETURNCHECK "if (result)" -#define TEMPLATE_RETURN "return result;" +#define TEMPLATE_METHODCALL "result = self.callMethod(\'\', parameters)" +#define TEMPLATE_NOTIFICATIONCALL "self.callNotification(\'\', parameters)" using namespace std; using namespace jsonrpc; @@ -32,8 +29,6 @@ PythonClientStubGenerator::PythonClientStubGenerator(const string &stubname, std void PythonClientStubGenerator::generateStub() { - // vector classname = PythonHelper::splitPackages(this->stubname); - // PythonHelper::prolog(*this, this->stubname); this->writeLine("#"); this->writeLine("# This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!"); this->writeLine("#"); @@ -41,14 +36,9 @@ void PythonClientStubGenerator::generateStub() this->writeLine("import client"); this->writeNewLine(); - // int depth = PythonHelper::namespaceOpen(*this, stubname); - - // this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCLASS, "", classname.at(classname.size()-1))); - this->write(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCLASS, "", this->stubname)); - this->writeLine(":"); + this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCLASS, "", this->stubname)); this->increaseIndentation(); - // this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCONSTRUCTOR, "", classname.at(classname.size()-1))); this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCONSTRUCTOR, "", this->stubname)); this->writeNewLine(); @@ -64,39 +54,21 @@ void PythonClientStubGenerator::generateStub() void PythonClientStubGenerator::generateMethod(Procedure &proc) { string procsignature = TEMPLATE_PYTHON_CLIENT_SIGMETHOD; - // string returntype = PythonHelper::toCppReturntype(proc.GetReturnType()); - // if (proc.GetProcedureType() == RPC_NOTIFICATION) - // returntype = "void"; - - // replaceAll2(procsignature, "", returntype); replaceAll2(procsignature, "", proc.GetProcedureName()); // generate parameters string string params = generateParameterDeclarationList(proc); replaceAll2(procsignature, "", params); - this->write(procsignature); - this->writeLine(":"); + this->writeLine(procsignature); this->increaseIndentation(); - // this->writeLine("Json::Value p;"); - if (proc.GetParameterDeclarationType() == PARAMS_BY_NAME) - { - this->writeLine("parmeters = {}"); - } - else if(proc.GetParameterDeclarationType() == PARAMS_BY_POSITION) - { - this->writeLine("parameters = []"); - } - generateAssignments(proc); this->writeNewLine(); generateProcCall(proc); this->writeNewLine(); this->decreaseIndentation(); - - } string PythonClientStubGenerator::generateParameterDeclarationList(Procedure &proc) @@ -104,13 +76,10 @@ string PythonClientStubGenerator::generateParameterDeclarationList(Procedure &pr stringstream param_string; parameterNameList_t list = proc.GetParameters(); - for (parameterNameList_t::iterator it = list.begin(); it != list.end();) + for (parameterNameList_t::iterator it = list.begin(); it != list.end(); ++it) { + param_string << ", "; param_string << it->first; - if(++it != list.end()) - { - param_string << ", "; - } } return param_string.str(); @@ -122,10 +91,20 @@ void PythonClientStubGenerator::generateAssignments(Procedure &proc) parameterNameList_t list = proc.GetParameters(); if(list.size() > 0) { + parameterDeclaration_t declType = proc.GetParameterDeclarationType(); + if (proc.GetParameterDeclarationType() == PARAMS_BY_NAME) + { + this->writeLine("parameters = {}"); + } + else if(proc.GetParameterDeclarationType() == PARAMS_BY_POSITION) + { + this->writeLine("parameters = []"); + } + for (parameterNameList_t::iterator it = list.begin(); it != list.end(); ++it) { - if(proc.GetParameterDeclarationType() == PARAMS_BY_NAME) + if(declType == PARAMS_BY_NAME) { assignment = TEMPLATE_NAMED_ASSIGNMENT; } @@ -151,18 +130,6 @@ void PythonClientStubGenerator::generateProcCall(Procedure &proc) { call = TEMPLATE_METHODCALL; this->writeLine(replaceAll(call, "", proc.GetProcedureName())); - // call = TEMPLATE_RETURNCHECK; - // replaceAll2(call,"", PythonHelper::isCppConversion(proc.GetReturnType())); - // this->writeLine(call); - // this->increaseIndentation(); - // call = TEMPLATE_RETURN; - // replaceAll2(call,"", PythonHelper::toCppConversion(proc.GetReturnType())); - // this->writeLine(call); - // this->decreaseIndentation(); - // this->writeLine("else"); - // this->increaseIndentation(); - // this->writeLine("throw jsonrpc::JsonRpcException(jsonrpc::Errors::ERROR_CLIENT_INVALID_RESPONSE, result.toStyledString());"); - // this->decreaseIndentation(); this->writeLine("return result"); } else From efe39ff36dcec58e69980cce55ba5eddd53c8b72 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 10:33:40 -0700 Subject: [PATCH 05/13] Renamed files; updated python library import --- ...thon_client_stub_generator.cpp => pyclientstubgenerator.cpp} | 2 +- .../{python_client_stub_generator.h => pyclientstubgenerator.h} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/stubgenerator/client/{python_client_stub_generator.cpp => pyclientstubgenerator.cpp} (98%) rename src/stubgenerator/client/{python_client_stub_generator.h => pyclientstubgenerator.h} (100%) diff --git a/src/stubgenerator/client/python_client_stub_generator.cpp b/src/stubgenerator/client/pyclientstubgenerator.cpp similarity index 98% rename from src/stubgenerator/client/python_client_stub_generator.cpp rename to src/stubgenerator/client/pyclientstubgenerator.cpp index b8832aca..fcf3253d 100644 --- a/src/stubgenerator/client/python_client_stub_generator.cpp +++ b/src/stubgenerator/client/pyclientstubgenerator.cpp @@ -33,7 +33,7 @@ void PythonClientStubGenerator::generateStub() this->writeLine("# This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!"); this->writeLine("#"); this->writeNewLine(); - this->writeLine("import client"); + this->writeLine("from jsonrpc_pyclient import client"); this->writeNewLine(); this->writeLine(replaceAll(TEMPLATE_PYTHON_CLIENT_SIGCLASS, "", this->stubname)); diff --git a/src/stubgenerator/client/python_client_stub_generator.h b/src/stubgenerator/client/pyclientstubgenerator.h similarity index 100% rename from src/stubgenerator/client/python_client_stub_generator.h rename to src/stubgenerator/client/pyclientstubgenerator.h From 7cee41f13468aff8aea53043f73a749781323c54 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 10:35:49 -0700 Subject: [PATCH 06/13] add pyclient header to stubgenerator --- src/stubgenerator/stubgenerator.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/stubgenerator/stubgenerator.cpp b/src/stubgenerator/stubgenerator.cpp index 9cc42839..5ffd68f9 100644 --- a/src/stubgenerator/stubgenerator.cpp +++ b/src/stubgenerator/stubgenerator.cpp @@ -18,6 +18,7 @@ #include "server/cppserverstubgenerator.h" #include "client/cppclientstubgenerator.h" #include "client/jsclientstubgenerator.h" +#include "client/pyclientstubgenerator.h" using namespace std; using namespace jsonrpc; From 3ddf47fcbdbfdb0128195125ca184ebb54c6ad78 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 11:21:52 -0700 Subject: [PATCH 07/13] updated python syntax --- src/stubgenerator/client/pyclientstubgenerator.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/stubgenerator/client/pyclientstubgenerator.cpp b/src/stubgenerator/client/pyclientstubgenerator.cpp index fcf3253d..68691fae 100644 --- a/src/stubgenerator/client/pyclientstubgenerator.cpp +++ b/src/stubgenerator/client/pyclientstubgenerator.cpp @@ -1,4 +1,4 @@ -#include "python_client_stub_generator.h" +#include "pyclientstubgenerator.h" #include #define TEMPLATE_PYTHON_CLIENT_SIGCLASS "class (client.Client):" @@ -10,8 +10,8 @@ #define TEMPLATE_NAMED_ASSIGNMENT "parameters[\'\'] = " #define TEMPLATE_POSITION_ASSIGNMENT "parameters.append()" -#define TEMPLATE_METHODCALL "result = self.callMethod(\'\', parameters)" -#define TEMPLATE_NOTIFICATIONCALL "self.callNotification(\'\', parameters)" +#define TEMPLATE_METHODCALL "result = self.call_method(\'\', parameters)" +#define TEMPLATE_NOTIFICATIONCALL "self.call_notification(\'\', parameters)" using namespace std; using namespace jsonrpc; From b105a4af306ed254b70a0c7bcc7214867c33b36b Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 11:23:21 -0700 Subject: [PATCH 08/13] fixed pyclient include name --- src/stubgenerator/stubgeneratorfactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stubgenerator/stubgeneratorfactory.cpp b/src/stubgenerator/stubgeneratorfactory.cpp index c95f8930..e51e24c2 100644 --- a/src/stubgenerator/stubgeneratorfactory.cpp +++ b/src/stubgenerator/stubgeneratorfactory.cpp @@ -15,7 +15,7 @@ #include "helper/cpphelper.h" #include "client/cppclientstubgenerator.h" #include "client/jsclientstubgenerator.h" -#include "client/python_client_stub_generator.h" +#include "client/pyclientstubgenerator.h" #include "server/cppserverstubgenerator.h" using namespace jsonrpc; @@ -34,7 +34,7 @@ bool StubGeneratorFactory::createStubGenerators(int argc, char **argv, vector", "name of the JavaScript client stub class"); struct arg_str *jsclientfile = arg_str0(NULL, "js-client-file", "", "name of the JavaScript client stub file"); struct arg_str *pyclient = arg_str0(NULL, "python-client", "", "name of the Python client stub class"); - struct arg_str *pyclientfile = arg_str0(NULL, "python-client-file", "", "name of the Python client stub file"); + struct arg_str *pyclientfile = arg_str0(NULL, "python-client-file", "", "name of the Python client stub file"); From 51acbeb784d6a12fbc4b7a19db61665da2b97e8f Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 12:25:01 -0700 Subject: [PATCH 09/13] updated pyclient argument syntax --- src/stubgenerator/stubgeneratorfactory.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/stubgenerator/stubgeneratorfactory.cpp b/src/stubgenerator/stubgeneratorfactory.cpp index e51e24c2..fe6c44c5 100644 --- a/src/stubgenerator/stubgeneratorfactory.cpp +++ b/src/stubgenerator/stubgeneratorfactory.cpp @@ -33,8 +33,8 @@ bool StubGeneratorFactory::createStubGenerators(int argc, char **argv, vector", "name of the C++ client stub file"); struct arg_str *jsclient = arg_str0(NULL, "js-client", "", "name of the JavaScript client stub class"); struct arg_str *jsclientfile = arg_str0(NULL, "js-client-file", "", "name of the JavaScript client stub file"); - struct arg_str *pyclient = arg_str0(NULL, "python-client", "", "name of the Python client stub class"); - struct arg_str *pyclientfile = arg_str0(NULL, "python-client-file", "", "name of the Python client stub file"); + struct arg_str *pyclient = arg_str0(NULL, "py-client", "", "name of the Python client stub class"); + struct arg_str *pyclientfile = arg_str0(NULL, "py-client-file", "", "name of the Python client stub file"); From c7bd61bb30877738150cbeabdb64095847cf3512 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 12:47:11 -0700 Subject: [PATCH 10/13] updated manpage --- doc/manpage.in | 68 +++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/doc/manpage.in b/doc/manpage.in index 92b54fa5..3725d9e5 100644 --- a/doc/manpage.in +++ b/doc/manpage.in @@ -5,15 +5,16 @@ jsonrpcstub \- genearate stubs for the libjson\-rpc\-cpp framework. .SH SYNOPSIS .B -jsonrpcstub specfile.json [\-\-cpp\-server=namespace::ClassName] - [\-\-cpp\-server\-file=classqname.h] [\-\-cpp\-client=namespace::ClassName] -[\-\-cpp\-client-file=classname.h] [\-\-js\-client=ClassName] -[\-\-js-client-file=classname.js] [\-h] [\-v] [\-\-version] +jsonrpcstub specfile.json [\-\-cpp\-server=namespace::ClassName] + [\-\-cpp\-server\-file=classqname.h] [\-\-cpp\-client=namespace::ClassName] +[\-\-cpp\-client-file=classname.h] [\-\-js\-client=ClassName] +[\-\-js-client-file=classname.js] [\-\-py\-client=ClassName] +[\-\-py\-client\-file=classname.py] [\-h] [\-v] [\-\-version] .PP .SH DESCRIPTION .PP -jsonrpcstub is a tool to generate C++ and JavaScript classes from a procedure specification file. +jsonrpcstub is a tool to generate C++, JavaScript, and Python classes from a procedure specification file. .SS SPECIFICATION SYNTAX .PP The specifictaion file is a JSON file containing all available JSON\-RPC methods and notifications @@ -38,9 +39,10 @@ with their corresponding parameters and return values contained in a top\-level .fi .PP -The literal in each \fB"params"\fP and \fB"returns"\fP section defines the corresponding type. -If the \fb"params"\fP contains an array, the parameters are accepted by position, -if it contains an object, they are accepted by name. +The literal in each \fB"params"\fP and \fB"returns"\fP section defines the corresponding type. +If the \fb"params"\fP contains an array, the parameters are accepted by position, +if it contains an object, they are accepted by name. + .SH OPTIONS .IP \-h Print usage information. @@ -49,34 +51,48 @@ Print verbose information during generation. .IP \-\-version Print version info and exit. .IP \-\-cpp\-server=ClassName -Creates a Abstract Server class. Namespaces can be provided using the :: notation +Creates a Abstract Server class. Namespaces can be provided using the :: notation (e.g. ns1::ns2::Classname). .IP \-\-cpp\-server\-file=filename.h Defines the filename to use when generating the C++ Abstract Server class. If this is not provided, the lowercase classname is used. .IP \-\-cpp\-client=ClassName -Creates a C++ client class. Namespaces can be provided using the :: notation +Creates a C++ client class. Namespaces can be provided using the :: notation (e.g. ns1::ns2::Classname). .IP \-\-cpp\-client\-file=filename.h Defines the filename to use when generating the C++ client class. If this is not provided, the lowercase classname is used. .IP \-\-js\-client=ClassName -Creates a JavaScript client class. No namespaces are supported in this option. +Creates a JavaScript client class. No namespaces are supported in this option. .IP \-\-js\-client-file=filename.js -Defines the filename to use when generating the JavaScrip client class. +Defines the filename to use when generating the JavaScript client class. +.IP \-\-py\-client=ClassName +Creates a Python client class. No namespaces are supported in this option. +.IP \-\-py\-client\-file=filename.py +Defines the filename to use when generating the Python client class. +If this is not provided, the lowercase classname is used. + .SH EXAMPLES .PP Generate C++ Stubs for Server and Client, the classes will be named AbstractStubServer and StubClient: -.P P +.IP .B -\& jsonrpcstub spec.json \-\-cpp\-server=AbstractStubServer \-\-cpp\-client=StubClient +\&jsonrpcstub spec.json \-\-cpp\-server=AbstractStubServer \-\-cpp\-client=StubClient .B .PP Generate JavaScript Client class MyRpcClient into file someclient.js: +.IP +.B +\&jsonrpcstub spec.json \-\-js\-client=MyRpcClient \-\-js\-client\-file=someclient.js +.B .PP +Generate Python client class StubClient, which will be saved into stubclient.py +.IP .B -\& jsonrpcstub spec.json \-\-js\-client=MyRpcClient \-\-js\-client\-file=someclient.js +\&jsonrpcstub spec.json \-\-py\-client=StubClient .B +.PP + .SH EXIT STATUS This command returns 0 if no error occurred. In any other case, it returns 1. .SH SEE ALSO @@ -88,21 +104,21 @@ No known bugs. Please report found bugs as an issue on github or send me an emai Copyright (C) 2011\-2015 Peter Spiess\-Knafl -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in the -Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -the Software, and to permit persons to whom the Software is furnished to do so, +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in the +Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all +The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, -INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR -PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE -LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. .SH AUTHOR From e0f536e74f0bd9f033309cf736e9814e850f0933 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 12:48:52 -0700 Subject: [PATCH 11/13] updated authors --- AUTHORS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AUTHORS.md b/AUTHORS.md index 081b7f70..cd62548b 100644 --- a/AUTHORS.md +++ b/AUTHORS.md @@ -33,6 +33,9 @@ Alexandre Poirot + adapted build file to generate pkg-config file for this lib. + added client and server connectors that use Tcp Sockets on Linux and Windows (uses native socket and thread API on each OS) +Trevor Vannoy ++ python client stub generator + Bugfixes (chronological order) ============================== From 1e5c9001add5bed2090cb923d85dc78230a7a9a6 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 13:58:00 -0700 Subject: [PATCH 12/13] added string normalization for method names --- .../client/pyclientstubgenerator.cpp | 20 ++++++++++++++++++- .../client/pyclientstubgenerator.h | 5 +++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/stubgenerator/client/pyclientstubgenerator.cpp b/src/stubgenerator/client/pyclientstubgenerator.cpp index 68691fae..a5175fa3 100644 --- a/src/stubgenerator/client/pyclientstubgenerator.cpp +++ b/src/stubgenerator/client/pyclientstubgenerator.cpp @@ -33,6 +33,11 @@ void PythonClientStubGenerator::generateStub() this->writeLine("# This file is generated by jsonrpcstub, DO NOT CHANGE IT MANUALLY!"); this->writeLine("#"); this->writeNewLine(); + this->writeLine("#"); + this->writeLine("# To use this client, jsonrpc_pyclient must be installed:"); + this->writeLine("# pip install jsonrpc_pyclient"); + this->writeLine("#"); + this->writeNewLine(); this->writeLine("from jsonrpc_pyclient import client"); this->writeNewLine(); @@ -54,7 +59,7 @@ void PythonClientStubGenerator::generateStub() void PythonClientStubGenerator::generateMethod(Procedure &proc) { string procsignature = TEMPLATE_PYTHON_CLIENT_SIGMETHOD; - replaceAll2(procsignature, "", proc.GetProcedureName()); + replaceAll2(procsignature, "", normalizeString(proc.GetProcedureName())); // generate parameters string string params = generateParameterDeclarationList(proc); @@ -147,3 +152,16 @@ string PythonClientStubGenerator::class2Filename(const string &classname) std::transform(result.begin(), result.end(), result.begin(), ::tolower); return result + ".py"; } + +string PythonClientStubGenerator::normalizeString(const string &text) +{ + string result = text; + for(unsigned int i=0; i < text.length(); i++) + { + if (!((text[i] >= 'a' && text[i] <= 'z') || (text[i] >= 'A' && text[i] <= 'Z') || (text[i] >= '0' && text[i] <= '9') || text[i] == '_')) + { + result[i] = '_'; + } + } + return result; +} diff --git a/src/stubgenerator/client/pyclientstubgenerator.h b/src/stubgenerator/client/pyclientstubgenerator.h index fd028c19..6207e55e 100644 --- a/src/stubgenerator/client/pyclientstubgenerator.h +++ b/src/stubgenerator/client/pyclientstubgenerator.h @@ -5,6 +5,10 @@ namespace jsonrpc { + /** + * The stub client this class generates requires jsonrpc_pyclient + * to be installed from pypi. + */ class PythonClientStubGenerator : public StubGenerator { public: @@ -20,6 +24,7 @@ namespace jsonrpc void generateProcCall(Procedure &proc); std::string generateParameterDeclarationList(Procedure &proc); static std::string class2Filename(const std::string &classname); + static std::string normalizeString(const std::string &text); }; } #endif // PYTHON_CLIENT_STUB_GENERATOR_H From 79a93c5985776a38f843f73600e687c8a0eef605 Mon Sep 17 00:00:00 2001 From: Trevor Vannoy Date: Wed, 2 Nov 2016 13:58:23 -0700 Subject: [PATCH 13/13] added test case for python client stubgen --- src/test/test_stubgenerator.cpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/test/test_stubgenerator.cpp b/src/test/test_stubgenerator.cpp index 9318e3d0..ce1a96ab 100644 --- a/src/test/test_stubgenerator.cpp +++ b/src/test/test_stubgenerator.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include @@ -107,6 +108,25 @@ TEST_CASE("test_stubgen_jsclient", TEST_MODULE) CHECK(JSClientStubGenerator::class2Filename("TestClass") == "testclass.js"); } +TEST_CASE("test_stubgen_pyclient", TEST_MODULE) +{ + stringstream stream; + vector procedures = SpecificationParser::GetProceduresFromFile("testspec6.json"); + PythonClientStubGenerator stubgen("TestStubClient", procedures, stream); + stubgen.generateStub(); + string result = stream.str(); + + CHECK(result.find("from jsonrpc_pyclient import client") != string::npos); + CHECK(result.find("class TestStubClient(client.Client):") != string::npos); + CHECK(result.find("def __init__(self, connector, version='2.0'):") != string::npos); + CHECK(result.find("def test_method(self, name):") != string::npos); + CHECK(result.find("def test_notification(self, name):") != string::npos); + CHECK(result.find("def test_method2(self, object, values):") != string::npos); + CHECK(result.find("def test_notification2(self, object, values):") != string::npos); + + CHECK(PythonClientStubGenerator::class2Filename("TestClass") == "testclass.py"); +} + TEST_CASE("test_stubgen_indentation", TEST_MODULE) { stringstream stream;