def _generate_struct_builder(self, struct): fields = [ "%s %s" % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace, use_interface=True)) for field in struct.all_required_fields ] self.emit('// New{0} returns a new {0} instance'.format(struct.name)) signature = "func New{0}({1}) *{0}".format(struct.name, ', '.join(fields)) with self.block(signature): self.emit('s := new({0})'.format(struct.name)) for field in struct.all_required_fields: field_name = fmt_var(field.name) self.emit("s.{0} = {0}".format(field_name)) for field in struct.all_optional_fields: if field.has_default: if is_primitive_type(field.data_type): default = field.default if is_boolean_type(field.data_type): default = str(default).lower() self.emit('s.{0} = {1}'.format(fmt_var(field.name), default)) elif is_union_type(field.data_type): self.emit('s.%s = &%s{Tagged:dropbox.Tagged{"%s"}}' % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace).lstrip('*'), field.default.tag_name)) self.emit('return s') self.emit()
def _generate_struct_builder(self, struct): fields = ["%s %s" % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace, use_interface=True)) for field in struct.all_required_fields] self.emit('// New{0} returns a new {0} instance'.format(struct.name)) signature = "func New{0}({1}) *{0}".format(struct.name, ', '.join(fields)) with self.block(signature): self.emit('s := new({0})'.format(struct.name)) for field in struct.all_required_fields: field_name = fmt_var(field.name) self.emit("s.{0} = {0}".format(field_name)) for field in struct.all_optional_fields: if field.has_default: if is_primitive_type(field.data_type): default = field.default if is_boolean_type(field.data_type): default = str(default).lower() self.emit('s.{0} = {1}'.format(fmt_var(field.name), default)) elif is_union_type(field.data_type): self.emit('s.%s = &%s{Tagged:dropbox.Tagged{"%s"}}' % (fmt_var(field.name), fmt_type(field.data_type, struct.namespace).lstrip('*'), field.default.tag_name)) self.emit('return s') self.emit()
def _generate_struct(self, struct): with self.block('type %s struct' % struct.name): if struct.parent_type: self.emit( fmt_type(struct.parent_type, struct.namespace).lstrip('*')) for field in struct.fields: self._generate_field(field, namespace=struct.namespace) if struct.name in ('DownloadArg', ): self.emit( '// ExtraHeaders can be used to pass Range, If-None-Match headers' ) self.emit('ExtraHeaders map[string]string `json:"-"`') self._generate_struct_builder(struct) self.emit() if needs_base_type(struct): self.emit('// UnmarshalJSON deserializes into a %s instance' % struct.name) with self.block('func (u *%s) UnmarshalJSON(b []byte) error' % struct.name): with self.block('type wrap struct'): for field in struct.all_fields: self._generate_field(field, namespace=struct.namespace, raw=_needs_base_type( field.data_type)) self.emit('var w wrap') with self.block('if err := json.Unmarshal(b, &w); err != nil'): self.emit('return err') for field in struct.all_fields: dt = field.data_type fn = fmt_var(field.name) tn = fmt_type(dt, namespace=struct.namespace, use_interface=True) if _needs_base_type(dt): if is_list_type(dt): self.emit("u.{0} = make({1}, len(w.{0}))".format( fn, tn)) # Grab the underlying type to get the correct Is...FromJSON method tn = fmt_type(dt.data_type, namespace=struct.namespace, use_interface=True) with self.block( "for i, e := range w.{0}".format(fn)): self.emit("v, err := {1}FromJSON(e)".format( fn, tn)) with self.block('if err != nil'): self.emit('return err') self.emit("u.{0}[i] = v".format(fn)) else: self.emit("{0}, err := {1}FromJSON(w.{0})".format( fn, tn)) with self.block('if err != nil'): self.emit('return err') self.emit("u.{0} = {0}".format(fn)) else: self.emit("u.{0} = w.{0}".format(fn)) self.emit('return nil')
def _generate_route(self, namespace, route): out = self.emit fn = fmt_var(route.name) err = fmt_type(route.error_data_type, namespace) out('//%sAPIError is an error-wrapper for the %s route' % (fn, route.name)) with self.block('type {fn}APIError struct'.format(fn=fn)): out('dropbox.APIError') out('EndpointError {err} `json:"error"`'.format(err=err)) out() signature = 'func (dbx *apiImpl) ' + self._generate_route_signature( namespace, route) with self.block(signature): out('cli := dbx.Client') out() self._generate_request(namespace, route) self._generate_post(route) self._generate_response(route) with self.block('if resp.StatusCode == http.StatusOK'): self._generate_result(route) self._generate_error_handling(route) out()
def _generate_route(self, namespace, route): out = self.emit fn = fmt_var(route.name) err = fmt_type(route.error_data_type, namespace) out('//%sAPIError is an error-wrapper for the %s route' % (fn, route.name)) with self.block('type {fn}APIError struct'.format(fn=fn)): out('dropbox.APIError') out('EndpointError {err} `json:"error"`'.format(err=err)) out() signature = 'func (dbx *apiImpl) ' + self._generate_route_signature( namespace, route) with self.block(signature): out('cli := dbx.Client') out() self._generate_request(namespace, route) self._generate_post() self._generate_response(route) with self.block('if resp.StatusCode == http.StatusOK'): self._generate_result(route) self._generate_error_handling(route) out()
def _generate_route(self, namespace, route): out = self.emit fn = fmt_var(route.name) err = fmt_type(route.error_data_type, namespace) out('//%sAPIError is an error-wrapper for the %s route' % (fn, route.name)) with self.block('type {fn}APIError struct'.format(fn=fn)): out('dropbox.APIError') out('EndpointError {err} `json:"error"`'.format(err=err)) out() signature = 'func (dbx *apiImpl) ' + self._generate_route_signature( namespace, route) with self.block(signature): if route.deprecated is not None: out('log.Printf("WARNING: API `%s` is deprecated")' % fn) if route.deprecated.by is not None: out('log.Printf("Use API `%s` instead")' % fmt_var(route.deprecated.by.name)) out() out('cli := dbx.Client') out() self._generate_request(namespace, route) self._generate_post() self._generate_response(route) ok_check = 'if resp.StatusCode == http.StatusOK' if fn == "Download": ok_check += ' || resp.StatusCode == http.StatusPartialContent' with self.block(ok_check): self._generate_result(route) self._generate_error_handling(route) out()
def _generate_base_type(self, base): t = fmt_type(base).lstrip('*') self.emit( '// Is{0} is the interface type for {0} and its subtypes'.format( t)) with self.block('type Is%s interface' % t): self.emit('Is%s()' % t) self.emit() self.emit('// Is{0} implements the Is{0} interface'.format(t)) self.emit("func (u *{0}) Is{0}() {{}}".format(t)) self.emit() self._generate_union_helper(base) self.emit( "// Is{0}FromJSON converts JSON to a concrete Is{0} instance". format(t)) with self.block( "func Is{0}FromJSON(data []byte) (Is{0}, error)".format(t)): name = fmt_var(t, export=False) + 'Union' self.emit("var t {0}".format(name)) with self.block("if err := json.Unmarshal(data, &t); err != nil"): self.emit("return nil, err") with self.block("switch t.Tag"): fields = base.get_enumerated_subtypes() for field in fields: with self.block('case "%s":' % field.name, delim=(None, None)): self.emit("return t.{0}, nil".format( fmt_var(field.name))) # FIX THIS self.emit("return nil, nil")
def _generate_field(self, field, union_field=False, namespace=None, raw=False): generate_doc(self, field) field_name = fmt_var(field.name) type_name = fmt_type(field.data_type, namespace, use_interface=True, raw=raw) json_tag = '`json:"%s"`' % field.name if is_nullable_type(field.data_type) or union_field: json_tag = '`json:"%s,omitempty"`' % field.name self.emit('%s %s %s' % (field_name, type_name, json_tag))
def _generate_struct(self, struct): with self.block('type %s struct' % struct.name): if struct.parent_type: self.emit(fmt_type(struct.parent_type, struct.namespace).lstrip('*')) for field in struct.fields: self._generate_field(field, namespace=struct.namespace) self.emit() self._generate_struct_builder(struct)
def _generate_route_signature(self, namespace, route): req = fmt_type(route.arg_data_type, namespace) res = fmt_type(route.result_data_type, namespace, use_interface=True) fn = fmt_var(route.name) style = route.attrs.get('style', 'rpc') arg = '' if is_void_type(route.arg_data_type) else 'arg {req}' ret = '(err error)' if is_void_type(route.result_data_type) else \ '(res {res}, err error)' signature = '{fn}(' + arg + ') ' + ret if style == 'download': signature = '{fn}(' + arg + \ ') (res {res}, content io.ReadCloser, err error)' elif style == 'upload': signature = '{fn}(' + arg + ', content io.Reader) ' + ret if is_void_type(route.arg_data_type): signature = '{fn}(content io.Reader) ' + ret return signature.format(fn=fn, req=req, res=res)
def _generate_struct(self, struct): with self.block('type %s struct' % struct.name): if struct.parent_type: self.emit( fmt_type(struct.parent_type, struct.namespace).lstrip('*')) for field in struct.fields: self._generate_field(field, namespace=struct.namespace) self.emit() self._generate_struct_builder(struct)
def _generate_struct(self, struct): with self.block('type %s struct' % struct.name): if struct.parent_type: self.emit(fmt_type(struct.parent_type, struct.namespace).lstrip('*')) for field in struct.fields: self._generate_field(field, namespace=struct.namespace) if struct.name in ('DownloadArg',): self.emit('// ExtraHeaders can be used to pass Range, If-None-Match headers') self.emit('ExtraHeaders map[string]string `json:"-"`') self._generate_struct_builder(struct)
def _generate_base_type(self, base): t = fmt_type(base).lstrip('*') self.emit('// Is{0} is the interface type for {0} and its subtypes'.format(t)) with self.block('type Is%s interface' % t): self.emit('Is%s()' % t) self.emit() self.emit('// Is{0} implements the Is{0} interface'.format(t)) self.emit("func (u *{0}) Is{0}() {{}}".format(t)) self.emit() self._generate_union_helper(base)
def _generate_field(self, field, union_field=False, namespace=None, raw=False): generate_doc(self, field) field_name = fmt_var(field.name) type_name = fmt_type(field.data_type, namespace, use_interface=True) json_tag = '`json:"%s"`' % field.name if is_nullable_type(field.data_type) or union_field: json_tag = '`json:"%s,omitempty"`' % field.name if raw: self.emit('%s json.RawMessage %s' % (field_name, json_tag)) else: self.emit('%s %s %s' % (field_name, type_name, json_tag))
def _generate_base_type(self, base): t = fmt_type(base).lstrip('*') self.emit( '// Is{0} is the interface type for {0} and its subtypes'.format( t)) with self.block('type Is%s interface' % t): self.emit('Is%s()' % t) self.emit() self.emit('// Is{0} implements the Is{0} interface'.format(t)) self.emit("func (u *{0}) Is{0}() {{}}".format(t)) self.emit() self._generate_union_helper(base)
def _generate_route(self, namespace, route): out = self.emit route_name = route.name if route.version != 1: route_name += '_v%d' % route.version fn = fmt_var(route.name) if route.version != 1: fn += 'V%d' % route.version err = fmt_type(route.error_data_type, namespace) out('//%sAPIError is an error-wrapper for the %s route' % (fn, route_name)) with self.block('type {fn}APIError struct'.format(fn=fn)): out('dropbox.APIError') out('EndpointError {err} `json:"error"`'.format(err=err)) out() signature = 'func (dbx *apiImpl) ' + self._generate_route_signature( namespace, route) with self.block(signature): if route.deprecated is not None: out('log.Printf("WARNING: API `%s` is deprecated")' % fn) if route.deprecated.by is not None: replacement_fn = fmt_var(route.deprecated.by.name) if route.deprecated.by.version != 1: replacement_fn += "V%d" % route.deprecated.by.version out('log.Printf("Use API `%s` instead")' % replacement_fn) out() args = { "Host": route.attrs.get('host', 'api'), "Namespace": namespace.name, "Route": route_name, "Auth": route.attrs.get('auth', ''), "Style": route.attrs.get('style', 'rpc'), } with self.block('req := dropbox.Request'): for k, v in args.items(): out(k + ':"' + v + '",') out("Arg: {arg},".format( arg="arg" if not is_void_type(route.arg_data_type) else "nil")) out("ExtraHeaders: {headers},".format( headers="arg.ExtraHeaders" if fmt_var(route.name) == "Download" else "nil")) out() out("var resp []byte") out("var respBody io.ReadCloser") out("resp, respBody, err = (*dropbox.Context)(dbx).Execute(req, {body})" .format(body="content" if route.attrs.get('style', '') == 'upload' else "nil")) with self.block("if err != nil"): out("var appErr {fn}APIError".format(fn=fn)) out("err = {auth}ParseError(err, &appErr)".format( auth="auth." if namespace.name != "auth" else "")) with self.block("if err == &appErr"): out("err = appErr") out("return") out() if is_struct_type( route.result_data_type ) and route.result_data_type.has_enumerated_subtypes(): out('var tmp %sUnion' % fmt_var(route.result_data_type.name, export=False)) with self.block('err = json.Unmarshal(resp, &tmp);' 'if err != nil'): out('return') with self.block('switch tmp.Tag'): for t in route.result_data_type.get_enumerated_subtypes(): with self.block('case "%s":' % t.name, delim=(None, None)): self.emit('res = tmp.%s' % fmt_var(t.name)) elif not is_void_type(route.result_data_type): with self.block('err = json.Unmarshal(resp, &res);' 'if err != nil'): out('return') out() else: out("_ = resp") if route.attrs.get('style', 'rpc') == "download": out("content = respBody") else: out("_ = respBody") out('return') out()