From 08265912fb99ee50b1bfcd1e45ecf710eb1ed48b Mon Sep 17 00:00:00 2001 From: Seth Centerbar Date: Sat, 21 Nov 2020 12:15:05 -0500 Subject: [PATCH 1/6] Add python client generation to /example --- example/client.gen.py | 63 +++++++++++++++++++++++++++++++++++++++++ example/client.py.plush | 63 +++++++++++++++++++++++++++++++++++++++++ example/generate.sh | 6 ++++ 3 files changed, 132 insertions(+) create mode 100644 example/client.gen.py create mode 100644 example/client.py.plush diff --git a/example/client.gen.py b/example/client.gen.py new file mode 100644 index 0000000..31491cf --- /dev/null +++ b/example/client.gen.py @@ -0,0 +1,63 @@ +# Code generated by oto; DO NOT EDIT. + +import requests +import json + +class Client: + """Client provides access to the Greeter Service.""" + + def __init__(self, endpoint="http://localhost:8080/oto"): + self.endpoint = endpoint + if self.endpoint == "": + raise FieldError(field="endpoint", message="endpoint missing") + +class GreeterService: + """GreeterService is a polite API for greeting people.""" + + def __init__(self, client): + self.client = client + + def greet(self, greetRequest): + """Greet prepares a lovely greeting.""" + url = "{}/GreeterService.Greet".format(self.client.endpoint) + headers = { + 'Accept': 'application/json; charset=utf8', + 'Content-Type': 'application/json; charset=utf8' + } + r = requests.post(url, json=greetRequest, headers=headers) + if r.status_code != 200: + raise OtoError(message="status code: {}".format(r.status_code)) + j = r.json() + if 'error' in j: + err = j.get('error') + if err != '': + raise OtoError(message=err) + return j + + + +class Error(Exception): + """Base class for exceptions in this module.""" + pass + +class OtoError(Error): + """Exception raised for an error making the request. + + Attributes: + message -- explanation of the error + """ + + def __init__(self, message): + self.message = message + +class FieldError(Error): + """Exception raised for missing fields. + + Attributes: + field -- field which the error occurred + message -- explanation of the error + """ + + def __init__(self, field, message): + self.field = field + self.message = message diff --git a/example/client.py.plush b/example/client.py.plush new file mode 100644 index 0000000..cb4e0c1 --- /dev/null +++ b/example/client.py.plush @@ -0,0 +1,63 @@ +# Code generated by oto; DO NOT EDIT. + +import requests +import json + +class Client: + """Client provides access to the Greeter Service.""" + + def __init__(self, endpoint="http://localhost:8080/oto"): + self.endpoint = endpoint + if self.endpoint == "": + raise FieldError(field="endpoint", message="endpoint missing") + +<%= for (service) in def.Services { %>class <%= service.Name %>: + """<%= format_comment_line(service.Comment) %>""" + + def __init__(self, client): + self.client = client + <%= for (method) in service.Methods { %> + def <%= method.NameLowerCamel %>(self, <%= method.InputObject.ObjectNameLowerCamel %>): + """<%= format_comment_line(method.Comment) %>""" + url = "{}/<%= service.Name %>.<%= method.Name %>".format(self.client.endpoint) + headers = { + 'Accept': 'application/json; charset=utf8', + 'Content-Type': 'application/json; charset=utf8' + } + r = requests.post(url, json=<%= method.InputObject.ObjectNameLowerCamel %>, headers=headers) + if r.status_code != 200: + raise OtoError(message="status code: {}".format(r.status_code)) + j = r.json() + if 'error' in j: + err = j.get('error') + if err != '': + raise OtoError(message=err) + return j + <% } %> +<% } %> + +class Error(Exception): + """Base class for exceptions in this module.""" + pass + +class OtoError(Error): + """Exception raised for an error making the request. + + Attributes: + message -- explanation of the error + """ + + def __init__(self, message): + self.message = message + +class FieldError(Error): + """Exception raised for missing fields. + + Attributes: + field -- field which the error occurred + message -- explanation of the error + """ + + def __init__(self, field, message): + self.field = field + self.message = message diff --git a/example/generate.sh b/example/generate.sh index 66f2751..6c1db15 100755 --- a/example/generate.sh +++ b/example/generate.sh @@ -13,6 +13,12 @@ oto -template client.js.plush \ ./def echo "generated client.gen.js" +oto -template client.py.plush \ + -out client.gen.py \ + -pkg main \ + ./def +echo "generated client.gen.py" + oto -template client.swift.plush \ -out ./swift/SwiftCLIExample/SwiftCLIExample/client.gen.swift \ -pkg main \ From 59cb5ddaccc39e99961eb72aea4fa0a7128ec070 Mon Sep 17 00:00:00 2001 From: Seth Centerbar Date: Sun, 22 Nov 2020 01:22:04 -0500 Subject: [PATCH 2/6] Add python types to parser --- parser/parser.go | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/parser/parser.go b/parser/parser.go index ee98493..4cdedf3 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -145,6 +145,7 @@ type FieldType struct { IsObject bool `json:"isObject"` JSType string `json:"jsType"` SwiftType string `json:"swiftType"` + PythonType string `json:"pythonType"` } // Parser parses Oto Go definition packages. @@ -410,25 +411,31 @@ func (p *Parser) parseFieldType(pkg *packages.Package, obj types.Object) (FieldT if ftype.IsObject { ftype.JSType = "object" ftype.SwiftType = "Any" + ftype.PythonType = "Any" } else { switch ftype.TypeName { case "interface{}": ftype.JSType = "any" ftype.SwiftType = "Any" + ftype.PythonType = "Any" case "map[string]interface{}": ftype.JSType = "object" ftype.SwiftType = "Any" + ftype.PythonType = "Any" case "string": ftype.JSType = "string" ftype.SwiftType = "String" + ftype.PythonType = "str" case "bool": ftype.JSType = "boolean" ftype.SwiftType = "Bool" + ftype.PythonType = "bool" case "int", "int16", "int32", "int64", "uint", "uint16", "uint32", "uint64", "float32", "float64": ftype.JSType = "number" ftype.SwiftType = "Double" + ftype.PythonType = "int" } } @@ -444,9 +451,10 @@ func (p *Parser) addOutputFields() error { NameLowerCamel: "error", Comment: "Error is string explaining what went wrong. Empty if everything was fine.", Type: FieldType{ - TypeName: "string", - JSType: "string", - SwiftType: "String", + TypeName: "string", + JSType: "string", + SwiftType: "String", + PythonType: "str", }, Metadata: map[string]interface{}{}, Example: "something went wrong", From 5af41db4e036fde44c4e0bc5ee42875a2cf28d6e Mon Sep 17 00:00:00 2001 From: Seth Centerbar Date: Sun, 22 Nov 2020 01:23:18 -0500 Subject: [PATCH 3/6] Python client w/ type generation. Uploading in progress work for visibility --- example/client.gen.py | 63 ----------------------------------------- example/client.py.plush | 15 ++++++++-- example/generate.sh | 2 +- 3 files changed, 14 insertions(+), 66 deletions(-) delete mode 100644 example/client.gen.py diff --git a/example/client.gen.py b/example/client.gen.py deleted file mode 100644 index 31491cf..0000000 --- a/example/client.gen.py +++ /dev/null @@ -1,63 +0,0 @@ -# Code generated by oto; DO NOT EDIT. - -import requests -import json - -class Client: - """Client provides access to the Greeter Service.""" - - def __init__(self, endpoint="http://localhost:8080/oto"): - self.endpoint = endpoint - if self.endpoint == "": - raise FieldError(field="endpoint", message="endpoint missing") - -class GreeterService: - """GreeterService is a polite API for greeting people.""" - - def __init__(self, client): - self.client = client - - def greet(self, greetRequest): - """Greet prepares a lovely greeting.""" - url = "{}/GreeterService.Greet".format(self.client.endpoint) - headers = { - 'Accept': 'application/json; charset=utf8', - 'Content-Type': 'application/json; charset=utf8' - } - r = requests.post(url, json=greetRequest, headers=headers) - if r.status_code != 200: - raise OtoError(message="status code: {}".format(r.status_code)) - j = r.json() - if 'error' in j: - err = j.get('error') - if err != '': - raise OtoError(message=err) - return j - - - -class Error(Exception): - """Base class for exceptions in this module.""" - pass - -class OtoError(Error): - """Exception raised for an error making the request. - - Attributes: - message -- explanation of the error - """ - - def __init__(self, message): - self.message = message - -class FieldError(Error): - """Exception raised for missing fields. - - Attributes: - field -- field which the error occurred - message -- explanation of the error - """ - - def __init__(self, field, message): - self.field = field - self.message = message diff --git a/example/client.py.plush b/example/client.py.plush index cb4e0c1..b405d74 100644 --- a/example/client.py.plush +++ b/example/client.py.plush @@ -3,6 +3,7 @@ import requests import json + class Client: """Client provides access to the Greeter Service.""" @@ -11,20 +12,28 @@ class Client: if self.endpoint == "": raise FieldError(field="endpoint", message="endpoint missing") + +<%= for (object) in def.Objects { %>class <%= object.Name %>: + """<%= format_comment_line(object.Comment) %>""" + + def __init__(self<%= for (field) in object.Fields { %>, <%=field.NameLowerCamel%>:<%= field.Type.PythonType%><% } %>) -> None: + <%= for (field) in object.Fields { %>self.<%=field.NameLowerCamel%> = <%=field.NameLowerCamel%> + <% } %> +<% } %> <%= for (service) in def.Services { %>class <%= service.Name %>: """<%= format_comment_line(service.Comment) %>""" def __init__(self, client): self.client = client <%= for (method) in service.Methods { %> - def <%= method.NameLowerCamel %>(self, <%= method.InputObject.ObjectNameLowerCamel %>): + def <%= method.NameLowerCamel %>(self, <%= method.InputObject.ObjectName %>) -> <%=method.OutputObject.ObjectName%>: """<%= format_comment_line(method.Comment) %>""" url = "{}/<%= service.Name %>.<%= method.Name %>".format(self.client.endpoint) headers = { 'Accept': 'application/json; charset=utf8', 'Content-Type': 'application/json; charset=utf8' } - r = requests.post(url, json=<%= method.InputObject.ObjectNameLowerCamel %>, headers=headers) + r = requests.post(url, json=<%= method.InputObject.ObjectName %>, headers=headers) if r.status_code != 200: raise OtoError(message="status code: {}".format(r.status_code)) j = r.json() @@ -40,6 +49,7 @@ class Error(Exception): """Base class for exceptions in this module.""" pass + class OtoError(Error): """Exception raised for an error making the request. @@ -50,6 +60,7 @@ class OtoError(Error): def __init__(self, message): self.message = message + class FieldError(Error): """Exception raised for missing fields. diff --git a/example/generate.sh b/example/generate.sh index 6c1db15..1842501 100755 --- a/example/generate.sh +++ b/example/generate.sh @@ -14,7 +14,7 @@ oto -template client.js.plush \ echo "generated client.gen.js" oto -template client.py.plush \ - -out client.gen.py \ + -out clientgen.py \ -pkg main \ ./def echo "generated client.gen.py" From 8209c8511f236e622fa41c4763ee87ec16c92ebe Mon Sep 17 00:00:00 2001 From: Seth Centerbar Date: Sun, 22 Nov 2020 01:25:16 -0500 Subject: [PATCH 4/6] Add clientgen.py for visibility of progress --- example/clientgen.py | 83 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 83 insertions(+) create mode 100644 example/clientgen.py diff --git a/example/clientgen.py b/example/clientgen.py new file mode 100644 index 0000000..e64a58a --- /dev/null +++ b/example/clientgen.py @@ -0,0 +1,83 @@ +# Code generated by oto; DO NOT EDIT. + +import requests +import json + + +class Client: + """Client provides access to the Greeter Service.""" + + def __init__(self, endpoint="http://localhost:8080/oto"): + self.endpoint = endpoint + if self.endpoint == "": + raise FieldError(field="endpoint", message="endpoint missing") + + +class GreetRequest: + """GreetRequest is the request object for GreeterService.Greet.""" + + def __init__(self, name: str, age: int) -> None: + self.name = name + self.age = age + + +class GreetResponse: + """GreetResponse is the response object containing a person's greeting.""" + + def __init__(self, greeting: str, error: str) -> None: + self.greeting = greeting + self.error = error + + +class GreeterService: + """GreeterService is a polite API for greeting people.""" + + def __init__(self, client): + self.client = client + + def greet(self, GreetRequest) -> GreetResponse: + """Greet prepares a lovely greeting.""" + url = "{}/GreeterService.Greet".format(self.client.endpoint) + headers = { + "Accept": "application/json; charset=utf8", + "Content-Type": "application/json; charset=utf8", + } + r = requests.post(url, json=GreetRequest, headers=headers) + if r.status_code != 200: + raise OtoError(message="status code: {}".format(r.status_code)) + j = r.json() + if "error" in j: + err = j.get("error") + if err != "": + raise OtoError(message=err) + return j + + +class Error(Exception): + """Base class for exceptions in this module.""" + + pass + + +class OtoError(Error): + """Exception raised for an error making the request. + + Attributes: + message -- explanation of the error + """ + + def __init__(self, message): + self.message = message + + +class FieldError(Error): + """Exception raised for missing fields. + + Attributes: + field -- field which the error occurred + message -- explanation of the error + """ + + def __init__(self, field, message): + self.field = field + self.message = message From 0bb3cebf1e907c1eeee4cc580247eb7506dd541a Mon Sep 17 00:00:00 2001 From: Seth Centerbar Date: Sun, 22 Nov 2020 18:47:47 -0500 Subject: [PATCH 5/6] Uploading WIP, will squash this one out later --- example/client.py.plush | 30 ++++++++++++--- example/clientgen.py | 83 ----------------------------------------- example/generate.sh | 2 +- 3 files changed, 26 insertions(+), 89 deletions(-) delete mode 100644 example/clientgen.py diff --git a/example/client.py.plush b/example/client.py.plush index b405d74..f2ba54d 100644 --- a/example/client.py.plush +++ b/example/client.py.plush @@ -14,10 +14,25 @@ class Client: <%= for (object) in def.Objects { %>class <%= object.Name %>: - """<%= format_comment_line(object.Comment) %>""" + """ + <%= format_comment_line(object.Comment) %> + + Attributes + ---------- + <%= for (field) in object.Fields { %><%=field.NameLowerCamel%> : <%= field.Type.PythonType %> + <%= format_comment_line(field.Comment) %> + <% } %> + """ - def __init__(self<%= for (field) in object.Fields { %>, <%=field.NameLowerCamel%>:<%= field.Type.PythonType%><% } %>) -> None: - <%= for (field) in object.Fields { %>self.<%=field.NameLowerCamel%> = <%=field.NameLowerCamel%> + def __init__(self<%= for (field) in object.Fields { %>, <%= field.NameLowerCamel %>: <%= field.Type.PythonType %><% } %>) -> None: + """ + Constructs all of the neccesary attributes for the <%= object.Name %> + + <%= for (field) in object.Fields { %><%=field.NameLowerCamel%> : <%= field.Type.PythonType %> + <%= format_comment_line(field.Comment) %> + <% } %> + """ + <%= for (field) in object.Fields { %>self.<%= field.NameLowerCamel %> = <%= field.NameLowerCamel %> <% } %> <% } %> <%= for (service) in def.Services { %>class <%= service.Name %>: @@ -26,8 +41,13 @@ class Client: def __init__(self, client): self.client = client <%= for (method) in service.Methods { %> - def <%= method.NameLowerCamel %>(self, <%= method.InputObject.ObjectName %>) -> <%=method.OutputObject.ObjectName%>: - """<%= format_comment_line(method.Comment) %>""" + def <%= method.NameLowerCamel %>(self, <%= method.InputObject.ObjectName %>: <%= method.InputObject.ObjectName %>) -> <%=method.OutputObject.ObjectName%>: + """ + <%= format_comment_line(method.Comment) %> + + :param <%= method.InputObject.ObjectName %> <%= method.InputObject.ObjectName %>: + + """ url = "{}/<%= service.Name %>.<%= method.Name %>".format(self.client.endpoint) headers = { 'Accept': 'application/json; charset=utf8', diff --git a/example/clientgen.py b/example/clientgen.py deleted file mode 100644 index e64a58a..0000000 --- a/example/clientgen.py +++ /dev/null @@ -1,83 +0,0 @@ -# Code generated by oto; DO NOT EDIT. - -import requests -import json - - -class Client: - """Client provides access to the Greeter Service.""" - - def __init__(self, endpoint="http://localhost:8080/oto"): - self.endpoint = endpoint - if self.endpoint == "": - raise FieldError(field="endpoint", message="endpoint missing") - - -class GreetRequest: - """GreetRequest is the request object for GreeterService.Greet.""" - - def __init__(self, name: str, age: int) -> None: - self.name = name - self.age = age - - -class GreetResponse: - """GreetResponse is the response object containing a person's greeting.""" - - def __init__(self, greeting: str, error: str) -> None: - self.greeting = greeting - self.error = error - - -class GreeterService: - """GreeterService is a polite API for greeting people.""" - - def __init__(self, client): - self.client = client - - def greet(self, GreetRequest) -> GreetResponse: - """Greet prepares a lovely greeting.""" - url = "{}/GreeterService.Greet".format(self.client.endpoint) - headers = { - "Accept": "application/json; charset=utf8", - "Content-Type": "application/json; charset=utf8", - } - r = requests.post(url, json=GreetRequest, headers=headers) - if r.status_code != 200: - raise OtoError(message="status code: {}".format(r.status_code)) - j = r.json() - if "error" in j: - err = j.get("error") - if err != "": - raise OtoError(message=err) - return j - - -class Error(Exception): - """Base class for exceptions in this module.""" - - pass - - -class OtoError(Error): - """Exception raised for an error making the request. - - Attributes: - message -- explanation of the error - """ - - def __init__(self, message): - self.message = message - - -class FieldError(Error): - """Exception raised for missing fields. - - Attributes: - field -- field which the error occurred - message -- explanation of the error - """ - - def __init__(self, field, message): - self.field = field - self.message = message diff --git a/example/generate.sh b/example/generate.sh index 1842501..d8bb0ad 100755 --- a/example/generate.sh +++ b/example/generate.sh @@ -14,7 +14,7 @@ oto -template client.js.plush \ echo "generated client.gen.js" oto -template client.py.plush \ - -out clientgen.py \ + -out ./python/clientgen.py \ -pkg main \ ./def echo "generated client.gen.py" From c41f5d1594469667253c0b0f5a6f4c1c8a61f8fc Mon Sep 17 00:00:00 2001 From: Seth Centerbar Date: Tue, 6 Apr 2021 23:18:22 -0400 Subject: [PATCH 6/6] Update numeric type to float for python --- parser/parser.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parser/parser.go b/parser/parser.go index 4cdedf3..b472834 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -435,7 +435,7 @@ func (p *Parser) parseFieldType(pkg *packages.Package, obj types.Object) (FieldT "float32", "float64": ftype.JSType = "number" ftype.SwiftType = "Double" - ftype.PythonType = "int" + ftype.PythonType = "float" } }