OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
t_py_generator.cc
Go to the documentation of this file.
1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  */
19 
20 #include <string>
21 #include <fstream>
22 #include <iostream>
23 #include <vector>
24 
25 #include <stdlib.h>
26 #include <sys/stat.h>
27 #include <sys/types.h>
28 #include <sstream>
29 #include <algorithm>
30 #include "t_generator.h"
31 #include "platform.h"
32 #include "version.h"
33 
34 #ifdef SANDESH
35 #include <cassert>
36 #include "boost/tuple/tuple.hpp"
37 #endif
38 using namespace std;
39 
40 
45 class t_py_generator : public t_generator {
46  public:
48  t_program* program,
49  const std::map<std::string, std::string>& parsed_options,
50  const std::string& option_string)
51  : t_generator(program)
52  {
53  (void) option_string;
54  std::map<std::string, std::string>::const_iterator iter;
55 
56  iter = parsed_options.find("new_style");
57  gen_newstyle_ = (iter != parsed_options.end());
58 
59  iter = parsed_options.find("slots");
60  gen_slots_ = (iter != parsed_options.end());
61 
62  iter = parsed_options.find("dynamic");
63  gen_dynamic_ = (iter != parsed_options.end());
64 
65  if (gen_dynamic_) {
66  gen_newstyle_ = 0; // dynamic is newstyle
67  gen_dynbaseclass_ = "TBase";
68  gen_dynbaseclass_exc_ = "TExceptionBase";
69  import_dynbase_ = "from thrift.protocol.TBase import TBase, TExceptionBase\n";
70  }
71 
72  iter = parsed_options.find("dynbase");
73  if (iter != parsed_options.end()) {
74  gen_dynbase_ = true;
75  gen_dynbaseclass_ = (iter->second);
76  }
77 
78  iter = parsed_options.find("dynexc");
79  if (iter != parsed_options.end()) {
80  gen_dynbaseclass_exc_ = (iter->second);
81  }
82 
83  iter = parsed_options.find("dynimport");
84  if (iter != parsed_options.end()) {
85  gen_dynbase_ = true;
86  import_dynbase_ = (iter->second);
87  }
88 
89  iter = parsed_options.find("twisted");
90  gen_twisted_ = (iter != parsed_options.end());
91 
92  iter = parsed_options.find("utf8strings");
93  gen_utf8strings_ = (iter != parsed_options.end());
94 
95  copy_options_ = option_string;
96 
97  if (gen_twisted_){
98  out_dir_base_ = "gen-py.twisted";
99  } else {
100  out_dir_base_ = "gen-py";
101  }
102  }
103 
108  void init_generator();
109  void close_generator();
110 
115  void generate_typedef (t_typedef* ttypedef);
116  void generate_enum (t_enum* tenum);
117  void generate_const (t_const* tconst);
118  void generate_struct (t_struct* tstruct);
119  void generate_xception (t_struct* txception);
120  void generate_service (t_service* tservice);
121 #ifdef SANDESH
122  void generate_sandesh (t_sandesh* tsandesh);
123 #endif
124  std::string render_const_value(t_type* type, t_const_value* value);
125 
130  void generate_py_struct(t_struct* tstruct, bool is_exception);
131  void generate_py_struct_definition(std::ofstream& out, t_struct* tstruct, bool is_xception=false, bool is_result=false);
132  void generate_py_struct_reader(std::ofstream& out, t_struct* tstruct);
133  void generate_py_struct_writer(std::ofstream& out, t_struct* tstruct);
134  void generate_py_struct_required_validator(std::ofstream& out, t_struct* tstruct);
135  void generate_py_function_helpers(t_function* tfunction);
136 #ifdef SANDESH
137  void generate_py_struct_logger(std::ofstream& out, t_struct* tstruct);
138  void generate_py_struct_sizeof(std::ofstream& out, t_struct* tstruct);
139 #endif
140 
144 #ifdef SANDESH
145  void generate_py_sandesh(t_sandesh *tsandesh);
146  void generate_py_sandesh_definition(std::ofstream& out, t_sandesh* tsandesh);
147  void generate_py_sandesh_reader(std::ofstream& out, t_sandesh* tsandesh);
148  void generate_py_sandesh_writer(std::ofstream& out, t_sandesh* tsandesh);
149  void generate_py_sandesh_compare(std::ofstream& out, t_sandesh* tsandesh);
150  void generate_py_sandesh_required_validator(std::ofstream& out, t_sandesh* tsandesh);
151  void generate_py_sandesh_http_request_handler(std::ofstream& out, t_sandesh* tsandesh);
152  void generate_py_sandesh_http_attr(ofstream& out,
153  t_type *ftype, const std::string& namel, const std::string& namer);
154  void generate_py_sandesh_skeleton_request(std::ofstream& out, t_sandesh* tsandesh);
155  void generate_py_sandesh_request_list(std::ofstream& out);
156  void generate_py_sandesh_http_request_list(std::ofstream& out, t_sandesh* tsandesh);
157  void generate_struct_log(std::ofstream& out, std::string prefix, std::string log_str);
158  void generate_container_log(std::ofstream& out, std::string prefix, t_type* ttype, string log_str);
159  void generate_field_log(std::ofstream& out, t_field *tfield, std::string log_str, std::string prefix);
160  void generate_py_sandesh_logger(std::ofstream& out, t_sandesh* tsandesh);
161  void generate_py_sandesh_hint(std::ofstream& out, t_sandesh* tsandesh);
162  void generate_py_sandesh_async(std::ofstream& out, t_sandesh* tsandesh);
163  void generate_py_sandesh_request(std::ofstream& out, t_sandesh* tsandesh);
164  void generate_py_sandesh_response(std::ofstream& out, t_sandesh* tsandesh);
165  void generate_py_sandesh_uve(std::ofstream& out, t_sandesh* tsandesh, bool update);
166  void generate_py_sandesh_uve_list(std::ofstream& out);
167  void generate_py_sandesh_alarm_list(std::ofstream& out);
168  void generate_py_sandesh_trace(std::ofstream& out, t_sandesh* tsandesh);
169  void generate_py_sandesh_sizeof(std::ofstream& out, t_sandesh* tsandesh);
170 #endif
171 
172 #ifdef SANDESH
173  void generate_py_sizeof(std::ofstream& out, const vector<t_field*>& fields);
174 #endif
175 
180  void generate_service_helpers (t_service* tservice);
181  void generate_service_interface (t_service* tservice);
182  void generate_service_client (t_service* tservice);
183  void generate_service_remote (t_service* tservice);
184  void generate_service_server (t_service* tservice);
185  void generate_process_function (t_service* tservice, t_function* tfunction);
186 
191  void generate_deserialize_field (std::ofstream &out,
192  t_field* tfield,
193  std::string prefix="",
194  bool inclass=false);
195 
196  void generate_deserialize_struct (std::ofstream &out,
197  t_struct* tstruct,
198  std::string prefix="");
199 
200  void generate_deserialize_container (std::ofstream &out,
201  t_type* ttype,
202  std::string prefix="");
203 
204  void generate_deserialize_set_element (std::ofstream &out,
205  t_set* tset,
206  std::string prefix="");
207 
208  void generate_deserialize_map_element (std::ofstream &out,
209  t_map* tmap,
210  std::string prefix="");
211 
212  void generate_deserialize_list_element (std::ofstream &out,
213  t_list* tlist,
214  std::string prefix="");
215 
216  void generate_serialize_field (std::ofstream &out,
217  t_field* tfield,
218  std::string prefix="");
219 
220  void generate_serialize_struct (std::ofstream &out,
221  t_struct* tstruct,
222  std::string prefix="");
223 
224 #ifdef SANDESH
225  void generate_serialize_sandesh (std::ofstream &out,
226  t_sandesh* tsandesh,
227  std::string prefix="");
228 #endif
229 
230  void generate_serialize_container (std::ofstream &out,
231  t_type* ttype,
232  std::string prefix="");
233 
234  void generate_serialize_map_element (std::ofstream &out,
235  t_map* tmap,
236  std::string kiter,
237  std::string viter);
238 
239  void generate_serialize_set_element (std::ofstream &out,
240  t_set* tmap,
241  std::string iter);
242 
243  void generate_serialize_list_element (std::ofstream &out,
244  t_list* tlist,
245  std::string iter);
246 
247  void generate_python_docstring (std::ofstream& out,
248  t_struct* tstruct);
249 
250  void generate_python_docstring (std::ofstream& out,
251  t_function* tfunction);
252 
253  void generate_python_docstring (std::ofstream& out,
254  t_doc* tdoc,
255  t_struct* tstruct,
256  const char* subheader);
257 
258  void generate_python_docstring (std::ofstream& out,
259  t_doc* tdoc);
260 
265  std::string py_autogen_comment();
266  std::string future_imports();
267 #ifdef SANDESH
268  std::string py_autogen_sandesh_request_skeleton_comment();
269  void py_autogen_sandesh_http_request_open(std::ofstream& out);
270  void py_autogen_sandesh_http_request_close(std::ofstream& out);
271 #endif
272  std::string py_imports();
273  std::string render_includes();
274  std::string render_fastbinary_includes();
275 #ifdef SANDESH
276  std::string render_sandesh_includes();
277 #endif
278  std::string declare_argument(t_field* tfield);
279  std::string render_field_default_value(t_field* tfield);
280  std::string type_name(t_type* ttype);
281  std::string function_signature(t_function* tfunction, std::string prefix="");
282  std::string function_signature_if(t_function* tfunction, std::string prefix="");
283  std::string argument_list(t_struct* tstruct);
284  std::string type_to_enum(t_type* ttype);
285  std::string type_to_spec_args(t_type* ttype);
286 
287  static bool is_valid_namespace(const std::string& sub_namespace) {
288  return sub_namespace == "twisted";
289  }
290 
291  static std::string get_real_py_module(const t_program* program, bool gen_twisted) {
292  if(gen_twisted) {
293  std::string twisted_module = program->get_namespace("py.twisted");
294  if(!twisted_module.empty()){
295  return twisted_module;
296  }
297  }
298 
299  std::string real_module = program->get_namespace("py");
300  if (real_module.empty()) {
301  return program->get_name();
302  }
303  return real_module;
304  }
305 
306  private:
307 
312 
317 
319  std::string gen_dynbaseclass_;
321 
322  std::string import_dynbase_;
323 
325 
326  std::string copy_options_;
327 
332 
337 
338 #ifdef SANDESH
339 
342  std::vector<std::string> sandesh_req_list_;
343 
347  std::vector<boost::tuple<std::string, std::string> > sandesh_uve_list_;
348 
352  std::vector<boost::tuple<std::string, std::string> > sandesh_alarm_list_;
353 #endif
354 
359  std::ofstream f_types_;
360  std::ofstream f_consts_;
361  std::ofstream f_service_;
362 #ifdef SANDESH
363  std::ofstream f_request_impl_;
364  std::ofstream f_http_request_;
365 #endif
366 
367  std::string package_dir_;
368 
369 };
370 
371 
379  // Make output directory
380  string module = get_real_py_module(program_, gen_twisted_);
381  package_dir_ = get_out_dir();
382  while (true) {
383  // TODO: Do better error checking here.
384  MKDIR(package_dir_.c_str());
385  std::ofstream init_py((package_dir_+"/__init__.py").c_str());
386  init_py.close();
387  if (module.empty()) {
388  break;
389  }
390  string::size_type pos = module.find('.');
391  if (pos == string::npos) {
392  package_dir_ += "/";
393  package_dir_ += module;
394  module.clear();
395  } else {
396  package_dir_ += "/";
397  package_dir_ += module.substr(0, pos);
398  module.erase(0, pos+1);
399  }
400  }
401 
402  // Make output file
403  string f_types_name = package_dir_+"/"+"ttypes.py";
404  f_types_.open(f_types_name.c_str());
405 
406  string f_consts_name = package_dir_+"/"+"constants.py";
407  f_consts_.open(f_consts_name.c_str());
408 
409  string f_init_name = package_dir_+"/__init__.py";
410  ofstream f_init;
411  f_init.open(f_init_name.c_str());
412  f_init <<
413  "__all__ = ['ttypes', 'constants'";
414  vector<t_service*> services = program_->get_services();
415  vector<t_service*>::iterator sv_iter;
416  for (sv_iter = services.begin(); sv_iter != services.end(); ++sv_iter) {
417  f_init << ", '" << (*sv_iter)->get_name() << "'";
418  }
419  f_init << "]" << endl;
420  f_init.close();
421 
422  // Print header
423  f_types_ <<
424  py_autogen_comment() << endl <<
425  py_imports() << endl <<
426  future_imports() << endl <<
427  render_includes() << endl <<
428  render_fastbinary_includes() <<
429  render_sandesh_includes() <<
430  endl << endl;
431 
432  f_consts_ <<
433  py_autogen_comment() << endl <<
434  py_imports() << endl <<
435  "from .ttypes import *" << endl <<
436  endl;
437 #ifdef SANDESH
438  string f_request_impl_name = package_dir_+"/request_skeleton.py";
439  f_request_impl_.open(f_request_impl_name.c_str());
440  f_request_impl_ <<
441  py_autogen_comment() << endl;
442  f_request_impl_ <<
443  py_autogen_sandesh_request_skeleton_comment() << endl;
444 
445  string f_http_request_name = package_dir_+"/http_request.py";
446  f_http_request_.open(f_http_request_name.c_str());
447  f_http_request_ <<
448  py_autogen_comment() << endl;
449  f_http_request_ <<
450  "from . import ttypes" << endl;
451  py_autogen_sandesh_http_request_open(f_http_request_);
452 #endif
453 }
454 
459  const vector<t_program*>& includes = program_->get_includes();
460  string result = "";
461  for (size_t i = 0; i < includes.size(); ++i) {
462  result += "from ." + get_real_py_module(includes[i], gen_twisted_) +
463  " import ttypes as " + get_real_py_module(includes[i], gen_twisted_) + "_ttypes\n";
464  }
465  if (includes.size() > 0) {
466  result += "\n";
467  }
468  return result;
469 }
470 
475  string hdr = "";
476  if (gen_dynamic_) {
477  hdr += std::string(import_dynbase_);
478  } else {
479 #ifdef SANDESH
480  hdr +=
481  "from pysandesh.transport import TTransport\n"
482  "from pysandesh.protocol import TBinaryProtocol, TProtocol\n"
483  "try:\n"
484  " from pysandesh.protocol import fastbinary\n"
485  "except:\n"
486  " fastbinary = None\n";
487 #else
488  hdr +=
489  "from thrift.transport import TTransport\n"
490  "from thrift.protocol import TBinaryProtocol, TProtocol\n"
491  "try:\n"
492  " from thrift.protocol import fastbinary\n"
493  "except:\n"
494  " fastbinary = None\n";
495 #endif
496  }
497  return hdr;
498 }
499 
500 #ifdef SANDESH
501 string t_py_generator::render_sandesh_includes() {
502  std::string module = get_real_py_module(program_, gen_twisted_);
503  std::string sandesh_includes("\n");
504  sandesh_includes +=
505  "from io import StringIO\n"
506  "import uuid\n"
507  "import netaddr\n"
508  "from sys import getsizeof\n"
509  "from itertools import chain\n";
510  if (module != "sandesh") {
511  sandesh_includes +=
512  "import bottle\n"
513  "from pysandesh import sandesh_base\n"
514  "from pysandesh.sandesh_http import SandeshHttp\n"
515  "from pysandesh.sandesh_uve import SandeshUVETypeMaps\n"
516  "from pysandesh.util import UTCTimestampUsec, UTCTimestampUsecToString\n"
517  "from pysandesh import util\n"
518  "from pysandesh.gen_py.sandesh.constants import *\n";
519  }
520  return sandesh_includes;
521 }
522 #endif
523 
528 #ifdef SANDESH
529  return
530  std::string("#\n") +
531  "# Autogenerated by Sandesh Compiler (" + SANDESH_VERSION + ")\n" +
532  "#\n" +
533  "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
534  "#\n" +
535  "# options string: " + copy_options_ + "\n" +
536  "# Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.\n" +
537  "#\n";
538 #else
539  return
540  std::string("#\n") +
541  "# Autogenerated by Thrift Compiler \n" +
542  "#\n" +
543  "# DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING\n" +
544  "#\n" +
545  "# options string: " + copy_options_ + "\n" +
546  "#\n";
547 #endif
548 }
549 
554 #ifdef SANDESH
555  return
556  string("from pysandesh.Thrift import TType, TMessageType, TException");
557 #else
558  return
559  string("from thrift.Thrift import TType, TMessageType, TException");
560 #endif
561 }
562 
567  std::string future_imports("\n");
568  return future_imports;
569 }
570 
575 #ifdef SANDESH
576  generate_py_sandesh_request_list(f_types_);
577  generate_py_sandesh_uve_list(f_types_);
578  generate_py_sandesh_alarm_list(f_types_);
579 #endif
580  // Close types file
581  f_types_.close();
582  f_consts_.close();
583 #ifdef SANDESH
584  f_request_impl_.close();
585  py_autogen_sandesh_http_request_close(f_http_request_);
586  f_http_request_.close();
587 #endif
588 }
589 
596  (void) ttypedef;
597 }
598 
606  std::ostringstream to_string_mapping, from_string_mapping;
607 
608  f_types_ <<
609  "class " << tenum->get_name() <<
610  (gen_newstyle_ ? "(object)" : "") <<
611  (gen_dynamic_ ? "(" + gen_dynbaseclass_ + ")" : "") <<
612  ":" << endl;
613  indent_up();
614  generate_python_docstring(f_types_, tenum);
615 
616  to_string_mapping << indent() << "_VALUES_TO_NAMES = {" << endl;
617  from_string_mapping << indent() << "_NAMES_TO_VALUES = {" << endl;
618 
619  vector<t_enum_value*> constants = tenum->get_constants();
620  vector<t_enum_value*>::iterator c_iter;
621  for (c_iter = constants.begin(); c_iter != constants.end(); ++c_iter) {
622  int value = (*c_iter)->get_value();
623  indent(f_types_) << (*c_iter)->get_name() << " = " << value << endl;
624 
625  // Dictionaries to/from string names of enums
626  to_string_mapping <<
627  indent() << indent() << value << ": \"" <<
628  escape_string((*c_iter)->get_name()) << "\"," << endl;
629  from_string_mapping <<
630  indent() << indent() << '"' << escape_string((*c_iter)->get_name()) <<
631  "\": " << value << ',' << endl;
632  }
633  to_string_mapping << indent() << "}" << endl;
634  from_string_mapping << indent() << "}" << endl;
635 
636  indent_down();
637  f_types_ << endl;
638  f_types_ << to_string_mapping.str() << endl << from_string_mapping.str() << endl;
639 }
640 
645  t_type* type = tconst->get_type();
646  string name = tconst->get_name();
647  t_const_value* value = tconst->get_value();
648 
649  indent(f_consts_) << name << " = " << render_const_value(type, value);
650  f_consts_ << endl;
651 }
652 
659  type = get_true_type(type);
660  std::ostringstream out;
661 
662  if (type->is_base_type()) {
663  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
664  switch (tbase) {
666 #ifdef SANDESH
667  case t_base_type::TYPE_STATIC_CONST_STRING:
668  case t_base_type::TYPE_XML:
669 #endif
670  out << '"' << get_escaped_string(value) << '"';
671  break;
673  out << (value->get_integer() > 0 ? "True" : "False");
674  break;
679 #ifdef SANDESH
680  case t_base_type::TYPE_U16:
681  case t_base_type::TYPE_U32:
682  case t_base_type::TYPE_U64:
683  case t_base_type::TYPE_IPV4:
684 #endif
685  out << value->get_integer();
686  break;
688  if (value->get_type() == t_const_value::CV_INTEGER) {
689  out << value->get_integer();
690  } else {
691  out << value->get_double();
692  }
693  break;
694 #ifdef SANDESH
695  case t_base_type::TYPE_UUID:
696  out << "uuid.UUID('{" << get_escaped_string(value) <<"}')";
697  break;
698  case t_base_type::TYPE_IPADDR:
699  out << "netaddr.IPAddress('" << value->get_string() << "')";
700  break;
701 #endif
702  default:
703  throw "compiler error: no const of base type " + t_base_type::t_base_name(tbase);
704  }
705  } else if (type->is_enum()) {
706  indent(out) << value->get_integer();
707  } else if (type->is_struct() || type->is_xception()) {
708  out << type->get_name() << "(**{" << endl;
709  indent_up();
710  const vector<t_field*>& fields = ((t_struct*)type)->get_members();
711  vector<t_field*>::const_iterator f_iter;
712  const map<t_const_value*, t_const_value*>& val = value->get_map();
713  map<t_const_value*, t_const_value*>::const_iterator v_iter;
714  for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
715  t_type* field_type = NULL;
716  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
717  if ((*f_iter)->get_name() == v_iter->first->get_string()) {
718  field_type = (*f_iter)->get_type();
719  }
720  }
721  if (field_type == NULL) {
722  throw "type error: " + type->get_name() + " has no field " + v_iter->first->get_string();
723  }
724  out << indent();
725  out << render_const_value(g_type_string, v_iter->first);
726  out << " : ";
727  out << render_const_value(field_type, v_iter->second);
728  out << "," << endl;
729  }
730  indent_down();
731  indent(out) << "})";
732  } else if (type->is_map()) {
733  t_type* ktype = ((t_map*)type)->get_key_type();
734  t_type* vtype = ((t_map*)type)->get_val_type();
735  out << "{" << endl;
736  indent_up();
737  const map<t_const_value*, t_const_value*>& val = value->get_map();
738  map<t_const_value*, t_const_value*>::const_iterator v_iter;
739  for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
740  out << indent();
741  out << render_const_value(ktype, v_iter->first);
742  out << " : ";
743  out << render_const_value(vtype, v_iter->second);
744  out << "," << endl;
745  }
746  indent_down();
747  indent(out) << "}";
748  } else if (type->is_list() || type->is_set()) {
749  t_type* etype;
750  if (type->is_list()) {
751  etype = ((t_list*)type)->get_elem_type();
752  } else {
753  etype = ((t_set*)type)->get_elem_type();
754  }
755  if (type->is_set()) {
756  out << "set(";
757  }
758  out << "[" << endl;
759  indent_up();
760  const vector<t_const_value*>& val = value->get_list();
761  vector<t_const_value*>::const_iterator v_iter;
762  for (v_iter = val.begin(); v_iter != val.end(); ++v_iter) {
763  out << indent();
764  out << render_const_value(etype, *v_iter);
765  out << "," << endl;
766  }
767  indent_down();
768  indent(out) << "]";
769  if (type->is_set()) {
770  out << ")";
771  }
772  } else {
773  throw "CANNOT GENERATE CONSTANT FOR TYPE: " + type->get_name();
774  }
775 
776  return out.str();
777 }
778 
783  generate_py_struct(tstruct, false);
784 }
785 
793  generate_py_struct(txception, true);
794 }
795 
796 void t_py_generator::generate_sandesh(t_sandesh* tsandesh) {
797  generate_py_sandesh(tsandesh);
798 }
799 
804  bool is_exception) {
805  generate_py_struct_definition(f_types_, tstruct, is_exception);
806 }
807 
814  t_struct* tstruct,
815  bool is_exception,
816  bool is_result) {
817  (void) is_result;
818  const vector<t_field*>& members = tstruct->get_members();
819  const vector<t_field*>& sorted_members = tstruct->get_sorted_members();
820  vector<t_field*>::const_iterator m_iter;
821 
822  out << std::endl <<
823  "class " << tstruct->get_name();
824  if (is_exception) {
825  if (gen_dynamic_) {
826  out << "(" << gen_dynbaseclass_exc_ << ")";
827  } else {
828  out << "(TException)";
829  }
830  } else {
831  if (gen_newstyle_) {
832  out << "(object)";
833  } else if (gen_dynamic_) {
834  out << "(" << gen_dynbaseclass_ << ")";
835  }
836  }
837  out << ":" << endl;
838  indent_up();
839  generate_python_docstring(out, tstruct);
840 
841  out << endl;
842 
843  /*
844  Here we generate the structure specification for the fastbinary codec.
845  These specifications have the following structure:
846  thrift_spec -> tuple of item_spec
847  item_spec -> None | (tag, type_enum, name, spec_args, default)
848  tag -> integer
849  type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ...
850  name -> string_literal
851  default -> None # Handled by __init__
852  spec_args -> None # For simple types
853  | (type_enum, spec_args) # Value type for list/set
854  | (type_enum, spec_args, type_enum, spec_args)
855  # Key and value for map
856  | (class_name, spec_args_ptr) # For struct/exception
857  class_name -> identifier # Basically a pointer to the class
858  spec_args_ptr -> expression # just class_name.spec_args
859 
860  TODO(dreiss): Consider making this work for structs with negative tags.
861  */
862 
863  if (gen_slots_) {
864  indent(out) << "__slots__ = [ " << endl;
865  indent_up();
866  for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
867  indent(out) << "'" << (*m_iter)->get_name() << "'," << endl;
868  }
869  indent_down();
870  indent(out) << " ]" << endl << endl;
871 
872  }
873 
874  // TODO(dreiss): Look into generating an empty tuple instead of None
875  // for structures with no members.
876  // TODO(dreiss): Test encoding of structs where some inner structs
877  // don't have thrift_spec.
878  if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) {
879  indent(out) << "thrift_spec = (" << endl;
880  indent_up();
881 
882  int sorted_keys_pos = 0;
883  for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
884 
885  for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) {
886  indent(out) << "None, # " << sorted_keys_pos << endl;
887  }
888 
889  indent(out) << "(" << (*m_iter)->get_key() << ", "
890  << type_to_enum((*m_iter)->get_type()) << ", "
891  << "'" << (*m_iter)->get_name() << "'" << ", "
892  << type_to_spec_args((*m_iter)->get_type()) << ", "
893  << render_field_default_value(*m_iter) << ", "
894  << "),"
895  << " # " << sorted_keys_pos
896  << endl;
897 
898  sorted_keys_pos ++;
899  }
900 
901  indent_down();
902  indent(out) << ")" << endl << endl;
903  } else {
904  indent(out) << "thrift_spec = None" << endl;
905  }
906 
907 
908  if (members.size() > 0) {
909  out <<
910  indent() << "def __init__(self,";
911 
912  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
913 #ifdef SANDESH
914  // skip const string
915  t_type* type = get_true_type((*m_iter)->get_type());
916  if (type->is_static_const_string()) {
917  continue;
918  }
919 #endif
920  // This fills in default values, as opposed to nulls
921  out << " " << declare_argument(*m_iter) << ",";
922  }
923 
924  out << "):" << endl;
925 
926  indent_up();
927 
928  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
929  // Initialize fields
930  t_type* type = (*m_iter)->get_type();
931  if (!type->is_base_type() && !type->is_enum() && (*m_iter)->get_value() != NULL) {
932  indent(out) <<
933  "if " << (*m_iter)->get_name() << " is " << "self.thrift_spec[" <<
934  (*m_iter)->get_key() << "][4]:" << endl;
935  indent(out) << " " << (*m_iter)->get_name() << " = " <<
936  render_field_default_value(*m_iter) << endl;
937 #ifdef SANDESH
938  } else if (type->is_static_const_string()) {
939  indent(out) <<
940  "self." << (*m_iter)->get_name() << " = " <<
941  render_const_value(type, (*m_iter)->get_value()) << endl;
942  } else {
943 #else
944  }
945 #endif
946  indent(out) <<
947  "self." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << endl;
948 #ifdef SANDESH
949  }
950 #endif
951  }
952 
953 #ifdef SANDESH
954  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
955  if ((*m_iter)->get_name() == "name") {
956  std::map<std::string, std::string>::iterator it;
957  it = (*m_iter)->annotations_.find("key");
958  if (it != (*m_iter)->annotations_.end()) {
959  indent(out) << "self._table = '" << it->second << "'" << endl;
960  }
961  break;
962  }
963  }
964 #endif
965 
966  indent_down();
967 
968  out << endl;
969  }
970 
971  if (!gen_dynamic_) {
972  generate_py_struct_reader(out, tstruct);
973  generate_py_struct_writer(out, tstruct);
974  }
975 
976 #ifdef SANDESH
977  generate_py_struct_logger(out, tstruct);
978  generate_py_struct_sizeof(out, tstruct);
979 #endif
980 
981  // For exceptions only, generate a __str__ method. This is
982  // because when raised exceptions are printed to the console, __repr__
983  // isn't used. See python bug #5882
984  if (is_exception) {
985  out <<
986  indent() << "def __str__(self):" << endl <<
987  indent() << " return repr(self)" << endl <<
988  endl;
989  }
990 
991  if (!gen_slots_) {
992  // Printing utilities so that on the command line thrift
993  // structs look pretty like dictionaries
994  out <<
995  indent() << "def __repr__(self):" << endl <<
996  indent() << " L = ['%s=%r' % (key, value)" << endl <<
997  indent() << " for key, value in self.__dict__.items()]" << endl <<
998  indent() << " return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl <<
999  endl;
1000 
1001  // Equality and inequality methods that compare by value
1002  out <<
1003  indent() << "def __eq__(self, other):" << endl;
1004  indent_up();
1005  out <<
1006  indent() << "return isinstance(other, self.__class__) and "
1007  "self.__dict__ == other.__dict__" << endl;
1008  indent_down();
1009  out << endl;
1010 
1011  out <<
1012  indent() << "def __ne__(self, other):" << endl;
1013  indent_up();
1014 
1015  out <<
1016  indent() << "return not (self == other)" << endl;
1017  indent_down();
1018  out << endl;
1019 
1020  // In python2 __hash__ function is implicit for user-defined objects
1021  // For python3, return id of object as hash which is status quo in python2.
1022  out <<
1023  indent() << "def __hash__(self):" << endl;
1024  indent_up();
1025 
1026  out <<
1027  indent() << "return id(self)" << endl;
1028  indent_down();
1029  } else if (!gen_dynamic_) {
1030  // no base class available to implement __eq__ and __repr__ and __ne__ for us
1031  // so we must provide one that uses __slots__
1032  out <<
1033  indent() << "def __repr__(self):" << endl <<
1034  indent() << " L = ['%s=%r' % (key, getattr(self, key))" << endl <<
1035  indent() << " for key in self.__slots__]" << endl <<
1036  indent() << " return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl <<
1037  endl;
1038 
1039  // Equality method that compares each attribute by value and type, walking __slots__
1040  out <<
1041  indent() << "def __eq__(self, other):" << endl <<
1042  indent() << " if not isinstance(other, self.__class__):" << endl <<
1043  indent() << " return False" << endl <<
1044  indent() << " for attr in self.__slots__:" << endl <<
1045  indent() << " my_val = getattr(self, attr)" << endl <<
1046  indent() << " other_val = getattr(other, attr)" << endl <<
1047  indent() << " if my_val != other_val:" << endl <<
1048  indent() << " return False" << endl <<
1049  indent() << " return True" << endl <<
1050  endl;
1051 
1052  out <<
1053  indent() << "def __ne__(self, other):" << endl <<
1054  indent() << " return not (self == other)" << endl <<
1055  endl;
1056  }
1057  indent_down();
1058 }
1059 
1064  t_struct* tstruct) {
1065  const vector<t_field*>& fields = tstruct->get_members();
1066  vector<t_field*>::const_iterator f_iter;
1067 
1068  indent(out) <<
1069  "def read(self, iprot):" << endl;
1070  indent_up();
1071 
1072  indent(out) <<
1073  "if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated "
1074  "and isinstance(iprot.trans, TTransport.CReadableTransport) "
1075  "and self.thrift_spec is not None "
1076  "and fastbinary is not None:" << endl;
1077  indent_up();
1078 
1079  indent(out) <<
1080  "fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))" << endl;
1081 #ifdef SANDESH
1082  indent(out) <<
1083  "return 0" << endl;
1084 #else
1085  indent(out) <<
1086  "return" << endl;
1087 #endif
1088  indent_down();
1089 
1090 #ifdef SANDESH
1091  indent(out) <<
1092  "read_cnt = 0" << endl;
1093 #endif
1094 
1095 #ifdef SANDESH
1096  indent(out) <<
1097  "length = iprot.readStructBegin()" << endl;
1098  indent(out) <<
1099  "if length < 0: return -1" << endl;
1100  indent(out) <<
1101  "read_cnt += length" << endl;
1102 #else
1103  indent(out) <<
1104  "iprot.readStructBegin()" << endl;
1105 #endif
1106 
1107  // Loop over reading in fields
1108  indent(out) <<
1109  "while True:" << endl;
1110  indent_up();
1111 
1112  // Read beginning field marker
1113 #ifdef SANDESH
1114  indent(out) <<
1115  "(length, fname, ftype, fid) = iprot.readFieldBegin()" << endl;
1116  indent(out) <<
1117  "if length < 0: return -1" << endl;
1118  indent(out) <<
1119  "read_cnt += length" << endl;
1120 #else
1121  indent(out) <<
1122  "(fname, ftype, fid) = iprot.readFieldBegin()" << endl;
1123 #endif
1124 
1125  // Check for field STOP marker and break
1126  indent(out) <<
1127  "if ftype == TType.STOP:" << endl;
1128  indent_up();
1129  indent(out) <<
1130  "break" << endl;
1131  indent_down();
1132 
1133  // Switch statement on the field we are reading
1134  bool first = true;
1135 
1136  // Generate deserialization code for known cases
1137  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1138  if (first) {
1139  first = false;
1140  out <<
1141  indent() << "if ";
1142  } else {
1143  out <<
1144  indent() << "elif ";
1145  }
1146  out << "fid == " << (*f_iter)->get_key() << ":" << endl;
1147  indent_up();
1148  indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << ":" << endl;
1149  indent_up();
1150  generate_deserialize_field(out, *f_iter, "self.");
1151  indent_down();
1152  out <<
1153  indent() << "else:" << endl <<
1154  indent() << " iprot.skip(ftype)" << endl;
1155  indent_down();
1156  }
1157 
1158  // In the default case we skip the field
1159  out <<
1160  indent() << "else:" << endl <<
1161  indent() << " iprot.skip(ftype)" << endl;
1162 
1163  // Read field end marker
1164 #ifdef SANDESH
1165  indent(out) <<
1166  "length = iprot.readFieldEnd()" << endl;
1167  indent(out) <<
1168  "if length < 0: return -1" << endl;
1169  indent(out) <<
1170  "read_cnt += length" << endl;
1171 #else
1172  indent(out) <<
1173  "iprot.readFieldEnd()" << endl;
1174 #endif
1175 
1176  indent_down();
1177 
1178 #ifdef SANDESH
1179  indent(out) <<
1180  "length = iprot.readStructEnd()" << endl;
1181  indent(out) <<
1182  "if length < 0: return -1" << endl;
1183  indent(out) <<
1184  "read_cnt += length" << endl;
1185 #else
1186  indent(out) <<
1187  "iprot.readStructEnd()" << endl;
1188 #endif
1189 
1190 #ifdef SANDESH
1191  indent(out) <<
1192  "return read_cnt" << endl;
1193 #endif
1194 
1195  indent_down();
1196  out << endl;
1197 }
1198 
1200  t_struct* tstruct) {
1201  string name = tstruct->get_name();
1202  const vector<t_field*>& fields = tstruct->get_sorted_members();
1203  vector<t_field*>::const_iterator f_iter;
1204 
1205  indent(out) <<
1206  "def write(self, oprot):" << endl;
1207  indent_up();
1208 
1209  indent(out) <<
1210  "if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated "
1211  "and self.thrift_spec is not None "
1212  "and fastbinary is not None:" << endl;
1213  indent_up();
1214 
1215  indent(out) <<
1216  "oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))" << endl;
1217 #ifdef SANDESH
1218  indent(out) <<
1219  "return 0" << endl;
1220 #else
1221  indent(out) <<
1222  "return" << endl;
1223 #endif
1224  indent_down();
1225 
1226 #ifdef SANDESH
1227  indent(out) <<
1228  "if oprot.writeStructBegin(self.__class__.__name__) < 0: return -1" << endl;
1229 #else
1230  indent(out) <<
1231  "oprot.writeStructBegin('" << name << "')" << endl;
1232 #endif
1233 
1234  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1235  // Write field header
1236 #ifdef SANDESH
1237  indent(out) <<
1238  "if self." << (*f_iter)->get_name() << " is not None:" << endl;
1239  indent_up();
1240  indent(out) <<
1241  "annotations = {}" << endl;
1242  if (!((*f_iter)->annotations_.empty())) {
1243  std::map<std::string, std::string>::iterator it;
1244  for (it = (*f_iter)->annotations_.begin(); it != (*f_iter)->annotations_.end(); it++) {
1245  if (((*f_iter)->get_name() == "name") && (it->first == "key")) {
1246  indent(out) << "if self._table is None or self._table is '': return -1" << endl;
1247  indent(out) << "annotations['key'] = " << "self._table" << endl;
1248  } else {
1249  indent(out) << "annotations['" << (*it).first << "'] = '" <<
1250  (*it).second << "'" << endl;
1251  }
1252  }
1253  }
1254  indent(out) <<
1255  "if oprot.writeFieldBegin(" <<
1256  "'" << (*f_iter)->get_name() << "', " <<
1257  type_to_enum((*f_iter)->get_type()) << ", " <<
1258  (*f_iter)->get_key() << ", annotations) < 0: return -1" << endl;
1259 #else
1260  indent(out) <<
1261  "if self." << (*f_iter)->get_name() << " is not None:" << endl;
1262  indent_up();
1263  indent(out) <<
1264  "oprot.writeFieldBegin(" <<
1265  "'" << (*f_iter)->get_name() << "', " <<
1266  type_to_enum((*f_iter)->get_type()) << ", " <<
1267  (*f_iter)->get_key() << ")" << endl;
1268 #endif
1269 
1270  // Write field contents
1271  generate_serialize_field(out, *f_iter, "self.");
1272 
1273  // Write field closer
1274 #ifdef SANDESH
1275  indent(out) <<
1276  "if oprot.writeFieldEnd() < 0: return -1" << endl;
1277 #else
1278  indent(out) <<
1279  "oprot.writeFieldEnd()" << endl;
1280 #endif
1281  indent_down();
1282  }
1283 
1284  // Write the struct map
1285 #ifdef SANDESH
1286  out <<
1287  indent() << "if oprot.writeFieldStop() < 0: return -1" << endl <<
1288  indent() << "if oprot.writeStructEnd() < 0: return -1" << endl <<
1289  indent() << "return 0" << endl;
1290 #else
1291  out <<
1292  indent() << "oprot.writeFieldStop()" << endl <<
1293  indent() << "oprot.writeStructEnd()" << endl;
1294 #endif
1295  out << endl;
1296  indent_down();
1298  out <<
1299  endl;
1300 }
1301 
1303  t_struct* tstruct) {
1304  indent(out) << "def validate(self):" << endl;
1305  indent_up();
1306 
1307  const vector<t_field*>& fields = tstruct->get_members();
1308 
1309  if (fields.size() > 0) {
1310  vector<t_field*>::const_iterator f_iter;
1311 
1312  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1313  t_field* field = (*f_iter);
1314  if (field->get_req() == t_field::T_REQUIRED) {
1315  indent(out) << "if self." << field->get_name() << " is None:" << endl;
1316  indent(out) << " raise TProtocol.TProtocolException(message='Required field " <<
1317  field->get_name() << " is unset!')" << endl;
1318  }
1319  }
1320  }
1321 
1322  indent(out) << "return" << endl << endl;
1323  indent_down();
1324 }
1325 
1326 #ifdef SANDESH
1327 void t_py_generator::generate_py_sandesh(t_sandesh *tsandesh) {
1328  generate_py_sandesh_definition(f_types_, tsandesh);
1329 }
1330 
1331 void t_py_generator::generate_py_sandesh_definition(ofstream& out,
1332  t_sandesh* tsandesh) {
1333  const vector<t_field*>& members = tsandesh->get_members();
1334  const vector<t_field*>& sorted_members = tsandesh->get_sorted_members();
1335  vector<t_field*>::const_iterator m_iter;
1336  const t_base_type *sandesh_type = (t_base_type *)tsandesh->get_type();
1337 
1338  std::string base_class;
1339  if (sandesh_type->is_sandesh_system()) {
1340  base_class = "sandesh_base.SandeshSystem";
1341  } else if (sandesh_type->is_sandesh_object()) {
1342  base_class = "sandesh_base.SandeshObject";
1343  } else if (sandesh_type->is_sandesh_flow()) {
1344  if (sandesh_type->is_sandesh_session()) {
1345  base_class = "sandesh_base.SandeshFlowSession";
1346  } else {
1347  base_class = "sandesh_base.SandeshFlow";
1348  }
1349  } else if (sandesh_type->is_sandesh_request()) {
1350  base_class = "sandesh_base.SandeshRequest";
1351  } else if (sandesh_type->is_sandesh_response()) {
1352  base_class = "sandesh_base.SandeshResponse";
1353  } else if (sandesh_type->is_sandesh_uve()) {
1354  base_class = "sandesh_base.SandeshUVE";
1355  } else if (sandesh_type->is_sandesh_dynamic_uve()) {
1356  base_class = "sandesh_base.SandeshDynamicUVE";
1357  } else if (sandesh_type->is_sandesh_alarm()) {
1358  base_class = "sandesh_base.SandeshAlarm";
1359  } else if (sandesh_type->is_sandesh_trace() ||
1360  sandesh_type->is_sandesh_trace_object()) {
1361  base_class = "sandesh_base.SandeshTrace";
1362  } else {
1363  throw "compiler error: unsupported sandesh type " +
1364  t_base_type::t_base_name(sandesh_type->get_base());
1365  }
1366 
1367  out << std::endl <<
1368  "class " << tsandesh->get_name();
1369  out << "(" << base_class << "):" << endl;
1370  indent_up();
1371  // generate_python_docstring(out, tstruct);
1372 
1373  out << endl;
1374 
1375  /*
1376  Here we generate the structure specification for the fastbinary codec.
1377  These specifications have the following structure:
1378  thrift_spec -> tuple of item_spec
1379  item_spec -> None | (tag, type_enum, name, spec_args, default)
1380  tag -> integer
1381  type_enum -> TType.I32 | TType.STRING | TType.STRUCT | ...
1382  name -> string_literal
1383  default -> None # Handled by __init__
1384  spec_args -> None # For simple types
1385  | (type_enum, spec_args) # Value type for list/set
1386  | (type_enum, spec_args, type_enum, spec_args)
1387  # Key and value for map
1388  | (class_name, spec_args_ptr) # For struct/exception
1389  class_name -> identifier # Basically a pointer to the class
1390  spec_args_ptr -> expression # just class_name.spec_args
1391 
1392  TODO(dreiss): Consider making this work for structs with negative tags.
1393  */
1394 
1395  if (gen_slots_) {
1396  indent(out) << "__slots__ = [ " << endl;
1397  indent_up();
1398  for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
1399  indent(out) << "'" << (*m_iter)->get_name() << "'," << endl;
1400  }
1401  indent_down();
1402  indent(out) << " ]" << endl << endl;
1403 
1404  }
1405 
1406  // TODO(dreiss): Look into generating an empty tuple instead of None
1407  // for class with no members.
1408  // TODO(dreiss): Test encoding of class where some inner class
1409  // don't have thrift_spec.
1410  if (sorted_members.empty() || (sorted_members[0]->get_key() >= 0)) {
1411  indent(out) << "thrift_spec = (" << endl;
1412  indent_up();
1413 
1414  int sorted_keys_pos = 0;
1415  for (m_iter = sorted_members.begin(); m_iter != sorted_members.end(); ++m_iter) {
1416 
1417  for (; sorted_keys_pos != (*m_iter)->get_key(); sorted_keys_pos++) {
1418  indent(out) << "None, # " << sorted_keys_pos << endl;
1419  }
1420 
1421  indent(out) << "(" << (*m_iter)->get_key() << ", "
1422  << type_to_enum((*m_iter)->get_type()) << ", "
1423  << "'" << (*m_iter)->get_name() << "'" << ", "
1424  << type_to_spec_args((*m_iter)->get_type()) << ", "
1425  << render_field_default_value(*m_iter) << ", "
1426  << "),"
1427  << " # " << sorted_keys_pos
1428  << endl;
1429 
1430  sorted_keys_pos ++;
1431  }
1432 
1433  indent_down();
1434  indent(out) << ")" << endl << endl;
1435  } else {
1436  indent(out) << "thrift_spec = None" << endl << endl;
1437  }
1438 
1439  if (sandesh_type->is_sandesh_system()) {
1440  indent(out) << "rate_limit_buffer = util.deque(maxlen=sandesh_base."
1441  "SandeshSystem._DEFAULT_SEND_RATELIMIT)" << endl << endl;
1442  indent(out) << "do_rate_limit_drop_log = True" << endl << endl;
1443  }
1444 
1445  {
1446  out <<
1447  indent() << "def __init__(self";
1448 
1449  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1450  // skip const string
1451  t_type* type = get_true_type((*m_iter)->get_type());
1452  if (type->is_static_const_string()) {
1453  continue;
1454  }
1455  // This fills in default values, as opposed to nulls
1456  out << ", " << declare_argument(*m_iter);
1457  }
1458 
1459  if (sandesh_type->is_sandesh_system() ||
1460  sandesh_type->is_sandesh_object() ||
1461  sandesh_type->is_sandesh_flow()) {
1462  out << ", category='" << "__default__" <<
1463  "', level=SandeshLevel.SYS_INFO";
1464  }
1465  if (sandesh_type->is_sandesh_uve() ||
1466  sandesh_type->is_sandesh_dynamic_uve() ||
1467  sandesh_type->is_sandesh_alarm()) {
1468  out << ", table=None";
1469  }
1470  out << ", sandesh=sandesh_base.sandesh_global):" << endl;
1471 
1472  indent_up();
1473  if (sandesh_type->is_sandesh_trace()) {
1474  indent(out) << base_class <<
1475  ".__init__(self, type=SandeshType.TRACE)" << endl;
1476  } else if (sandesh_type->is_sandesh_trace_object()) {
1477  indent(out) << base_class <<
1478  ".__init__(self, type=SandeshType.TRACE_OBJECT)" << endl;
1479  } else {
1480  indent(out) << base_class << ".__init__(self)" << endl;
1481  }
1482 
1483  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
1484  // Initialize fields
1485  t_type* type = (*m_iter)->get_type();
1486  if (!type->is_base_type() && !type->is_enum() && (*m_iter)->get_value() != NULL) {
1487  indent(out) <<
1488  "if " << (*m_iter)->get_name() << " is " << "self.thrift_spec[" <<
1489  (*m_iter)->get_key() << "][4]:" << endl;
1490  indent(out) << " " << (*m_iter)->get_name() << " = " <<
1491  render_field_default_value(*m_iter) << endl;
1492  } else if (type->is_static_const_string()) {
1493  indent(out) <<
1494  "self." << (*m_iter)->get_name() << " = " <<
1495  render_const_value(type, (*m_iter)->get_value()) << endl;
1496  } else {
1497  indent(out) <<
1498  "self." << (*m_iter)->get_name() << " = " << (*m_iter)->get_name() << endl;
1499  }
1500  }
1501 
1502  indent(out) << "self._scope = sandesh.scope()" << endl;
1503  indent(out) << "self._module = sandesh.module()" << endl;
1504  indent(out) << "self._source = sandesh.source_id()" << endl;
1505  indent(out) << "self._node_type = sandesh.node_type()" << endl;
1506  indent(out) << "self._instance_id = sandesh.instance_id()" << endl;
1507  indent(out) << "self._seqnum = 0" << endl;
1508  indent(out) << "self._timestamp = UTCTimestampUsec()" << endl;
1509  indent(out) << "self._versionsig = " << tsandesh->get_4byte_fingerprint() << endl;
1510  generate_py_sandesh_hint(out, tsandesh);
1511  if (sandesh_type->is_sandesh_system() ||
1512  sandesh_type->is_sandesh_object() ||
1513  sandesh_type->is_sandesh_flow()) {
1514  indent(out) << "self._category = category" << endl;
1515  indent(out) << "self._level = level" << endl;
1516  }
1517  if (sandesh_type->is_sandesh_uve() ||
1518  sandesh_type->is_sandesh_dynamic_uve() ||
1519  sandesh_type->is_sandesh_alarm()) {
1520  indent(out) << "if table is not None:" << endl;
1521  indent_up();
1522  indent(out) << "self.data._table = table" << endl;
1523  indent_down();
1524  }
1525  indent_down();
1526 
1527  out << endl;
1528  }
1529 
1530  if (sandesh_type->is_sandesh_system() ||
1531  sandesh_type->is_sandesh_object() ||
1532  sandesh_type->is_sandesh_flow()) {
1533  generate_py_sandesh_async(out, tsandesh);
1534  } else if (sandesh_type->is_sandesh_request()) {
1535  generate_py_sandesh_request(out, tsandesh);
1536  } else if (sandesh_type->is_sandesh_response()) {
1537  generate_py_sandesh_response(out, tsandesh);
1538  } else if (sandesh_type->is_sandesh_uve() ||
1539  sandesh_type->is_sandesh_alarm()) {
1540  generate_py_sandesh_uve(out, tsandesh, true);
1541  } else if (sandesh_type->is_sandesh_dynamic_uve()) {
1542  generate_py_sandesh_uve(out, tsandesh, false);
1543  } else if (sandesh_type->is_sandesh_trace() ||
1544  sandesh_type->is_sandesh_trace_object()) {
1545  generate_py_sandesh_trace(out, tsandesh);
1546  }
1547 
1548  generate_py_sandesh_logger(out, tsandesh);
1549 
1550  if (!gen_dynamic_) {
1551  generate_py_sandesh_reader(out, tsandesh);
1552  generate_py_sandesh_writer(out, tsandesh);
1553  }
1554 
1555  generate_py_sandesh_compare(out, tsandesh);
1556  generate_py_sandesh_sizeof(out, tsandesh);
1557 
1558  if (!gen_slots_) {
1559  // Printing utilities so that on the command line thrift
1560  // structs look pretty like dictionaries
1561  out <<
1562  indent() << "def __repr__(self):" << endl <<
1563  indent() << " L = ['%s=%r' % (key, value)" << endl <<
1564  indent() << " for key, value in self.__dict__.items()]" << endl <<
1565  indent() << " return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl <<
1566  endl;
1567 
1568  // Equality and inequality methods that compare by value
1569  out <<
1570  indent() << "def __eq__(self, other):" << endl;
1571  indent_up();
1572  out <<
1573  indent() << "return isinstance(other, self.__class__) and "
1574  "self.__dict__ == other.__dict__" << endl;
1575  indent_down();
1576  out << endl;
1577 
1578  out <<
1579  indent() << "def __ne__(self, other):" << endl;
1580  indent_up();
1581 
1582  out <<
1583  indent() << "return not (self == other)" << endl;
1584  indent_down();
1585  } else if (!gen_dynamic_) {
1586  // no base class available to implement __eq__ and __repr__ and __ne__ for us
1587  // so we must provide one that uses __slots__
1588  out <<
1589  indent() << "def __repr__(self):" << endl <<
1590  indent() << " L = ['%s=%r' % (key, getattr(self, key))" << endl <<
1591  indent() << " for key in self.__slots__]" << endl <<
1592  indent() << " return '%s(%s)' % (self.__class__.__name__, ', '.join(L))" << endl <<
1593  endl;
1594 
1595  // Equality method that compares each attribute by value and type, walking __slots__
1596  out <<
1597  indent() << "def __eq__(self, other):" << endl <<
1598  indent() << " if not isinstance(other, self.__class__):" << endl <<
1599  indent() << " return False" << endl <<
1600  indent() << " for attr in self.__slots__:" << endl <<
1601  indent() << " my_val = getattr(self, attr)" << endl <<
1602  indent() << " other_val = getattr(other, attr)" << endl <<
1603  indent() << " if my_val != other_val:" << endl <<
1604  indent() << " return False" << endl <<
1605  indent() << " return True" << endl <<
1606  endl;
1607 
1608  out <<
1609  indent() << "def __ne__(self, other):" << endl <<
1610  indent() << " return not (self == other)" << endl <<
1611  endl;
1612  }
1613  indent_down();
1614 }
1615 
1619 void t_py_generator::generate_py_sandesh_reader(ofstream& out,
1620  t_sandesh* tsandesh) {
1621  const vector<t_field*>& fields = tsandesh->get_members();
1622  vector<t_field*>::const_iterator f_iter;
1623 
1624  indent(out) <<
1625  "def read(self, iprot):" << endl;
1626  indent_up();
1627 
1628  indent(out) <<
1629  "if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated "
1630  "and isinstance(iprot.trans, TTransport.CReadableTransport) "
1631  "and self.thrift_spec is not None "
1632  "and fastbinary is not None:" << endl;
1633  indent_up();
1634 
1635  indent(out) <<
1636  "fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec))" << endl;
1637  indent(out) <<
1638  "return -1" << endl;
1639  indent_down();
1640 
1641  indent(out) <<
1642  "read_cnt = 0" << endl;
1643 
1644  indent(out) <<
1645  "(length, sandesh_name) = iprot.readSandeshBegin()" << endl;
1646  indent(out) <<
1647  "if length < 0: return -1" << endl;
1648  indent(out) <<
1649  "read_cnt += length" << endl;
1650 
1651  // Loop over reading in fields
1652  indent(out) <<
1653  "while True:" << endl;
1654  indent_up();
1655 
1656  // Read beginning field marker
1657  indent(out) <<
1658  "(length, fname, ftype, fid) = iprot.readFieldBegin()" << endl;
1659  indent(out) <<
1660  "if length < 0: return -1" << endl;
1661  indent(out) <<
1662  "read_cnt += length" << endl;
1663 
1664  // Check for field STOP marker and break
1665  indent(out) <<
1666  "if ftype == TType.STOP:" << endl;
1667  indent_up();
1668  indent(out) <<
1669  "break" << endl;
1670  indent_down();
1671 
1672  // Switch statement on the field we are reading
1673  bool first = true;
1674 
1675  // Generate deserialization code for known cases
1676  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1677  if (first) {
1678  first = false;
1679  out <<
1680  indent() << "if ";
1681  } else {
1682  out <<
1683  indent() << "elif ";
1684  }
1685  out << "fid == " << (*f_iter)->get_key() << ":" << endl;
1686  indent_up();
1687  indent(out) << "if ftype == " << type_to_enum((*f_iter)->get_type()) << ":" << endl;
1688  indent_up();
1689  generate_deserialize_field(out, *f_iter, "self.");
1690  indent_down();
1691  out <<
1692  indent() << "else:" << endl <<
1693  indent() << " iprot.skip(ftype)" << endl;
1694  indent_down();
1695  }
1696 
1697  // In the default case we skip the field
1698  out <<
1699  indent() << "else:" << endl <<
1700  indent() << " iprot.skip(ftype)" << endl;
1701 
1702  // Read field end marker
1703  indent(out) <<
1704  "length = iprot.readFieldEnd()" << endl;
1705  indent(out) <<
1706  "if length < 0: return -1" << endl;
1707  indent(out) <<
1708  "read_cnt += length" << endl;
1709 
1710  indent_down();
1711 
1712  indent(out) <<
1713  "length = iprot.readSandeshEnd()" << endl;
1714  indent(out) <<
1715  "if length < 0: return -1" << endl;
1716  indent(out) <<
1717  "read_cnt += length" << endl;
1718 
1719  indent(out) <<
1720  "return read_cnt" << endl;
1721 
1722  indent_down();
1723  out << endl;
1724 }
1725 
1726 void t_py_generator::generate_py_sandesh_writer(ofstream& out,
1727  t_sandesh* tsandesh) {
1728  const vector<t_field*>& fields = tsandesh->get_sorted_members();
1729  vector<t_field*>::const_iterator f_iter;
1730 
1731  indent(out) <<
1732  "def write(self, oprot):" << endl;
1733  indent_up();
1734 
1735  indent(out) <<
1736  "if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated "
1737  "and self.thrift_spec is not None "
1738  "and fastbinary is not None:" << endl;
1739  indent_up();
1740 
1741  indent(out) <<
1742  "oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec)))" << endl;
1743  indent(out) <<
1744  "return 0" << endl;
1745  indent_down();
1746 
1747  indent(out) <<
1748  "if oprot.writeSandeshBegin(self.__class__.__name__) < 0: return -1" << endl;
1749  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1750  // Write field header
1751  indent(out) <<
1752  "if self." << (*f_iter)->get_name() << " is not None:" << endl;
1753  indent_up();
1754  indent(out) <<
1755  "annotations = {}" << endl;
1756  if (!((*f_iter)->annotations_.empty())) {
1757  std::map<std::string, std::string>::iterator it;
1758  for (it = (*f_iter)->annotations_.begin(); it != (*f_iter)->annotations_.end(); it++) {
1759  indent(out) << "annotations['" << (*it).first << "'] = '" <<
1760  (*it).second << "'" << endl;
1761  }
1762  }
1763  indent(out) <<
1764  "if oprot.writeFieldBegin(" <<
1765  "'" << (*f_iter)->get_name() << "', " <<
1766  type_to_enum((*f_iter)->get_type()) << ", " <<
1767  (*f_iter)->get_key() << ", annotations) < 0: return -1" << endl;
1768 
1769  // Write field contents
1770  generate_serialize_field(out, *f_iter, "self.");
1771 
1772  // Write field closer
1773  indent(out) <<
1774  "if oprot.writeFieldEnd() < 0: return -1" << endl;
1775 
1776  indent_down();
1777  }
1778 
1779  // Write the struct map
1780  indent(out) <<
1781  "if oprot.writeFieldStop() < 0: return -1" << endl;
1782  indent(out) <<
1783  "if oprot.writeSandeshEnd() < 0: return -1" << endl;
1784  indent(out) <<
1785  "return 0" << endl;
1786  out << endl;
1787  indent_down();
1788  generate_py_sandesh_required_validator(out, tsandesh);
1789  out <<
1790  endl;
1791 }
1792 
1793 void t_py_generator::generate_py_sandesh_required_validator(ofstream& out,
1794  t_sandesh* tsandesh) {
1795  indent(out) << "def validate(self):" << endl;
1796  indent_up();
1797 
1798  const vector<t_field*>& fields = tsandesh->get_members();
1799 
1800  if (fields.size() > 0) {
1801  vector<t_field*>::const_iterator f_iter;
1802 
1803  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1804  t_field* field = (*f_iter);
1805  if (field->get_req() == t_field::T_REQUIRED) {
1806  indent(out) << "if self." << field->get_name() << " is None:" << endl;
1807  indent(out) << " raise TProtocol.TProtocolException(message='Required field " <<
1808  field->get_name() << " is unset!')" << endl;
1809  }
1810  }
1811  }
1812 
1813  indent(out) << "return" << endl << endl;
1814  indent_down();
1815 }
1816 
1817 void t_py_generator::generate_py_sandesh_compare(ofstream& out,
1818  t_sandesh* tsandesh) {
1819  const vector<t_field*>& fields = tsandesh->get_sorted_members();
1820  vector<t_field*>::const_iterator f_iter;
1821 
1822  indent(out) <<
1823  "def compare(self, other):" << endl;
1824  indent_up();
1825  indent(out) <<
1826  "if not isinstance(other, self.__class__):" << endl;
1827  indent_up();
1828  indent(out) <<
1829  "return False" << endl;
1830  indent_down();
1831 
1832  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1833  indent(out) <<
1834  "if self." << (*f_iter)->get_name() << " != " <<
1835  "other." << (*f_iter)->get_name() << ":" << endl;
1836  indent_up();
1837  indent(out) << "return False" << endl;
1838  indent_down();
1839  }
1840 
1841  indent(out) << "return True" << endl << endl;
1842  indent_down();
1843 }
1844 
1845 void t_py_generator::generate_py_sandesh_http_attr(ofstream& out,
1846  t_type *ftype, const std::string& namel, const std::string& namer) {
1847 
1848  if (ftype->is_base_type()) {
1849 
1850  t_base_type::t_base bftype = ((t_base_type *)ftype)->get_base();
1851 
1852  indent(out) <<
1853  "if bottle.request.query." << namer << ":" << endl;
1854  indent_up();
1855  if (bftype == t_base_type::TYPE_STRING) {
1856  indent(out) <<
1857  "sandesh_req." << namel << " = str(" <<
1858  "bottle.request.query." << namer << ")" << endl;
1859  } else if (bftype == t_base_type::TYPE_UUID) {
1860  indent(out) << "try:" << endl;
1861  indent_up();
1862  indent(out) << "sandesh_req." << namel << " = uuid.UUID("
1863  << "bottle.request.query." << namer << ")" << endl;
1864  indent_down();
1865  indent(out) << "except ValueError:" << endl;
1866  indent_up();
1867  indent(out) << "return SandeshHttp.http_error('Invalid value for "
1868  << namel << ":" << namer << "')" << endl;
1869  indent_down();
1870  } else if (bftype == t_base_type::TYPE_IPADDR) {
1871  indent(out) << "try:" << endl;
1872  indent_up();
1873  indent(out) << "sandesh_req." << namel << " = netaddr.IPAddress("
1874  << "bottle.request.query." << namer << ")" << endl;
1875  indent_down();
1876  indent(out) << "except ValueError:" << endl;
1877  indent_up();
1878  indent(out) << "return SandeshHttp.http_error('Invalid value for "
1879  << namel << ":" << namer << "')" << endl;
1880  indent_down();
1881  } else {
1882  assert(bftype == t_base_type::TYPE_BOOL ||
1883  bftype == t_base_type::TYPE_BYTE ||
1884  bftype == t_base_type::TYPE_I16 ||
1885  bftype == t_base_type::TYPE_I32 ||
1886  bftype == t_base_type::TYPE_I64 ||
1887  bftype == t_base_type::TYPE_U16 ||
1888  bftype == t_base_type::TYPE_U32 ||
1889  bftype == t_base_type::TYPE_U64 ||
1890  bftype == t_base_type::TYPE_IPV4);
1891  indent(out) <<
1892  "try:" << endl;
1893  indent_up();
1894  indent(out) <<
1895  "sandesh_req." << namel << " = int(" <<
1896  "bottle.request.query." << namer << ")" << endl;
1897  indent_down();
1898  indent(out) <<
1899  "except ValueError:" << endl;
1900  indent_up();
1901  indent(out) <<
1902  "return SandeshHttp.http_error('Invalid data provided in Sandesh Request')" << endl;
1903  indent_down();
1904  }
1905  indent_down();
1906 
1907  } else {
1908  // Ignore this field for now
1909  }
1910 }
1911 
1912 void t_py_generator::generate_py_sandesh_http_request_handler(ofstream& out,
1913  t_sandesh* tsandesh) {
1914  const vector<t_field*>& fields = tsandesh->get_sorted_members();
1915  vector<t_field*>::const_iterator f_iter;
1916 
1917  indent(out) <<
1918  "@staticmethod" << endl;
1919  indent(out) <<
1920  "def handle_http_request(sandesh=sandesh_base.sandesh_global):" << endl;
1921  indent_up();
1922  indent(out) <<
1923  "sandesh_req = " << tsandesh->get_name() << "()" << endl;
1924  indent(out) <<
1925  "if not sandesh_req:" << endl;
1926  indent_up();
1927  indent(out) << "return SandeshHttp.http_error('Sandesh Request \"" << tsandesh->get_name() <<
1928  "\" not implemented')" << endl;
1929  indent_down();
1930  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
1931  t_type *ftype = (*f_iter)->get_type();
1932  if (f_iter == fields.begin()) {
1933  generate_py_sandesh_http_attr(out, ftype, (*f_iter)->get_name(), "x");
1934  }
1935  generate_py_sandesh_http_attr(out, ftype, (*f_iter)->get_name(), (*f_iter)->get_name());
1936  }
1937  // TODO: Call validate() to check if all the mandatory parameters are provided
1938  indent(out) << "sandesh_req._context = bottle.request.url" << endl;
1939  indent(out) << "handle_req_fn = getattr(sandesh_req, \"handle_request\", None)" << endl;
1940  indent(out) << "if callable(handle_req_fn):" << endl;
1941  indent_up();
1942  indent(out) << "handle_req_fn(sandesh_req)" << endl;
1943  indent_down();
1944  indent(out) << "else:" << endl;
1945  indent_up();
1946  indent(out) << "return SandeshHttp.http_error('Sandesh Request \"" << tsandesh->get_name() <<
1947  "\" not implemented')" << endl;
1948  indent_down();
1949  indent(out) << "resp = SandeshHttp.get_http_response()" << endl;
1950  indent(out) << "if resp:" << endl;
1951  indent_up();
1952  indent(out) << "return resp" << endl;
1953  indent_down();
1954  indent(out) << "else:" << endl;
1955  indent_up();
1956  indent(out) << "return SandeshHttp.http_error('No Response for Sandesh Request \"" <<
1957  tsandesh->get_name() << "\"')" << endl;
1958  indent_down();
1959  indent(out) << endl;
1960  indent_down();
1961  indent_down();
1962 }
1963 
1964 void t_py_generator::generate_py_sandesh_request_list(ofstream& out) {
1965  out << endl << endl;
1966  out << "_SANDESH_REQUEST_LIST = [" << endl;
1967  std::vector<std::string>::const_iterator it;
1968  for (it = sandesh_req_list_.begin(); it != sandesh_req_list_.end(); ++it) {
1969  indent(out) << *it << "," << endl;
1970  }
1971  out << "]" << endl;
1972 }
1973 
1974 void t_py_generator::generate_py_sandesh_http_request_list(ofstream& out,
1975  t_sandesh* tsandesh) {
1976  indent(out) <<
1977  "{ 'uri':" << "'/Snh_" << tsandesh->get_name() << "'" <<
1978  ", 'method':" << "ttypes." << tsandesh->get_name() << ".handle_http_request " <<
1979  "}," << endl;
1980 }
1981 
1982 void t_py_generator::py_autogen_sandesh_http_request_open(ofstream& out) {
1983  indent(out) << endl;
1984  indent(out) <<
1985  "_HTTP_REQUEST_LIST = [" << endl;
1986 }
1987 
1988 void t_py_generator::py_autogen_sandesh_http_request_close(ofstream& out) {
1989  out << "]" << endl << endl;
1990 }
1991 
1992 std::string t_py_generator::py_autogen_sandesh_request_skeleton_comment() {
1993  return
1994  std::string("\n") +
1995  "# This autogenerated skeleton file illustrates the implementation of" +
1996  "\n" +
1997  "# derived class to handle the sandesh request." +
1998  "\n";
1999 }
2000 
2001 void t_py_generator::generate_py_sandesh_skeleton_request(ofstream& out,
2002  t_sandesh* tsandesh) {
2003  const vector<t_field*>& members = tsandesh->get_members();
2004  vector<t_field*>::const_iterator m_iter;
2005 
2006  out << endl <<
2007  "# Create a derived class from \"" << tsandesh->get_name() << "\" to handle ";
2008  out << endl <<
2009  "# the sandesh request. Add this derived class \"" << tsandesh->get_name() << "_derived\"";
2010  out << endl <<
2011  "# in module " << tsandesh->get_name() << "_derived.py and " <<
2012  "add it in your package" << endl;
2013 
2014  out << endl <<
2015  "class " << tsandesh->get_name() << "_derived";
2016  out << "(" << tsandesh->get_name() << "):" << endl;
2017  indent_up();
2018  out << endl;
2019 
2020  if (members.size() > 0) {
2021  out <<
2022  indent() << "def __init__(self):" << endl;
2023  indent_up();
2024  out <<
2025  indent() << tsandesh->get_name() << ".__init__(self";
2026 
2027  for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
2028  // skip const string
2029  t_type* type = get_true_type((*m_iter)->get_type());
2030  if (type->is_static_const_string()) {
2031  continue;
2032  }
2033  // This fills in default values, as opposed to nulls
2034  out << ", " << declare_argument(*m_iter);
2035  }
2036  out << ")" << endl;
2037  indent_down();
2038  }
2039  out << endl;
2040  out << indent() << "def handle_request(self):" << endl;
2041  indent_up();
2042  indent(out) <<
2043  "# Add your code to handle the \"" << tsandesh->get_name() <<
2044  "\" request" << endl;
2045  indent(out) <<
2046  "pass" << endl;
2047  indent_down();
2048  indent(out) << endl;
2049 }
2050 
2051 void t_py_generator::generate_struct_log(ofstream& out,
2052  string prefix,
2053  string log_str) {
2054  indent(out) <<
2055  log_str << ".write('<< ')" << endl;
2056  indent(out) <<
2057  log_str << ".write(" << prefix << ".log())" << endl;
2058  indent(out) <<
2059  log_str << ".write('>>')" << endl;
2060 }
2061 
2062 void t_py_generator::generate_container_log(ofstream& out,
2063  string prefix,
2064  t_type* ttype,
2065  string log_str) {
2066  if (ttype->is_map()) {
2067  string kiter = tmp("kiter");
2068  string viter = tmp("viter");
2069  indent(out) <<
2070  log_str << ".write('{ ')" << endl;
2071  indent(out) <<
2072  "for " << kiter << "," << viter << " in " << prefix << ".items():" << endl;
2073  indent_up();
2074  t_field kfield(((t_map*)ttype)->get_key_type(), kiter);
2075  generate_field_log(out, &kfield, log_str, "");
2076  indent(out) <<
2077  log_str << ".write(' : ')" << endl;
2078  t_field vfield(((t_map*)ttype)->get_val_type(), viter);
2079  generate_field_log(out, &vfield, log_str, "");
2080  indent_down();
2081  indent(out) <<
2082  log_str << ".write(' }')" << endl;
2083  } else if (ttype->is_set()) {
2084  string iter = tmp("iter");
2085  indent(out) <<
2086  log_str << ".write('( ')" << endl;
2087  indent(out) <<
2088  "for " << iter << " in " << prefix << ":" << endl;
2089  indent_up();
2090  t_field efield(((t_set*)ttype)->get_elem_type(), iter);
2091  generate_field_log(out, &efield, log_str, "");
2092  indent(out) <<
2093  log_str << ".write(', ')" << endl;
2094  indent_down();
2095  indent(out) <<
2096  log_str << ".write(' )')" << endl;
2097  } else if (ttype->is_list()) {
2098  string iter = tmp("iter");
2099  indent(out) <<
2100  log_str << ".write('[ ')" << endl;
2101  indent(out) <<
2102  "for " << iter << " in " << prefix << ":" << endl;
2103  indent_up();
2104  t_field efield(((t_list*)ttype)->get_elem_type(), iter);
2105  generate_field_log(out, &efield, log_str, "");
2106  indent(out) <<
2107  log_str << ".write(', ')" << endl;
2108  indent_down();
2109  indent(out) <<
2110  log_str << ".write(' ]')" << endl;
2111  }
2112 }
2113 
2114 void t_py_generator::generate_field_log(ofstream& out,
2115  t_field *tfield,
2116  string log_str,
2117  string prefix) {
2118  t_type* type = get_true_type(tfield->get_type());
2119 
2120  if (type->is_struct() || type->is_xception()) {
2121  generate_struct_log(out, prefix + tfield->get_name(), log_str);
2122  } else if (type->is_container()) {
2123  generate_container_log(out, prefix + tfield->get_name(), type, log_str);
2124  } else if (type->is_base_type() || type->is_enum()) {
2125  string name = prefix + tfield->get_name();
2126  if (type->is_base_type()) {
2127  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2128  switch (tbase) {
2130  break;
2132  case t_base_type::TYPE_STATIC_CONST_STRING:
2133  case t_base_type::TYPE_XML:
2134  indent(out) <<
2135  log_str << ".write(" << name << ")" << endl;
2136  break;
2138  indent(out) <<
2139  "if " << name << ":" << endl;
2140  indent_up();
2141  indent(out) <<
2142  log_str << ".write('True')" << endl;
2143  indent_down();
2144  indent(out) <<
2145  "else:" << endl;
2146  indent_up();
2147  indent(out) <<
2148  log_str << ".write('False')" << endl;
2149  indent_down();
2150  break;
2152  indent(out) <<
2153  log_str << ".write(hex(" << name << "))" << endl;
2154  break;
2155  case t_base_type::TYPE_I16:
2156  indent(out) <<
2157  log_str << ".write(str(" << name << "))" << endl;
2158  break;
2159  case t_base_type::TYPE_I32:
2160  indent(out) <<
2161  log_str << ".write(str(" << name << "))" << endl;
2162  break;
2163  case t_base_type::TYPE_I64:
2164  indent(out) <<
2165  log_str << ".write(str(" << name << "))" << endl;
2166  break;
2167  case t_base_type::TYPE_U16:
2168  indent(out) <<
2169  log_str << ".write(str(" << name << "))" << endl;
2170  break;
2171  case t_base_type::TYPE_U32:
2172  indent(out) <<
2173  log_str << ".write(str(" << name << "))" << endl;
2174  break;
2175  case t_base_type::TYPE_U64:
2176  indent(out) <<
2177  log_str << ".write(str(" << name << "))" << endl;
2178  break;
2180  indent(out) <<
2181  log_str << ".write(str(" << name << "))" << endl;
2182  break;
2183  case t_base_type::TYPE_IPV4:
2184  indent(out) << "import socket, struct" << endl;
2185  indent(out) <<
2186  log_str << ".write(socket.inet_ntoa(struct.pack('!L'," << name << ")))" << endl;
2187  break;
2188  case t_base_type::TYPE_IPADDR:
2189  indent(out) <<
2190  log_str << ".write(str(" << name << "))" << endl;
2191  break;
2192  case t_base_type::TYPE_UUID:
2193  indent(out) <<
2194  log_str << ".write(str(" << name << "))" << endl;
2195  break;
2196  default:
2197  throw "compiler error: unrecognized base type " + t_base_type::t_base_name(tbase);
2198  }
2199  } else if (type->is_enum()) {
2200  indent(out) <<
2201  log_str << ".write(str(" << name << "))" << endl;
2202  }
2203  } else {
2204  printf("DO NOT KNOW HOW TO GENERATE LOG FOR FIELD '%s' TYPE '%s'\n",
2205  tfield->get_name().c_str(),
2206  type->get_name().c_str());
2207  }
2208 }
2209 
2210 void t_py_generator::generate_py_sandesh_logger(ofstream &out,
2211  t_sandesh* tsandesh) {
2212  const vector<t_field*>& fields = tsandesh->get_members();
2213  vector<t_field*>::const_iterator f_iter;
2214  t_base_type *sandesh_type = (t_base_type *)tsandesh->get_type();
2215 
2216  std::string log_str = "log_str";
2217  indent(out) <<
2218  "def log(self, trace=False):" << endl;
2219  indent_up();
2220  indent(out) <<
2221  log_str << " = StringIO()" << endl;
2222  bool init = false;
2223  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2224  if (!init) {
2225  init = true;
2226  indent(out) << "if trace:" << endl;
2227  indent_up();
2228  indent(out) << log_str << ".write(str(self._timestamp))" << endl;
2229  indent(out) << log_str << ".write(' ')" << endl;
2230  indent_down();
2231  // Only systemlog, objectlog, and flowlog have valid level and category
2232  if (sandesh_type->is_sandesh_system() ||
2233  sandesh_type->is_sandesh_object() ||
2234  sandesh_type->is_sandesh_flow()) {
2235  indent(out) <<
2236  "if self._category is not None:" << endl;
2237  indent_up();
2238  indent(out) << log_str << ".write(self._category)" << endl;
2239  indent_down();
2240  indent(out) << log_str << ".write(' [')" << endl;
2241  indent(out) << log_str << ".write(SandeshLevel._VALUES_TO_NAMES["
2242  << "self._level])" << endl;
2243  indent(out) << log_str << ".write(']: ')" << endl;
2244  }
2245  indent(out) << log_str << ".write(self.__class__.__name__ + " <<
2246  "': ')" << endl;
2247  }
2248  indent(out) <<
2249  "if self." << (*f_iter)->get_name() << " is not None:" << endl;
2250  indent_up();
2251  if (sandesh_type->is_sandesh_system() ||
2252  sandesh_type->is_sandesh_trace()) {
2253  generate_field_log(out, *f_iter, log_str, "self.");
2254  indent(out) << log_str << ".write(' ')" << endl;
2255  } else {
2256  indent(out) << log_str <<
2257  ".write('" << (*f_iter)->get_name() << " = ')"<< endl;
2258  generate_field_log(out, *f_iter, log_str, "self.");
2259  indent(out) << log_str << ".write(' ')" << endl;
2260  }
2261  indent_down();
2262  }
2263  indent(out) <<
2264  "return log_str.getvalue()" << endl << endl;
2265  indent_down();
2266 }
2267 
2268 void t_py_generator::generate_py_struct_logger(ofstream &out,
2269  t_struct* tstruct) {
2270  const vector<t_field*>& fields = tstruct->get_members();
2271  vector<t_field*>::const_iterator f_iter;
2272 
2273  std::string log_str = "log_str";
2274  indent(out) <<
2275  "def log(self):" << endl;
2276  indent_up();
2277  indent(out) <<
2278  log_str << " = StringIO()" << endl;
2279 
2280  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2281  indent(out) <<
2282  "if self." << (*f_iter)->get_name() << " is not None:" << endl;
2283  indent_up();
2284  t_type *type = get_true_type((*f_iter)->get_type());
2285  bool write_fname = true;
2286  if (type->is_base_type()) {
2287  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
2288  if (tbase == t_base_type::TYPE_STATIC_CONST_STRING) {
2289  write_fname = false;
2290  }
2291  }
2292  if (write_fname) {
2293  indent(out) <<
2294  log_str << ".write('" << (*f_iter)->get_name() << " = ')"<< endl;
2295  }
2296  generate_field_log(out, *f_iter, log_str, "self.");
2297  indent(out) <<
2298  log_str << ".write(' ')" << endl;
2299  indent_down();
2300  }
2301  indent(out) <<
2302  "return log_str.getvalue()" << endl << endl;
2303  indent_down();
2304 }
2305 
2306 void t_py_generator::generate_py_sizeof(std::ofstream& out,
2307  const vector<t_field*>& fields) {
2308  indent(out) << "def __sizeof__(self):" << endl;
2309  indent_up();
2310  indent(out) << "size = 0" << endl;
2311  vector<t_field*>::const_iterator f_iter;
2312  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2313  std::string fname((*f_iter)->get_name());
2314  indent(out) << "if self." << fname << " is not None:" << endl;
2315  indent_up();
2316  indent(out) << "size += getsizeof(self." << fname << ")" << endl;
2317  t_type* type = get_true_type((*f_iter)->get_type());
2318  if (type->is_container()) {
2319  if (type->is_map()) {
2320  indent(out) <<
2321  "size += sum(map(getsizeof, chain.from_iterable(iter(self." <<
2322  fname << ".items()))))" << endl;
2323 
2324  } else {
2325  indent(out) <<
2326  "size += sum(map(getsizeof, self." << fname << "))" << endl;
2327  }
2328  }
2329  indent_down();
2330  }
2331  indent(out) << "return size" << endl << endl;
2332  indent_down();
2333 }
2334 
2335 void t_py_generator::generate_py_struct_sizeof(std::ofstream& out,
2336  t_struct* tstruct) {
2337  const vector<t_field*>& fields = tstruct->get_members();
2338  generate_py_sizeof(out, fields);
2339 }
2340 
2341 void t_py_generator::generate_py_sandesh_sizeof(std::ofstream& out,
2342  t_sandesh* tsandesh) {
2343  const vector<t_field*>& fields = tsandesh->get_members();
2344  generate_py_sizeof(out, fields);
2345 }
2346 
2347 void t_py_generator::generate_py_sandesh_hint(ofstream& out,
2348  t_sandesh* tsandesh) {
2349  bool has_key_annotation = tsandesh->has_key_annotation();
2350  string shints = "0";
2351 
2352  if (has_key_annotation) {
2353  shints += " | SANDESH_KEY_HINT";
2354  }
2355 
2356  indent(out) << "self._hints = " << shints << endl;
2357 }
2358 
2359 void t_py_generator::generate_py_sandesh_trace(std::ofstream& out,
2360  t_sandesh* tsandesh) {
2361 }
2362 
2363 void t_py_generator::generate_py_sandesh_async(std::ofstream& out,
2364  t_sandesh* tsandesh) {
2365 }
2366 
2367 void t_py_generator::generate_py_sandesh_request(std::ofstream& out,
2368  t_sandesh* tsandesh) {
2369  // Generate http request handler
2370  generate_py_sandesh_http_request_handler(out, tsandesh);
2371  // Update sandesh request list
2372  sandesh_req_list_.push_back(tsandesh->get_name());
2373  // Update _HTTP_REQUEST_LIST in http_request.py
2374  generate_py_sandesh_http_request_list(f_http_request_, tsandesh);
2375  // Generate the Sandesh Request Skeleton
2376  generate_py_sandesh_skeleton_request(f_request_impl_, tsandesh);
2377 }
2378 
2379 void t_py_generator::generate_py_sandesh_response(std::ofstream& out,
2380  t_sandesh* tsandesh) {
2381 }
2382 
2383 void t_py_generator::generate_py_sandesh_uve(std::ofstream& out,
2384  t_sandesh* tsandesh,
2385  bool update) {
2386  const vector<t_field*>& fields = tsandesh->get_members();
2387  vector<t_field*>::const_iterator f_iter = fields.begin();
2388  assert((*f_iter)->get_name() == "data");
2389  t_type* t = get_true_type((*f_iter)->get_type());
2390  t_struct* ts = (t_struct*)t;
2391  if (update) {
2392  out << indent() << "def update_uve(self, tdata):" << endl;
2393  indent_up();
2394  assert(t->is_struct());
2395  const vector<t_field*>& sfields = ts->get_members();
2396  vector<t_field*>::const_iterator s_iter;
2397 
2398  for (s_iter = sfields.begin(); s_iter != sfields.end(); ++s_iter) {
2399  out << indent() << "if self.data." << (*s_iter)->get_name() << " is not None:" << endl;
2400  indent_up();
2401  out << indent() << "tdata." << (*s_iter)->get_name() << " = self.data." <<
2402  (*s_iter)->get_name() << endl;
2403  indent_down();
2404  }
2405  out << indent() << "return tdata" << endl;
2406  f_iter++;
2407  assert(f_iter == fields.end());
2408  indent_down();
2409  out << endl;
2410  }
2411 
2412  const t_base_type *sandesh_type = (t_base_type *)tsandesh->get_type();
2413  if (sandesh_type->is_sandesh_uve() || sandesh_type->is_sandesh_dynamic_uve()) {
2414  // Update sandesh UVE list
2415  sandesh_uve_list_.push_back(boost::make_tuple(tsandesh->get_name(),
2416  ts->get_name()));
2417  } else if (sandesh_type->is_sandesh_alarm()) {
2418  // Update sandesh Alarm list
2419  sandesh_alarm_list_.push_back(boost::make_tuple(tsandesh->get_name(),
2420  ts->get_name()));
2421  }
2422 }
2423 
2424 void t_py_generator::generate_py_sandesh_uve_list(ofstream& out) {
2425  out << endl << endl;
2426  out << "_SANDESH_UVE_LIST = [" << endl;
2427  std::vector<boost::tuple<std::string, std::string> >::const_iterator it;
2428  for (it = sandesh_uve_list_.begin(); it != sandesh_uve_list_.end(); ++it) {
2429  indent(out) << "(" << it->get<0>() << ", " << it->get<1>() << ")," << endl;
2430  }
2431  out << "]" << endl;
2432 }
2433 
2434 void t_py_generator::generate_py_sandesh_alarm_list(ofstream& out) {
2435  out << endl << endl;
2436  out << "_SANDESH_ALARM_LIST = [" << endl;
2437  std::vector<boost::tuple<std::string, std::string> >::const_iterator it;
2438  for (it = sandesh_alarm_list_.begin(); it != sandesh_alarm_list_.end();
2439  ++it) {
2440  indent(out) << "(" << it->get<0>() << ", " << it->get<1>() << ")," << endl;
2441  }
2442  out << "]" << endl;
2443 }
2444 #endif
2445 
2452  string f_service_name = package_dir_+"/"+service_name_+".py";
2453  f_service_.open(f_service_name.c_str());
2454 
2455  f_service_ <<
2456  py_autogen_comment() << endl <<
2457  py_imports() << endl;
2458 
2459  if (tservice->get_extends() != NULL) {
2460  f_service_ <<
2461  "import " << get_real_py_module(tservice->get_extends()->get_program(), gen_twisted_) <<
2462  "." << tservice->get_extends()->get_name() << endl;
2463  }
2464 
2465  f_service_ <<
2466  "from .ttypes import *" << endl <<
2467  "from thrift.Thrift import TProcessor" << endl <<
2468  render_fastbinary_includes() << endl;
2469 
2470  if (gen_twisted_) {
2471  f_service_ <<
2472  "from zope.interface import Interface, implements" << endl <<
2473  "from twisted.internet import defer" << endl <<
2474  "from thrift.transport import TTwisted" << endl;
2475  }
2476 
2477  f_service_ << endl;
2478 
2479  // Generate the three main parts of the service (well, two for now in PHP)
2480  generate_service_interface(tservice);
2481  generate_service_client(tservice);
2482  generate_service_server(tservice);
2483  generate_service_helpers(tservice);
2484  generate_service_remote(tservice);
2485 
2486  // Close service file
2487  f_service_.close();
2488 }
2489 
2496  vector<t_function*> functions = tservice->get_functions();
2497  vector<t_function*>::iterator f_iter;
2498 
2499  f_service_ <<
2500  "# HELPER FUNCTIONS AND STRUCTURES" << endl;
2501 
2502  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2503  t_struct* ts = (*f_iter)->get_arglist();
2506  }
2507 }
2508 
2515  if (!tfunction->is_oneway()) {
2516  t_struct result(program_, tfunction->get_name() + "_result");
2517  t_field success(tfunction->get_returntype(), "success", 0);
2518  if (!tfunction->get_returntype()->is_void()) {
2519  result.append(&success);
2520  }
2521 
2522  t_struct* xs = tfunction->get_xceptions();
2523  const vector<t_field*>& fields = xs->get_members();
2524  vector<t_field*>::const_iterator f_iter;
2525  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
2526  result.append(*f_iter);
2527  }
2528  generate_py_struct_definition(f_service_, &result, false, true);
2529  }
2530 }
2531 
2538  string extends = "";
2539  string extends_if = "";
2540  if (tservice->get_extends() != NULL) {
2541  extends = type_name(tservice->get_extends());
2542  extends_if = "(" + extends + ".Iface)";
2543  } else {
2544  if (gen_twisted_) {
2545  extends_if = "(Interface)";
2546  } else if (gen_newstyle_ || gen_dynamic_) {
2547  extends_if = "(object)";
2548  }
2549  }
2550 
2551  f_service_ <<
2552  "class Iface" << extends_if << ":" << endl;
2553  indent_up();
2555  vector<t_function*> functions = tservice->get_functions();
2556  if (functions.empty()) {
2557  f_service_ <<
2558  indent() << "pass" << endl;
2559  } else {
2560  vector<t_function*>::iterator f_iter;
2561  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2562  f_service_ <<
2563  indent() << "def " << function_signature_if(*f_iter) << ":" << endl;
2564  indent_up();
2566  f_service_ <<
2567  indent() << "pass" << endl << endl;
2568  indent_down();
2569  }
2570  }
2571 
2572  indent_down();
2573  f_service_ <<
2574  endl;
2575 }
2576 
2583  string extends = "";
2584  string extends_client = "";
2585  if (tservice->get_extends() != NULL) {
2586  extends = type_name(tservice->get_extends());
2587  if (gen_twisted_) {
2588  extends_client = "(" + extends + ".Client)";
2589  } else {
2590  extends_client = extends + ".Client, ";
2591  }
2592  } else {
2593  if (gen_twisted_ && (gen_newstyle_ || gen_dynamic_)) {
2594  extends_client = "(object)";
2595  }
2596  }
2597 
2598  if (gen_twisted_) {
2599  f_service_ <<
2600  "class Client" << extends_client << ":" << endl <<
2601  " implements(Iface)" << endl << endl;
2602  } else {
2603  f_service_ <<
2604  "class Client(" << extends_client << "Iface):" << endl;
2605  }
2606  indent_up();
2608 
2609  // Constructor function
2610  if (gen_twisted_) {
2611  f_service_ <<
2612  indent() << "def __init__(self, transport, oprot_factory):" << endl;
2613  } else {
2614  f_service_ <<
2615  indent() << "def __init__(self, iprot, oprot=None):" << endl;
2616  }
2617  if (extends.empty()) {
2618  if (gen_twisted_) {
2619  f_service_ <<
2620  indent() << " self._transport = transport" << endl <<
2621  indent() << " self._oprot_factory = oprot_factory" << endl <<
2622  indent() << " self._seqid = 0" << endl <<
2623  indent() << " self._reqs = {}" << endl <<
2624  endl;
2625  } else {
2626  f_service_ <<
2627  indent() << " self._iprot = self._oprot = iprot" << endl <<
2628  indent() << " if oprot is not None:" << endl <<
2629  indent() << " self._oprot = oprot" << endl <<
2630  indent() << " self._seqid = 0" << endl <<
2631  endl;
2632  }
2633  } else {
2634  if (gen_twisted_) {
2635  f_service_ <<
2636  indent() << " " << extends << ".Client.__init__(self, transport, oprot_factory)" << endl <<
2637  endl;
2638  } else {
2639  f_service_ <<
2640  indent() << " " << extends << ".Client.__init__(self, iprot, oprot)" << endl <<
2641  endl;
2642  }
2643  }
2644 
2645  // Generate client method implementations
2646  vector<t_function*> functions = tservice->get_functions();
2647  vector<t_function*>::const_iterator f_iter;
2648  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2649  t_struct* arg_struct = (*f_iter)->get_arglist();
2650  const vector<t_field*>& fields = arg_struct->get_members();
2651  vector<t_field*>::const_iterator fld_iter;
2652  string funname = (*f_iter)->get_name();
2653 
2654  // Open function
2655  indent(f_service_) <<
2656  "def " << function_signature(*f_iter) << ":" << endl;
2657  indent_up();
2659  if (gen_twisted_) {
2660  indent(f_service_) << "self._seqid += 1" << endl;
2661  if (!(*f_iter)->is_oneway()) {
2662  indent(f_service_) <<
2663  "d = self._reqs[self._seqid] = defer.Deferred()" << endl;
2664  }
2665  }
2666 
2667  indent(f_service_) <<
2668  "self.send_" << funname << "(";
2669 
2670  bool first = true;
2671  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2672  if (first) {
2673  first = false;
2674  } else {
2675  f_service_ << ", ";
2676  }
2677  f_service_ << (*fld_iter)->get_name();
2678  }
2679  f_service_ << ")" << endl;
2680 
2681  if (!(*f_iter)->is_oneway()) {
2682  f_service_ << indent();
2683  if (gen_twisted_) {
2684  f_service_ << "return d" << endl;
2685  } else {
2686  if (!(*f_iter)->get_returntype()->is_void()) {
2687  f_service_ << "return ";
2688  }
2689  f_service_ <<
2690  "self.recv_" << funname << "()" << endl;
2691  }
2692  } else {
2693  if (gen_twisted_) {
2694  f_service_ <<
2695  indent() << "return defer.succeed(None)" << endl;
2696  }
2697  }
2698  indent_down();
2699  f_service_ << endl;
2700 
2701  indent(f_service_) <<
2702  "def send_" << function_signature(*f_iter) << ":" << endl;
2703 
2704  indent_up();
2705 
2706  std::string argsname = (*f_iter)->get_name() + "_args";
2707 
2708  // Serialize the request header
2709  if (gen_twisted_) {
2710  f_service_ <<
2711  indent() << "oprot = self._oprot_factory.getProtocol(self._transport)" << endl <<
2712  indent() <<
2713  "oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', TMessageType.CALL, self._seqid)"
2714  << endl;
2715  } else {
2716  f_service_ <<
2717  indent() << "self._oprot.writeMessageBegin('" << (*f_iter)->get_name() << "', TMessageType.CALL, self._seqid)" << endl;
2718  }
2719 
2720  f_service_ <<
2721  indent() << "args = " << argsname << "()" << endl;
2722 
2723  for (fld_iter = fields.begin(); fld_iter != fields.end(); ++fld_iter) {
2724  f_service_ <<
2725  indent() << "args." << (*fld_iter)->get_name() << " = " << (*fld_iter)->get_name() << endl;
2726  }
2727 
2728  // Write to the stream
2729  if (gen_twisted_) {
2730  f_service_ <<
2731  indent() << "args.write(oprot)" << endl <<
2732  indent() << "oprot.writeMessageEnd()" << endl <<
2733  indent() << "oprot.trans.flush()" << endl;
2734  } else {
2735  f_service_ <<
2736  indent() << "args.write(self._oprot)" << endl <<
2737  indent() << "self._oprot.writeMessageEnd()" << endl <<
2738  indent() << "self._oprot.trans.flush()" << endl;
2739  }
2740 
2741  indent_down();
2742 
2743  if (!(*f_iter)->is_oneway()) {
2744  std::string resultname = (*f_iter)->get_name() + "_result";
2745  // Open function
2746  f_service_ <<
2747  endl;
2748  if (gen_twisted_) {
2749  f_service_ <<
2750  indent() << "def recv_" << (*f_iter)->get_name() <<
2751  "(self, iprot, mtype, rseqid):" << endl;
2752  } else {
2753  t_struct noargs(program_);
2754  t_function recv_function((*f_iter)->get_returntype(),
2755  string("recv_") + (*f_iter)->get_name(),
2756  &noargs);
2757  f_service_ <<
2758  indent() << "def " << function_signature(&recv_function) << ":" << endl;
2759  }
2760  indent_up();
2761 
2762  // TODO(mcslee): Validate message reply here, seq ids etc.
2763 
2764  if (gen_twisted_) {
2765  f_service_ <<
2766  indent() << "d = self._reqs.pop(rseqid)" << endl;
2767  } else {
2768  f_service_ <<
2769  indent() << "(fname, mtype, rseqid) = self._iprot.readMessageBegin()" << endl;
2770  }
2771 
2772  f_service_ <<
2773  indent() << "if mtype == TMessageType.EXCEPTION:" << endl <<
2774  indent() << " x = TApplicationException()" << endl;
2775 
2776  if (gen_twisted_) {
2777  f_service_ <<
2778  indent() << " x.read(iprot)" << endl <<
2779  indent() << " iprot.readMessageEnd()" << endl <<
2780  indent() << " return d.errback(x)" << endl <<
2781  indent() << "result = " << resultname << "()" << endl <<
2782  indent() << "result.read(iprot)" << endl <<
2783  indent() << "iprot.readMessageEnd()" << endl;
2784  } else {
2785  f_service_ <<
2786  indent() << " x.read(self._iprot)" << endl <<
2787  indent() << " self._iprot.readMessageEnd()" << endl <<
2788  indent() << " raise x" << endl <<
2789  indent() << "result = " << resultname << "()" << endl <<
2790  indent() << "result.read(self._iprot)" << endl <<
2791  indent() << "self._iprot.readMessageEnd()" << endl;
2792  }
2793 
2794  // Careful, only return _result if not a void function
2795  if (!(*f_iter)->get_returntype()->is_void()) {
2796  f_service_ <<
2797  indent() << "if result.success is not None:" << endl;
2798  if (gen_twisted_) {
2799  f_service_ <<
2800  indent() << " return d.callback(result.success)" << endl;
2801  } else {
2802  f_service_ <<
2803  indent() << " return result.success" << endl;
2804  }
2805  }
2806 
2807  t_struct* xs = (*f_iter)->get_xceptions();
2808  const std::vector<t_field*>& xceptions = xs->get_members();
2809  vector<t_field*>::const_iterator x_iter;
2810  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
2811  f_service_ <<
2812  indent() << "if result." << (*x_iter)->get_name() << " is not None:" << endl;
2813  if (gen_twisted_) {
2814  f_service_ <<
2815  indent() << " return d.errback(result." << (*x_iter)->get_name() << ")" << endl;
2816 
2817  } else {
2818  f_service_ <<
2819  indent() << " raise result." << (*x_iter)->get_name() << "" << endl;
2820  }
2821  }
2822 
2823  // Careful, only return _result if not a void function
2824  if ((*f_iter)->get_returntype()->is_void()) {
2825  if (gen_twisted_) {
2826  indent(f_service_) <<
2827  "return d.callback(None)" << endl;
2828  } else {
2829  indent(f_service_) <<
2830  "return" << endl;
2831  }
2832  } else {
2833  if (gen_twisted_) {
2834  f_service_ <<
2835  indent() << "return d.errback(TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\"))" << endl;
2836  } else {
2837  f_service_ <<
2838  indent() << "raise TApplicationException(TApplicationException.MISSING_RESULT, \"" << (*f_iter)->get_name() << " failed: unknown result\");" << endl;
2839  }
2840  }
2841 
2842  // Close function
2843  indent_down();
2844  f_service_ << endl;
2845  }
2846  }
2847 
2848  indent_down();
2849  f_service_ <<
2850  endl;
2851 }
2852 
2859  vector<t_function*> functions = tservice->get_functions();
2860  vector<t_function*>::iterator f_iter;
2861 
2862  string f_remote_name = package_dir_+"/"+service_name_+"-remote";
2863  ofstream f_remote;
2864  f_remote.open(f_remote_name.c_str());
2865 
2866  f_remote <<
2867  "#!/usr/bin/env python" << endl <<
2868  py_autogen_comment() << endl <<
2869  "import sys" << endl <<
2870  "import pprint" << endl <<
2871  "from urlparse import urlparse" << endl <<
2872  "from thrift.transport import TTransport" << endl <<
2873  "from thrift.transport import TSocket" << endl <<
2874  "from thrift.transport import THttpClient" << endl <<
2875  "from thrift.protocol import TBinaryProtocol" << endl <<
2876  endl;
2877 
2878  f_remote <<
2879  "import " << service_name_ << endl <<
2880  "from .ttypes import *" << endl <<
2881  endl;
2882 
2883  f_remote <<
2884  "if len(sys.argv) <= 1 or sys.argv[1] == '--help':" << endl <<
2885  " print ''" << endl <<
2886  " print 'Usage: ' + sys.argv[0] + ' [-h host[:port]] [-u url] [-f[ramed]] function [arg1 [arg2...]]'" << endl <<
2887  " print ''" << endl <<
2888  " print 'Functions:'" << endl;
2889  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2890  f_remote <<
2891  " print ' " << (*f_iter)->get_returntype()->get_name() << " " << (*f_iter)->get_name() << "(";
2892  t_struct* arg_struct = (*f_iter)->get_arglist();
2893  const std::vector<t_field*>& args = arg_struct->get_members();
2894  vector<t_field*>::const_iterator a_iter;
2895  int num_args = args.size();
2896  bool first = true;
2897  for (int i = 0; i < num_args; ++i) {
2898  if (first) {
2899  first = false;
2900  } else {
2901  f_remote << ", ";
2902  }
2903  f_remote <<
2904  args[i]->get_type()->get_name() << " " << args[i]->get_name();
2905  }
2906  f_remote << ")'" << endl;
2907  }
2908  f_remote <<
2909  " print ''" << endl <<
2910  " sys.exit(0)" << endl <<
2911  endl;
2912 
2913  f_remote <<
2914  "pp = pprint.PrettyPrinter(indent = 2)" << endl <<
2915  "host = 'localhost'" << endl <<
2916  "port = 9090" << endl <<
2917  "uri = ''" << endl <<
2918  "framed = False" << endl <<
2919  "http = False" << endl <<
2920  "argi = 1" << endl <<
2921  endl <<
2922  "if sys.argv[argi] == '-h':" << endl <<
2923  " parts = sys.argv[argi+1].split(':')" << endl <<
2924  " host = parts[0]" << endl <<
2925  " if len(parts) > 1:" << endl <<
2926  " port = int(parts[1])" << endl <<
2927  " argi += 2" << endl <<
2928  endl <<
2929  "if sys.argv[argi] == '-u':" << endl <<
2930  " url = urlparse(sys.argv[argi+1])" << endl <<
2931  " parts = url[1].split(':')" << endl <<
2932  " host = parts[0]" << endl <<
2933  " if len(parts) > 1:" << endl <<
2934  " port = int(parts[1])" << endl <<
2935  " else:" << endl <<
2936  " port = 80" << endl <<
2937  " uri = url[2]" << endl <<
2938  " if url[4]:" << endl <<
2939  " uri += '?%s' % url[4]" << endl <<
2940  " http = True" << endl <<
2941  " argi += 2" << endl <<
2942  endl <<
2943  "if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed':" << endl <<
2944  " framed = True" << endl <<
2945  " argi += 1" << endl <<
2946  endl <<
2947  "cmd = sys.argv[argi]" << endl <<
2948  "args = sys.argv[argi+1:]" << endl <<
2949  endl <<
2950  "if http:" << endl <<
2951  " transport = THttpClient.THttpClient(host, port, uri)" << endl <<
2952  "else:" << endl <<
2953  " socket = TSocket.TSocket(host, port)" << endl <<
2954  " if framed:" << endl <<
2955  " transport = TTransport.TFramedTransport(socket)" << endl <<
2956  " else:" << endl <<
2957  " transport = TTransport.TBufferedTransport(socket)" << endl <<
2958  "protocol = TBinaryProtocol.TBinaryProtocol(transport)" << endl <<
2959  "client = " << service_name_ << ".Client(protocol)" << endl <<
2960  "transport.open()" << endl <<
2961  endl;
2962 
2963  // Generate the dispatch methods
2964  bool first = true;
2965 
2966  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
2967  if (first) {
2968  first = false;
2969  } else {
2970  f_remote << "el";
2971  }
2972 
2973  t_struct* arg_struct = (*f_iter)->get_arglist();
2974  const std::vector<t_field*>& args = arg_struct->get_members();
2975  vector<t_field*>::const_iterator a_iter;
2976  int num_args = args.size();
2977 
2978  f_remote <<
2979  "if cmd == '" << (*f_iter)->get_name() << "':" << endl <<
2980  " if len(args) != " << num_args << ":" << endl <<
2981  " print '" << (*f_iter)->get_name() << " requires " << num_args << " args'" << endl <<
2982  " sys.exit(1)" << endl <<
2983  " pp.pprint(client." << (*f_iter)->get_name() << "(";
2984  for (int i = 0; i < num_args; ++i) {
2985  if (args[i]->get_type()->is_string()) {
2986  f_remote << "args[" << i << "],";
2987  } else {
2988  f_remote << "eval(args[" << i << "]),";
2989  }
2990  }
2991  f_remote << "))" << endl;
2992 
2993  f_remote << endl;
2994  }
2995  f_remote << "else:" << endl;
2996  f_remote << " print 'Unrecognized method %s' % cmd" << endl;
2997  f_remote << " sys.exit(1)" << endl;
2998  f_remote << endl;
2999 
3000  f_remote << "transport.close()" << endl;
3001 
3002  // Close service file
3003  f_remote.close();
3004 
3005 #ifndef _MSC_VER
3006 
3007  // Make file executable, love that bitwise OR action
3008  chmod(f_remote_name.c_str(),
3009  S_IRUSR
3010  | S_IWUSR
3011  | S_IXUSR
3012 #ifndef MINGW
3013  | S_IRGRP
3014  | S_IXGRP
3015  | S_IROTH
3016  | S_IXOTH
3017 #endif
3018  );
3019 
3020 #endif // _MSC_VER
3021 }
3022 
3029  // Generate the dispatch methods
3030  vector<t_function*> functions = tservice->get_functions();
3031  vector<t_function*>::iterator f_iter;
3032 
3033  string extends = "";
3034  string extends_processor = "";
3035  if (tservice->get_extends() != NULL) {
3036  extends = type_name(tservice->get_extends());
3037  extends_processor = extends + ".Processor, ";
3038  }
3039 
3040  // Generate the header portion
3041  if (gen_twisted_) {
3042  f_service_ <<
3043  "class Processor(" << extends_processor << "TProcessor):" << endl <<
3044  " implements(Iface)" << endl << endl;
3045  } else {
3046  f_service_ <<
3047  "class Processor(" << extends_processor << "Iface, TProcessor):" << endl;
3048  }
3049 
3050  indent_up();
3051 
3052  indent(f_service_) <<
3053  "def __init__(self, handler):" << endl;
3054  indent_up();
3055  if (extends.empty()) {
3056  if (gen_twisted_) {
3057  f_service_ <<
3058  indent() << "self._handler = Iface(handler)" << endl;
3059  } else {
3060  f_service_ <<
3061  indent() << "self._handler = handler" << endl;
3062  }
3063 
3064  f_service_ <<
3065  indent() << "self._processMap = {}" << endl;
3066  } else {
3067  if (gen_twisted_) {
3068  f_service_ <<
3069  indent() << extends << ".Processor.__init__(self, Iface(handler))" << endl;
3070  } else {
3071  f_service_ <<
3072  indent() << extends << ".Processor.__init__(self, handler)" << endl;
3073  }
3074  }
3075  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
3076  f_service_ <<
3077  indent() << "self._processMap[\"" << (*f_iter)->get_name() << "\"] = Processor.process_" << (*f_iter)->get_name() << endl;
3078  }
3079  indent_down();
3080  f_service_ << endl;
3081 
3082  // Generate the server implementation
3083  indent(f_service_) <<
3084  "def process(self, iprot, oprot):" << endl;
3085  indent_up();
3086 
3087  f_service_ <<
3088  indent() << "(name, type, seqid) = iprot.readMessageBegin()" << endl;
3089 
3090  // TODO(mcslee): validate message
3091 
3092  // HOT: dictionary function lookup
3093  f_service_ <<
3094  indent() << "if name not in self._processMap:" << endl <<
3095  indent() << " iprot.skip(TType.STRUCT)" << endl <<
3096  indent() << " iprot.readMessageEnd()" << endl <<
3097  indent() << " x = TApplicationException(TApplicationException.UNKNOWN_METHOD, 'Unknown function %s' % (name))" << endl <<
3098  indent() << " oprot.writeMessageBegin(name, TMessageType.EXCEPTION, seqid)" << endl <<
3099  indent() << " x.write(oprot)" << endl <<
3100  indent() << " oprot.writeMessageEnd()" << endl <<
3101  indent() << " oprot.trans.flush()" << endl;
3102 
3103  if (gen_twisted_) {
3104  f_service_ <<
3105  indent() << " return defer.succeed(None)" << endl;
3106  } else {
3107  f_service_ <<
3108  indent() << " return" << endl;
3109  }
3110 
3111  f_service_ <<
3112  indent() << "else:" << endl;
3113 
3114  if (gen_twisted_) {
3115  f_service_ <<
3116  indent() << " return self._processMap[name](self, seqid, iprot, oprot)" << endl;
3117  } else {
3118  f_service_ <<
3119  indent() << " self._processMap[name](self, seqid, iprot, oprot)" << endl;
3120 
3121  // Read end of args field, the T_STOP, and the struct close
3122  f_service_ <<
3123  indent() << "return True" << endl;
3124  }
3125 
3126  indent_down();
3127  f_service_ << endl;
3128 
3129  // Generate the process subfunctions
3130  for (f_iter = functions.begin(); f_iter != functions.end(); ++f_iter) {
3131  generate_process_function(tservice, *f_iter);
3132  }
3133 
3134  indent_down();
3135  f_service_ << endl;
3136 }
3137 
3144  t_function* tfunction) {
3145  (void) tservice;
3146  // Open function
3147  indent(f_service_) <<
3148  "def process_" << tfunction->get_name() <<
3149  "(self, seqid, iprot, oprot):" << endl;
3150  indent_up();
3151 
3152  string argsname = tfunction->get_name() + "_args";
3153  string resultname = tfunction->get_name() + "_result";
3154 
3155  f_service_ <<
3156  indent() << "args = " << argsname << "()" << endl <<
3157  indent() << "args.read(iprot)" << endl <<
3158  indent() << "iprot.readMessageEnd()" << endl;
3159 
3160  t_struct* xs = tfunction->get_xceptions();
3161  const std::vector<t_field*>& xceptions = xs->get_members();
3162  vector<t_field*>::const_iterator x_iter;
3163 
3164  // Declare result for non oneway function
3165  if (!tfunction->is_oneway()) {
3166  f_service_ <<
3167  indent() << "result = " << resultname << "()" << endl;
3168  }
3169 
3170  if (gen_twisted_) {
3171  // Generate the function call
3172  t_struct* arg_struct = tfunction->get_arglist();
3173  const std::vector<t_field*>& fields = arg_struct->get_members();
3174  vector<t_field*>::const_iterator f_iter;
3175 
3176  f_service_ <<
3177  indent() << "d = defer.maybeDeferred(self._handler." <<
3178  tfunction->get_name() << ", ";
3179  bool first = true;
3180  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3181  if (first) {
3182  first = false;
3183  } else {
3184  f_service_ << ", ";
3185  }
3186  f_service_ << "args." << (*f_iter)->get_name();
3187  }
3188  f_service_ << ")" << endl;
3189 
3190  // Shortcut out here for oneway functions
3191  if (tfunction->is_oneway()) {
3192  f_service_ <<
3193  indent() << "return d" << endl;
3194  indent_down();
3195  f_service_ << endl;
3196  return;
3197  }
3198 
3199  f_service_ <<
3200  indent() <<
3201  "d.addCallback(self.write_results_success_" <<
3202  tfunction->get_name() << ", result, seqid, oprot)" << endl;
3203 
3204  if (xceptions.size() > 0) {
3205  f_service_ <<
3206  indent() <<
3207  "d.addErrback(self.write_results_exception_" <<
3208  tfunction->get_name() << ", result, seqid, oprot)" << endl;
3209  }
3210 
3211  f_service_ <<
3212  indent() << "return d" << endl;
3213 
3214  indent_down();
3215  f_service_ << endl;
3216 
3217  indent(f_service_) <<
3218  "def write_results_success_" << tfunction->get_name() <<
3219  "(self, success, result, seqid, oprot):" << endl;
3220  indent_up();
3221  f_service_ <<
3222  indent() << "result.success = success" << endl <<
3223  indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name() <<
3224  "\", TMessageType.REPLY, seqid)" << endl <<
3225  indent() << "result.write(oprot)" << endl <<
3226  indent() << "oprot.writeMessageEnd()" << endl <<
3227  indent() << "oprot.trans.flush()" << endl;
3228  indent_down();
3229  f_service_ << endl;
3230 
3231  // Try block for a function with exceptions
3232  if (!tfunction->is_oneway() && xceptions.size() > 0) {
3233  indent(f_service_) <<
3234  "def write_results_exception_" << tfunction->get_name() <<
3235  "(self, error, result, seqid, oprot):" << endl;
3236  indent_up();
3237  f_service_ <<
3238  indent() << "try:" << endl;
3239 
3240  // Kinda absurd
3241  f_service_ <<
3242  indent() << " error.raiseException()" << endl;
3243  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
3244  f_service_ <<
3245  indent() << "except " << type_name((*x_iter)->get_type()) << ", " << (*x_iter)->get_name() << ":" << endl;
3246  if (!tfunction->is_oneway()) {
3247  indent_up();
3248  f_service_ <<
3249  indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << endl;
3250  indent_down();
3251  } else {
3252  f_service_ <<
3253  indent() << "pass" << endl;
3254  }
3255  }
3256  f_service_ <<
3257  indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name() <<
3258  "\", TMessageType.REPLY, seqid)" << endl <<
3259  indent() << "result.write(oprot)" << endl <<
3260  indent() << "oprot.writeMessageEnd()" << endl <<
3261  indent() << "oprot.trans.flush()" << endl;
3262  indent_down();
3263  f_service_ << endl;
3264  }
3265  } else {
3266 
3267  // Try block for a function with exceptions
3268  if (xceptions.size() > 0) {
3269  f_service_ <<
3270  indent() << "try:" << endl;
3271  indent_up();
3272  }
3273 
3274  // Generate the function call
3275  t_struct* arg_struct = tfunction->get_arglist();
3276  const std::vector<t_field*>& fields = arg_struct->get_members();
3277  vector<t_field*>::const_iterator f_iter;
3278 
3279  f_service_ << indent();
3280  if (!tfunction->is_oneway() && !tfunction->get_returntype()->is_void()) {
3281  f_service_ << "result.success = ";
3282  }
3283  f_service_ <<
3284  "self._handler." << tfunction->get_name() << "(";
3285  bool first = true;
3286  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
3287  if (first) {
3288  first = false;
3289  } else {
3290  f_service_ << ", ";
3291  }
3292  f_service_ << "args." << (*f_iter)->get_name();
3293  }
3294  f_service_ << ")" << endl;
3295 
3296  if (!tfunction->is_oneway() && xceptions.size() > 0) {
3297  indent_down();
3298  for (x_iter = xceptions.begin(); x_iter != xceptions.end(); ++x_iter) {
3299  f_service_ <<
3300  indent() << "except " << type_name((*x_iter)->get_type()) << ", " << (*x_iter)->get_name() << ":" << endl;
3301  if (!tfunction->is_oneway()) {
3302  indent_up();
3303  f_service_ <<
3304  indent() << "result." << (*x_iter)->get_name() << " = " << (*x_iter)->get_name() << endl;
3305  indent_down();
3306  } else {
3307  f_service_ <<
3308  indent() << "pass" << endl;
3309  }
3310  }
3311  }
3312 
3313  // Shortcut out here for oneway functions
3314  if (tfunction->is_oneway()) {
3315  f_service_ <<
3316  indent() << "return" << endl;
3317  indent_down();
3318  f_service_ << endl;
3319  return;
3320  }
3321 
3322  f_service_ <<
3323  indent() << "oprot.writeMessageBegin(\"" << tfunction->get_name() << "\", TMessageType.REPLY, seqid)" << endl <<
3324  indent() << "result.write(oprot)" << endl <<
3325  indent() << "oprot.writeMessageEnd()" << endl <<
3326  indent() << "oprot.trans.flush()" << endl;
3327 
3328  // Close function
3329  indent_down();
3330  f_service_ << endl;
3331  }
3332 }
3333 
3338  t_field* tfield,
3339  string prefix,
3340  bool inclass) {
3341  (void) inclass;
3342  t_type* type = get_true_type(tfield->get_type());
3343 
3344  if (type->is_void()) {
3345  throw "CANNOT GENERATE DESERIALIZE CODE FOR void TYPE: " +
3346  prefix + tfield->get_name();
3347  }
3348 
3349  string name = prefix + tfield->get_name();
3350 
3351  if (type->is_struct() || type->is_xception()) {
3353  (t_struct*)type,
3354  name);
3355  } else if (type->is_container()) {
3356  generate_deserialize_container(out, type, name);
3357  } else if (type->is_base_type() || type->is_enum()) {
3358  indent(out) <<
3359 #ifdef SANDESH
3360  "(length, " << name << ") = iprot.";
3361 #else
3362  name << " = iprot.";
3363 #endif
3364  if (type->is_base_type()) {
3365  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3366  switch (tbase) {
3368  throw "compiler error: cannot serialize void field in a struct: " +
3369  name;
3370  break;
3372 #ifdef SANDESH
3373  case t_base_type::TYPE_STATIC_CONST_STRING:
3374 #endif
3375  if (((t_base_type*)type)->is_binary() || !gen_utf8strings_) {
3376  out << "readString();";
3377  } else {
3378  out << "readString().decode('utf-8')";
3379  }
3380  break;
3381 #ifdef SANDESH
3382  case t_base_type::TYPE_XML:
3383  out << "readXML();";
3384  break;
3385  case t_base_type::TYPE_UUID:
3386  out << "readUUID();";
3387  break;
3388 #endif
3390  out << "readBool();";
3391  break;
3393  out << "readByte();";
3394  break;
3395  case t_base_type::TYPE_I16:
3396  out << "readI16();";
3397  break;
3398  case t_base_type::TYPE_I32:
3399  out << "readI32();";
3400  break;
3401  case t_base_type::TYPE_I64:
3402  out << "readI64();";
3403  break;
3404 #ifdef SANDESH
3405  case t_base_type::TYPE_U16:
3406  out << "readU16();";
3407  break;
3408  case t_base_type::TYPE_U32:
3409  out << "readU32();";
3410  break;
3411  case t_base_type::TYPE_U64:
3412  out << "readU64();";
3413  break;
3414  case t_base_type::TYPE_IPV4:
3415  out << "readIPV4();";
3416  break;
3417  case t_base_type::TYPE_IPADDR:
3418  out << "readIPADDR()";
3419  break;
3420 #endif
3422  out << "readDouble();";
3423  break;
3424  default:
3425  throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
3426  }
3427  } else if (type->is_enum()) {
3428  out << "readI32();";
3429  }
3430  out << endl;
3431 #ifdef SANDESH
3432  indent(out) << "if length < 0: return -1" << endl;
3433  indent(out) << "read_cnt += length" << endl;
3434 #endif
3435  } else {
3436  printf("DO NOT KNOW HOW TO DESERIALIZE FIELD '%s' TYPE '%s'\n",
3437  tfield->get_name().c_str(), type->get_name().c_str());
3438  }
3439 }
3440 
3445  t_struct* tstruct,
3446  string prefix) {
3447  out <<
3448  indent() << prefix << " = " << type_name(tstruct) << "()" << endl <<
3449 #ifdef SANDESH
3450  indent() << "read_cnt += " << prefix << ".read(iprot)" << endl;
3451 #else
3452  indent() << prefix << ".read(iprot)" << endl;
3453 #endif
3454 }
3455 
3461  t_type* ttype,
3462  string prefix) {
3463  string size = tmp("_size");
3464  string ktype = tmp("_ktype");
3465  string vtype = tmp("_vtype");
3466  string etype = tmp("_etype");
3467 
3468  t_field fsize(g_type_i32, size);
3469  t_field fktype(g_type_byte, ktype);
3470  t_field fvtype(g_type_byte, vtype);
3471  t_field fetype(g_type_byte, etype);
3472 
3473  // Declare variables, read header
3474  if (ttype->is_map()) {
3475  out <<
3476  indent() << prefix << " = {}" << endl <<
3477 #ifdef SANDESH
3478  indent() << "(length, " << ktype << ", " << vtype << ", " << size << " ) = iprot.readMapBegin() " << endl <<
3479  indent() << "read_cnt += length" << endl;
3480 #else
3481  indent() << "(" << ktype << ", " << vtype << ", " << size << " ) = iprot.readMapBegin() " << endl;
3482 #endif
3483  } else if (ttype->is_set()) {
3484  out <<
3485  indent() << prefix << " = set()" << endl <<
3486 #ifdef SANDESH
3487  indent() << "(length, " << etype << ", " << size << ") = iprot.readSetBegin()" << endl <<
3488  indent() << "read_cnt += length" << endl;
3489 #else
3490  indent() << "(" << etype << ", " << size << ") = iprot.readSetBegin()" << endl;
3491 #endif
3492  } else if (ttype->is_list()) {
3493  out <<
3494  indent() << prefix << " = []" << endl <<
3495 #ifdef SANDESH
3496  indent() << "(length, " << etype << ", " << size << ") = iprot.readListBegin()" << endl <<
3497  indent() << "read_cnt += length" << endl;
3498 #else
3499  indent() << "(" << etype << ", " << size << ") = iprot.readListBegin()" << endl;
3500 #endif
3501  }
3502 
3503  // For loop iterates over elements
3504  string i = tmp("_i");
3505  indent(out) <<
3506  "for " << i << " in range(" << size << "):" << endl;
3507 
3508  indent_up();
3509 
3510  if (ttype->is_map()) {
3511  generate_deserialize_map_element(out, (t_map*)ttype, prefix);
3512  } else if (ttype->is_set()) {
3513 #ifdef SANDESH
3514  t_type *etype = ((t_set*)ttype)->get_elem_type();
3515  if (etype->is_base_type() || etype->is_enum()) {
3516  indent(out) << "read_cnt += iprot.readContainerElementBegin()" << endl;
3517  }
3518 #endif
3519  generate_deserialize_set_element(out, (t_set*)ttype, prefix);
3520 #ifdef SANDESH
3521  if (etype->is_base_type() || etype->is_enum()) {
3522  indent(out) << "read_cnt += iprot.readContainerElementEnd()" << endl;
3523  }
3524 #endif
3525  } else if (ttype->is_list()) {
3526 #ifdef SANDESH
3527  t_type *etype = ((t_list*)ttype)->get_elem_type();
3528  if (etype->is_base_type() || etype->is_enum()) {
3529  indent(out) << "read_cnt += iprot.readContainerElementBegin()" << endl;
3530  }
3531 #endif
3532  generate_deserialize_list_element(out, (t_list*)ttype, prefix);
3533 #ifdef SANDESH
3534  if (etype->is_base_type() || etype->is_enum()) {
3535  indent(out) << "read_cnt += iprot.readContainerElementEnd()" << endl;
3536  }
3537 #endif
3538  }
3539 
3540  indent_down();
3541 
3542  // Read container end
3543  if (ttype->is_map()) {
3544 #ifdef SANDESH
3545  indent(out) << "read_cnt += iprot.readMapEnd()" << endl;
3546 #else
3547  indent(out) << "iprot.readMapEnd()" << endl;
3548 #endif
3549  } else if (ttype->is_set()) {
3550 #ifdef SANDESH
3551  indent(out) << "read_cnt += iprot.readSetEnd()" << endl;
3552 #else
3553  indent(out) << "iprot.readSetEnd()" << endl;
3554 #endif
3555  } else if (ttype->is_list()) {
3556 #ifdef SANDESH
3557  indent(out) << "read_cnt += iprot.readListEnd()" << endl;
3558 #else
3559  indent(out) << "iprot.readListEnd()" << endl;
3560 #endif
3561  }
3562 }
3563 
3564 
3569  t_map* tmap,
3570  string prefix) {
3571  string key = tmp("_key");
3572  string val = tmp("_val");
3573  t_field fkey(tmap->get_key_type(), key);
3574  t_field fval(tmap->get_val_type(), val);
3575 
3576 #ifdef SANDESH
3577  t_type* kttype = tmap->get_key_type();
3578  if (kttype->is_base_type() || kttype->is_enum()) {
3579  indent(out) << "read_cnt += iprot.readContainerElementBegin()" << endl;
3580  }
3581 #endif
3582  generate_deserialize_field(out, &fkey);
3583 #ifdef SANDESH
3584  if (kttype->is_base_type() || kttype->is_enum()) {
3585  indent(out) << "read_cnt += iprot.readContainerElementEnd()" << endl;
3586  }
3587 #endif
3588 
3589 #ifdef SANDESH
3590  t_type* vttype = tmap->get_val_type();
3591  if (vttype->is_base_type() || vttype->is_enum()) {
3592  indent(out) << "read_cnt += iprot.readContainerElementBegin()" << endl;
3593  }
3594 #endif
3595  generate_deserialize_field(out, &fval);
3596 #ifdef SANDESH
3597  if (vttype->is_base_type() || vttype->is_enum()) {
3598  indent(out) << "read_cnt += iprot.readContainerElementEnd()" << endl;
3599  }
3600 #endif
3601 
3602  indent(out) <<
3603  prefix << "[" << key << "] = " << val << endl;
3604 }
3605 
3610  t_set* tset,
3611  string prefix) {
3612  string elem = tmp("_elem");
3613  t_field felem(tset->get_elem_type(), elem);
3614 
3615  generate_deserialize_field(out, &felem);
3616 
3617  indent(out) <<
3618  prefix << ".add(" << elem << ")" << endl;
3619 }
3620 
3625  t_list* tlist,
3626  string prefix) {
3627  string elem = tmp("_elem");
3628  t_field felem(tlist->get_elem_type(), elem);
3629 
3630  generate_deserialize_field(out, &felem);
3631 
3632  indent(out) <<
3633  prefix << ".append(" << elem << ")" << endl;
3634 }
3635 
3636 
3644  t_field* tfield,
3645  string prefix) {
3646  t_type* type = get_true_type(tfield->get_type());
3647 
3648  // Do nothing for void types
3649  if (type->is_void()) {
3650  throw "CANNOT GENERATE SERIALIZE CODE FOR void TYPE: " +
3651  prefix + tfield->get_name();
3652  }
3653 
3654  if (type->is_struct() || type->is_xception()) {
3656  (t_struct*)type,
3657  prefix + tfield->get_name());
3658  } else if (type->is_container()) {
3660  type,
3661  prefix + tfield->get_name());
3662  } else if (type->is_base_type() || type->is_enum()) {
3663 
3664  string name = prefix + tfield->get_name();
3665 
3666  indent(out) <<
3667  "if oprot.";
3668 
3669  if (type->is_base_type()) {
3670  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
3671  switch (tbase) {
3673  throw
3674  "compiler error: cannot serialize void field in a struct: " + name;
3675  break;
3677 #ifdef SANDESH
3678  case t_base_type::TYPE_STATIC_CONST_STRING:
3679 #endif
3680  if (((t_base_type*)type)->is_binary() || !gen_utf8strings_) {
3681  out << "writeString(" << name << ")";
3682  } else {
3683  out << "writeString(" << name << ".encode('utf-8'))";
3684  }
3685  break;
3686 #ifdef SANDESH
3687  case t_base_type::TYPE_XML:
3688  out << "writeXML(" << name << ")";
3689  break;
3690  case t_base_type::TYPE_UUID:
3691  out << "writeUUID(" << name << ")";
3692  break;
3693 #endif
3695  out << "writeBool(" << name << ")";
3696  break;
3698  out << "writeByte(" << name << ")";
3699  break;
3700  case t_base_type::TYPE_I16:
3701  out << "writeI16(" << name << ")";
3702  break;
3703  case t_base_type::TYPE_I32:
3704  out << "writeI32(" << name << ")";
3705  break;
3706  case t_base_type::TYPE_I64:
3707  out << "writeI64(" << name << ")";
3708  break;
3709 #ifdef SANDESH
3710  case t_base_type::TYPE_U16:
3711  out << "writeU16(" << name << ")";
3712  break;
3713  case t_base_type::TYPE_U32:
3714  out << "writeU32(" << name << ")";
3715  break;
3716  case t_base_type::TYPE_U64:
3717  out << "writeU64(" << name << ")";
3718  break;
3719  case t_base_type::TYPE_IPV4:
3720  out << "writeIPV4(" << name << ")";
3721  break;
3722  case t_base_type::TYPE_IPADDR:
3723  out << "writeIPADDR(" << name << ")";
3724  break;
3725 #endif
3727  out << "writeDouble(" << name << ")";
3728  break;
3729  default:
3730  throw "compiler error: no PHP name for base type " + t_base_type::t_base_name(tbase);
3731  }
3732  } else if (type->is_enum()) {
3733  out << "writeI32(" << name << ")";
3734  }
3735  out << " < 0: return -1" << endl;
3736 #ifdef SANDESH
3737  } else if (type->is_sandesh()) {
3738  generate_serialize_sandesh(out, (t_sandesh*)type,
3739  prefix + tfield->get_name());
3740 #endif
3741  } else {
3742  printf("DO NOT KNOW HOW TO SERIALIZE FIELD '%s%s' TYPE '%s'\n",
3743  prefix.c_str(),
3744  tfield->get_name().c_str(),
3745  type->get_name().c_str());
3746  }
3747 }
3748 
3756  t_struct* tstruct,
3757  string prefix) {
3758  (void) tstruct;
3759  indent(out) <<
3760  "if " << prefix << ".write(oprot) < 0: return -1" << endl;
3761 }
3762 
3763 #ifdef SANDESH
3764 
3770 void t_py_generator::generate_serialize_sandesh(ofstream &out,
3771  t_sandesh* tsandesh,
3772  string prefix) {
3773  (void) tsandesh;
3774  indent(out) <<
3775  "if " << prefix << ".write(oprot) < 0: return -1" << endl;
3776 }
3777 #endif
3778 
3780  t_type* ttype,
3781  string prefix) {
3782  if (ttype->is_map()) {
3783  indent(out) <<
3784  "if oprot.writeMapBegin(" <<
3785  type_to_enum(((t_map*)ttype)->get_key_type()) << ", " <<
3786  type_to_enum(((t_map*)ttype)->get_val_type()) << ", " <<
3787  "len(" << prefix << ")) < 0: return -1" << endl;
3788  } else if (ttype->is_set()) {
3789  indent(out) <<
3790  "if oprot.writeSetBegin(" <<
3791  type_to_enum(((t_set*)ttype)->get_elem_type()) << ", " <<
3792  "len(" << prefix << ")) < 0: return -1" << endl;
3793  } else if (ttype->is_list()) {
3794  indent(out) <<
3795  "if oprot.writeListBegin(" <<
3796  type_to_enum(((t_list*)ttype)->get_elem_type()) << ", " <<
3797  "len(" << prefix << ")) < 0: return -1" << endl;
3798  }
3799 
3800  if (ttype->is_map()) {
3801  string kiter = tmp("kiter");
3802  string viter = tmp("viter");
3803  indent(out) <<
3804  "for " << kiter << "," << viter << " in " << prefix << ".items():" << endl;
3805  indent_up();
3806  generate_serialize_map_element(out, (t_map*)ttype, kiter, viter);
3807  indent_down();
3808  } else if (ttype->is_set()) {
3809  string iter = tmp("iter");
3810  indent(out) <<
3811  "for " << iter << " in " << prefix << ":" << endl;
3812  indent_up();
3813 #ifdef SANDESH
3814  t_type *etype = ((t_set*)ttype)->get_elem_type();
3815  if (etype->is_base_type() || etype->is_enum()) {
3816  indent(out) << "if oprot.writeContainerElementBegin() < 0: return -1" << endl;
3817  }
3818 #endif
3819  generate_serialize_set_element(out, (t_set*)ttype, iter);
3820 #ifdef SANDESH
3821  if (etype->is_base_type() || etype->is_enum()) {
3822  indent(out) << "if oprot.writeContainerElementEnd() < 0: return -1" << endl;
3823  }
3824 #endif
3825  indent_down();
3826  } else if (ttype->is_list()) {
3827  string iter = tmp("iter");
3828  indent(out) <<
3829  "for " << iter << " in " << prefix << ":" << endl;
3830  indent_up();
3831 #ifdef SANDESH
3832  t_type *etype = ((t_list*)ttype)->get_elem_type();
3833  if (etype->is_base_type() || etype->is_enum()) {
3834  indent(out) << "if oprot.writeContainerElementBegin() < 0: return -1" << endl;
3835  }
3836 #endif
3837  generate_serialize_list_element(out, (t_list*)ttype, iter);
3838 #ifdef SANDESH
3839  if (etype->is_base_type() || etype->is_enum()) {
3840  indent(out) << "if oprot.writeContainerElementEnd() < 0: return -1" << endl;
3841  }
3842 #endif
3843  indent_down();
3844  }
3845 
3846  if (ttype->is_map()) {
3847  indent(out) <<
3848  "if oprot.writeMapEnd() < 0: return -1" << endl;
3849  } else if (ttype->is_set()) {
3850  indent(out) <<
3851  "if oprot.writeSetEnd() < 0: return -1" << endl;
3852  } else if (ttype->is_list()) {
3853  indent(out) <<
3854  "if oprot.writeListEnd() < 0: return -1" << endl;
3855  }
3856 }
3857 
3863  t_map* tmap,
3864  string kiter,
3865  string viter) {
3866 #ifdef SANDESH
3867  t_type* kttype = tmap->get_key_type();
3868  if (kttype->is_base_type() || kttype->is_enum()) {
3869  indent(out) << "if oprot.writeContainerElementBegin() < 0: return -1" << endl;
3870  }
3871 #endif
3872  t_field kfield(tmap->get_key_type(), kiter);
3873  generate_serialize_field(out, &kfield, "");
3874 #ifdef SANDESH
3875  if (kttype->is_base_type() || kttype->is_enum()) {
3876  indent(out) << "if oprot.writeContainerElementEnd() < 0: return -1" << endl;
3877  }
3878 #endif
3879 
3880 #ifdef SANDESH
3881  t_type* vttype = tmap->get_val_type();
3882  if (vttype->is_base_type() || vttype->is_enum()) {
3883  indent(out) << "if oprot.writeContainerElementBegin() < 0: return -1" << endl;
3884  }
3885 #endif
3886  t_field vfield(tmap->get_val_type(), viter);
3887  generate_serialize_field(out, &vfield, "");
3888 #ifdef SANDESH
3889  if (vttype->is_base_type() || vttype->is_enum()) {
3890  indent(out) << "if oprot.writeContainerElementEnd() < 0: return -1" << endl;
3891  }
3892 #endif
3893 }
3894 
3899  t_set* tset,
3900  string iter) {
3901  t_field efield(tset->get_elem_type(), iter);
3902  generate_serialize_field(out, &efield, "");
3903 }
3904 
3909  t_list* tlist,
3910  string iter) {
3911  t_field efield(tlist->get_elem_type(), iter);
3912  generate_serialize_field(out, &efield, "");
3913 }
3914 
3919  t_struct* tstruct) {
3920  generate_python_docstring(out, tstruct, tstruct, "Attributes");
3921 }
3922 
3927  t_function* tfunction) {
3928  generate_python_docstring(out, tfunction, tfunction->get_arglist(), "Parameters");
3929 }
3930 
3935  t_doc* tdoc,
3936  t_struct* tstruct,
3937  const char* subheader) {
3938  bool has_doc = false;
3939  stringstream ss;
3940  if (tdoc->has_doc()) {
3941  has_doc = true;
3942  ss << tdoc->get_doc();
3943  }
3944 
3945  const vector<t_field*>& fields = tstruct->get_members();
3946  if (fields.size() > 0) {
3947  if (has_doc) {
3948  ss << endl;
3949  }
3950  has_doc = true;
3951  ss << subheader << ":\n";
3952  vector<t_field*>::const_iterator p_iter;
3953  for (p_iter = fields.begin(); p_iter != fields.end(); ++p_iter) {
3954  t_field* p = *p_iter;
3955  ss << " - " << p->get_name();
3956  if (p->has_doc()) {
3957  ss << ": " << p->get_doc();
3958  } else {
3959  ss << endl;
3960  }
3961  }
3962  }
3963 
3964  if (has_doc) {
3966  "\"\"\"\n",
3967  "", ss.str(),
3968  "\"\"\"\n");
3969  }
3970 }
3971 
3976  t_doc* tdoc) {
3977  if (tdoc->has_doc()) {
3979  "\"\"\"\n",
3980  "", tdoc->get_doc(),
3981  "\"\"\"\n");
3982  }
3983 }
3984 
3991  std::ostringstream result;
3992  result << tfield->get_name() << "=";
3993  if (tfield->get_value() != NULL) {
3994  result << "thrift_spec[" <<
3995  tfield->get_key() << "][4]";
3996  } else {
3997  result << "None";
3998  }
3999  return result.str();
4000 }
4001 
4008  t_type* type = get_true_type(tfield->get_type());
4009  if (tfield->get_value() != NULL) {
4010  return render_const_value(type, tfield->get_value());
4011  } else {
4012  return "None";
4013  }
4014 }
4015 
4023  string prefix) {
4024  // TODO(mcslee): Nitpicky, no ',' if argument_list is empty
4025  return
4026  prefix + tfunction->get_name() +
4027  "(self, " + argument_list(tfunction->get_arglist()) + ")";
4028 }
4029 
4037  string prefix) {
4038  // TODO(mcslee): Nitpicky, no ',' if argument_list is empty
4039  string signature = prefix + tfunction->get_name() + "(";
4040  if (!gen_twisted_) {
4041  signature += "self, ";
4042  }
4043  signature += argument_list(tfunction->get_arglist()) + ")";
4044  return signature;
4045 }
4046 
4047 
4052  string result = "";
4053 
4054  const vector<t_field*>& fields = tstruct->get_members();
4055  vector<t_field*>::const_iterator f_iter;
4056  bool first = true;
4057  for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
4058  if (first) {
4059  first = false;
4060  } else {
4061  result += ", ";
4062  }
4063  result += (*f_iter)->get_name();
4064  }
4065  return result;
4066 }
4067 
4069  t_program* program = ttype->get_program();
4070  if (ttype->is_service()) {
4071  return get_real_py_module(program, gen_twisted_) + "." + ttype->get_name();
4072  }
4073  if (program != NULL && program != program_) {
4074  return get_real_py_module(program, gen_twisted_) + "_ttypes." + ttype->get_name();
4075  }
4076  return ttype->get_name();
4077 }
4078 
4083  type = get_true_type(type);
4084 
4085  if (type->is_base_type()) {
4086  t_base_type::t_base tbase = ((t_base_type*)type)->get_base();
4087  switch (tbase) {
4089  throw "NO T_VOID CONSTRUCT";
4091  return "TType.STRING";
4093  return "TType.BOOL";
4095  return "TType.BYTE";
4096  case t_base_type::TYPE_I16:
4097  return "TType.I16";
4098  case t_base_type::TYPE_I32:
4099  return "TType.I32";
4100  case t_base_type::TYPE_I64:
4101  return "TType.I64";
4103  return "TType.DOUBLE";
4104 #ifdef SANDESH
4105  case t_base_type::TYPE_XML:
4106  return "TType.XML";
4107  case t_base_type::TYPE_UUID:
4108  return "TType.UUID";
4109  case t_base_type::TYPE_U16:
4110  return "TType.U16";
4111  case t_base_type::TYPE_U32:
4112  return "TType.U32";
4113  case t_base_type::TYPE_U64:
4114  return "TType.U64";
4115  case t_base_type::TYPE_IPV4:
4116  return "TType.IPV4";
4117  case t_base_type::TYPE_IPADDR:
4118  return "TType.IPADDR";
4119  case t_base_type::TYPE_STATIC_CONST_STRING:
4120  return "TType.STRING";
4121  case t_base_type::TYPE_SANDESH_SYSTEM:
4122  return "TType.STRING";
4123  case t_base_type::TYPE_SANDESH_REQUEST:
4124  return "TType.STRING";
4125  case t_base_type::TYPE_SANDESH_RESPONSE:
4126  return "TType.STRING";
4127  case t_base_type::TYPE_SANDESH_TRACE:
4128  return "TType.STRING";
4129  case t_base_type::TYPE_SANDESH_TRACE_OBJECT:
4130  return "TType.STRING";
4131  case t_base_type::TYPE_SANDESH_BUFFER:
4132  return "TTytpe.STRING";
4133  case t_base_type::TYPE_SANDESH_UVE:
4134  return "TTytpe.STRING";
4135  case t_base_type::TYPE_SANDESH_DYNAMIC_UVE:
4136  return "TTytpe.STRING";
4137  case t_base_type::TYPE_SANDESH_ALARM:
4138  return "TTytpe.STRING";
4139  case t_base_type::TYPE_SANDESH_OBJECT:
4140  return "TTytpe.STRING";
4141  case t_base_type::TYPE_SANDESH_FLOW:
4142  return "TTytpe.STRING";
4143  case t_base_type::TYPE_SANDESH_SESSION:
4144  return "TTytpe.STRING";
4145 #endif
4146  }
4147  } else if (type->is_enum()) {
4148  return "TType.I32";
4149  } else if (type->is_struct() || type->is_xception()) {
4150  return "TType.STRUCT";
4151 #ifdef SANDESH
4152  } else if (type->is_sandesh()) {
4153  return "TType.SANDESH";
4154 #endif
4155  } else if (type->is_map()) {
4156  return "TType.MAP";
4157  } else if (type->is_set()) {
4158  return "TType.SET";
4159  } else if (type->is_list()) {
4160  return "TType.LIST";
4161  }
4162 
4163  throw "INVALID TYPE IN type_to_enum: " + type->get_name();
4164 }
4165 
4168  while (ttype->is_typedef()) {
4169  ttype = ((t_typedef*)ttype)->get_type();
4170  }
4171 
4172  if (ttype->is_base_type() || ttype->is_enum()) {
4173  return "None";
4174  } else if (ttype->is_struct() || ttype->is_xception()) {
4175  return "(" + type_name(ttype) + ", " + type_name(ttype) + ".thrift_spec)";
4176  } else if (ttype->is_map()) {
4177  return "(" +
4178  type_to_enum(((t_map*)ttype)->get_key_type()) + "," +
4179  type_to_spec_args(((t_map*)ttype)->get_key_type()) + "," +
4180  type_to_enum(((t_map*)ttype)->get_val_type()) + "," +
4181  type_to_spec_args(((t_map*)ttype)->get_val_type()) +
4182  ")";
4183 
4184  } else if (ttype->is_set()) {
4185  return "(" +
4186  type_to_enum(((t_set*)ttype)->get_elem_type()) + "," +
4187  type_to_spec_args(((t_set*)ttype)->get_elem_type()) +
4188  ")";
4189 
4190  } else if (ttype->is_list()) {
4191  return "(" +
4192  type_to_enum(((t_list*)ttype)->get_elem_type()) + "," +
4193  type_to_spec_args(((t_list*)ttype)->get_elem_type()) +
4194  ")";
4195  }
4196 
4197  throw "INVALID TYPE IN type_to_spec_args: " + ttype->get_name();
4198 }
4199 
4200 
4201 THRIFT_REGISTER_GENERATOR(py, "Python",
4202 " new_style: Generate new-style classes.\n" \
4203 " twisted: Generate Twisted-friendly RPC services.\n" \
4204 " utf8strings: Encode/decode strings using utf8 in the generated code.\n" \
4205 " slots: Generate code using slots for instance members.\n" \
4206 " dynamic: Generate dynamic code, less code generated but slower.\n" \
4207 " dynbase=CLS Derive generated classes from class CLS instead of TBase.\n" \
4208 " dynexc=CLS Derive generated exceptions from CLS instead of TExceptionBase.\n" \
4209 " dynimport='from foo.bar import CLS'\n" \
4210 " Add an import line to generated code to find the dynbase class.\n")
std::string indent()
Definition: t_generator.h:181
virtual bool is_xception() const
Definition: t_type.h:74
const std::string & get_name() const
Definition: t_field.h:95
std::string type_name(t_type *ttype)
void generate_serialize_set_element(std::ofstream &out, t_set *tmap, std::string iter)
static bool is_valid_namespace(const std::string &sub_namespace)
void init()
Definition: bgp_log.cc:37
std::string tmp(std::string name)
Definition: t_generator.h:160
Definition: t_enum.h:30
bool has_doc()
Definition: t_doc.h:41
t_program * program_
Definition: t_generator.h:276
void generate_deserialize_map_element(std::ofstream &out, t_map *tmap, std::string prefix="")
void generate_py_struct_definition(std::ofstream &out, t_struct *tstruct, bool is_xception=false, bool is_result=false)
void generate_service(t_service *tservice)
Definition: t_type.h:48
std::string future_imports()
static std::string t_base_name(t_base tbase)
Definition: t_base_type.h:218
const std::string & get_name() const
Definition: t_function.h:91
const uint32_t get_4byte_fingerprint() const
Definition: t_type.h:139
std::string type_to_spec_args(t_type *ttype)
std::string package_dir_
virtual bool is_map() const
Definition: t_type.h:78
const std::string & get_name() const
Definition: t_program.h:92
void generate_deserialize_list_element(std::ofstream &out, t_list *tlist, std::string prefix="")
void indent_down()
Definition: t_generator.h:174
void generate_deserialize_field(std::ofstream &out, t_field *tfield, std::string prefix="", bool inclass=false)
std::string type_to_enum(t_type *ttype)
const members_type & get_sorted_members()
virtual bool is_enum() const
Definition: t_type.h:72
t_type * get_type() const
Definition: t_field.h:91
virtual bool is_base_type() const
Definition: t_type.h:61
void generate_py_struct_required_validator(std::ofstream &out, t_struct *tstruct)
void generate_service_helpers(t_service *tservice)
void generate_python_docstring(std::ofstream &out, t_struct *tstruct)
std::string gen_dynbaseclass_
t_py_generator(t_program *program, const std::map< std::string, std::string > &parsed_options, const std::string &option_string)
t_type * get_returntype() const
Definition: t_function.h:87
const std::map< t_const_value *, t_const_value * > & get_map() const
const members_type & get_members()
std::string py_imports()
int64_t get_integer() const
Definition: t_const_value.h:72
t_type * get_key_type() const
Definition: t_map.h:36
void generate_py_function_helpers(t_function *tfunction)
std::string service_name_
Definition: t_generator.h:288
t_const_value_type get_type() const
void generate_service_interface(t_service *tservice)
virtual bool is_container() const
Definition: t_type.h:75
void generate_serialize_map_element(std::ofstream &out, t_map *tmap, std::string kiter, std::string viter)
virtual bool is_typedef() const
Definition: t_type.h:71
t_type * get_type() const
Definition: t_const.h:40
#define MKDIR(x)
Definition: platform.h:28
uint8_t type
Definition: load_balance.h:109
t_struct * get_xceptions() const
Definition: t_function.h:99
t_type * get_elem_type() const
Definition: t_set.h:34
Definition: t_doc.h:27
void generate_deserialize_container(std::ofstream &out, t_type *ttype, std::string prefix="")
void generate_struct(t_struct *tstruct)
void generate_service_server(t_service *tservice)
virtual bool is_set() const
Definition: t_type.h:77
void generate_deserialize_set_element(std::ofstream &out, t_set *tset, std::string prefix="")
std::string gen_dynbaseclass_exc_
std::string get_name() const
Definition: t_const.h:44
std::ofstream f_types_
void generate_serialize_field(std::ofstream &out, t_field *tfield, std::string prefix="")
virtual bool is_void() const
Definition: t_type.h:60
void generate_typedef(t_typedef *ttypedef)
std::ofstream f_service_
t_const_value * get_value() const
Definition: t_const.h:48
void generate_deserialize_struct(std::ofstream &out, t_struct *tstruct, std::string prefix="")
t_type * get_elem_type() const
Definition: t_list.h:34
e_req get_req() const
Definition: t_field.h:113
int32_t get_key() const
Definition: t_field.h:99
void generate_xception(t_struct *txception)
t_type * get_val_type() const
Definition: t_map.h:40
std::string argument_list(t_struct *tstruct)
t_base get_base() const
Definition: t_base_type.h:81
void generate_process_function(t_service *tservice, t_function *tfunction)
const std::vector< t_function * > & get_functions() const
Definition: t_service.h:56
std::string copy_options_
void generate_service_client(t_service *tservice)
virtual const std::string & get_name() const
Definition: t_type.h:56
std::string declare_argument(t_field *tfield)
Definition: t_map.h:30
virtual bool is_list() const
Definition: t_type.h:76
virtual bool has_key_annotation() const
const std::vector< t_enum_value * > & get_constants()
Definition: t_enum.h:43
void generate_serialize_struct(std::ofstream &out, t_struct *tstruct, std::string prefix="")
std::string get_string() const
Definition: t_const_value.h:63
static t_type * get_true_type(t_type *type)
Definition: t_generator.h:268
double get_double() const
Definition: t_const_value.h:99
const std::string & get_namespace() const
Definition: t_program.h:95
std::ofstream f_consts_
t_program * get_program()
Definition: t_type.h:81
virtual bool is_struct() const
Definition: t_type.h:73
t_service * get_extends()
Definition: t_service.h:60
void generate_serialize_list_element(std::ofstream &out, t_list *tlist, std::string iter)
Definition: t_set.h:29
const std::string & get_doc() const
Definition: t_doc.h:37
const t_type * get_type()
Definition: t_sandesh.h:71
std::string function_signature(t_function *tfunction, std::string prefix="")
void generate_py_struct_reader(std::ofstream &out, t_struct *tstruct)
void indent_up()
Definition: t_generator.h:170
std::string render_field_default_value(t_field *tfield)
std::string import_dynbase_
void generate_service_remote(t_service *tservice)
Definition: t_list.h:29
std::string function_signature_if(t_function *tfunction, std::string prefix="")
std::string render_fastbinary_includes()
std::string render_includes()
#define SANDESH_VERSION
Definition: version.h:1
t_const_value * get_value()
Definition: t_field.h:121
void generate_docstring_comment(std::ofstream &out, const std::string &comment_start, const std::string &line_prefix, const std::string &contents, const std::string &comment_end)
Definition: t_generator.cc:107
static std::string get_real_py_module(const t_program *program, bool gen_twisted)
std::string render_const_value(t_type *type, t_const_value *value)
std::string py_autogen_comment()
void generate_enum(t_enum *tenum)
virtual bool is_service() const
Definition: t_type.h:79
void generate_serialize_container(std::ofstream &out, t_type *ttype, std::string prefix="")
void generate_py_struct(t_struct *tstruct, bool is_exception)
void generate_const(t_const *tconst)
void generate_py_struct_writer(std::ofstream &out, t_struct *tstruct)
bool is_oneway() const
Definition: t_function.h:103
#define THRIFT_REGISTER_GENERATOR(language, long_name, doc)
const std::vector< t_const_value * > & get_list() const
t_struct * get_arglist() const
Definition: t_function.h:95