MOBILE = 0; HOME = 1; WORK = 2; } message PhoneNumber { required string number = 1; optional PhoneType type = 2 [default = HOME]; } repeated PhoneNumber phone = 4; extensions 500 to 990; } message AddressBook { repeated Person person = 1; // Possible extension numbers. extensions 500 to max; }""" test4 = '''policy foo <exists foo: foo.x=foo.y>''' parser = plyproto.ProtobufAnalyzer() tests = globals() for t in tests: if t.startswith('test'): print 'parsin %s' % t parser.parse_string(globals()[t])
def generate(args): # Setting defaults if not hasattr(args, 'attic'): args.attic = None if not hasattr(args, 'write_to_file'): args.write_to_file = None if not hasattr(args, 'dest_file'): args.dest_file = None if not hasattr(args, 'dest_extension'): args.dest_extension = None if not hasattr(args, 'output'): args.output = None if not hasattr(args, 'quiet'): args.quiet = True # Validating if args.write_to_file == 'single' and args.dest_file is None: raise Exception( "[XosGenX] write_to_file option is specified as 'single' but no dest_file is provided" ) if args.write_to_file == 'model' and args.dest_extension is None: raise Exception( "[XosGenX] write_to_file option is specified as 'model' but no dest_extension is provided" ) if args.output is not None and not os.path.isabs(args.output): raise Exception( "[XosGenX] The output dir must be an absolute path!") if args.output is not None and not os.path.isdir(args.output): raise Exception("[XosGenX] The output dir must be a directory!") if hasattr(args, 'files'): inputs = XOSGenerator._read_input_from_files(args.files) elif hasattr(args, 'inputs'): inputs = args.inputs else: raise Exception("[XosGenX] No inputs provided!") template_path = XOSGenerator._get_template(args.target) [template_folder, template_name] = os.path.split(template_path) os_template_loader = jinja2.FileSystemLoader( searchpath=[template_folder]) os_template_env = jinja2.Environment(loader=os_template_loader) os_template_env = XOSGenerator._load_jinja2_extensions( os_template_env, args.attic) template = os_template_env.get_template(template_name) context = XOSGenerator._add_context(args) parser = plyxproto.ProtobufAnalyzer() ast = parser.parse_string(inputs, debug=0) v = XOSGenerator._attach_parser(ast, args) if args.output is not None and args.write_to_file == "model": rendered = {} for i, model in enumerate(v.models): models = {} models[model] = v.models[model] messages = [ XOSGenerator._find_message_by_model_name( v.messages, model) ] rendered[model] = template.render({ "proto": { 'message_table': models, 'messages': messages, 'policies': v.policies, 'message_names': [m['name'] for m in messages] }, "context": context, "options": v.options }) XOSGenerator._write_file_per_model(rendered, args.output, args.dest_extension, args.quiet) else: rendered = template.render({ "proto": { 'message_table': v.models, 'messages': v.messages, 'policies': v.policies, 'message_names': [m['name'] for m in v.messages] }, "context": context, "options": v.options }) if args.output is not None and args.write_to_file == "target": XOSGenerator._write_split_target(rendered, args.output, args.quiet) elif args.output is not None and args.write_to_file == "single": XOSGenerator._write_single_file(rendered, args.output, args.dest_file, args.quiet) return rendered
def process(args, operator=None): # Setting defaults if not hasattr(args, "attic"): args.attic = None if not hasattr(args, "write_to_file"): args.write_to_file = None if not hasattr(args, "dest_file"): args.dest_file = None if not hasattr(args, "dest_extension"): args.dest_extension = None if not hasattr(args, "output"): args.output = None if not hasattr(args, "quiet"): args.quiet = True # Validating if args.write_to_file == "single" and args.dest_file is None: raise Exception( "[XosGenX] write_to_file option is specified as 'single' but no dest_file is provided" ) if args.write_to_file == "model" and (args.dest_extension is None): raise Exception( "[XosGenX] write_to_file option is specified as 'model' but no dest_extension is provided" ) if args.output is not None and not os.path.isabs(args.output): raise Exception( "[XosGenX] The output dir must be an absolute path!") if args.output is not None and not os.path.isdir(args.output): raise Exception("[XosGenX] The output dir must be a directory!") if hasattr(args, "files"): inputs = XOSProcessor._read_input_from_files(args.files) elif hasattr(args, "inputs"): inputs = args.inputs else: raise Exception("[XosGenX] No inputs provided!") if not operator: operator = args.target template_path = XOSProcessor._get_template(operator) else: template_path = operator [template_folder, template_name] = os.path.split(template_path) os_template_loader = jinja2.FileSystemLoader( searchpath=[template_folder]) os_template_env = jinja2.Environment(loader=os_template_loader) os_template_env = XOSProcessor._load_jinja2_extensions( os_template_env, args.attic) template = os_template_env.get_template(template_name) context = XOSProcessor._add_context(args) parser = plyxproto.ProtobufAnalyzer() try: ast = parser.parse_string(inputs, debug=0) except plyxproto.ParsingError as e: line, start, end = e.error_range ptr = XOSProcessor._find_last_nonempty_line(inputs, start) if start == 0: beginning = "" else: beginning = inputs[ptr:start - 1] line_end_char = inputs[start + end:].find("\n") line_end = inputs[line_end_char] if e.message: error = e.message else: error = "xproto parsing error" print(error + "\n" + Fore.YELLOW + "Line %d:" % line + Fore.WHITE) print(beginning + Fore.YELLOW + inputs[start - 1:start + end] + Fore.WHITE + line_end) exit(1) v = XOSProcessor._attach_parser(ast, args) if args.include_models or args.include_apps: for message in v.messages: message["is_included"] = False if message["name"] in args.include_models: message["is_included"] = True else: app_label = message.get("options", {}).get("app_label").strip('"') if app_label in args.include_apps: message["is_included"] = True else: for message in v.messages: message["is_included"] = True if args.output is not None and args.write_to_file == "model": rendered = {} for i, model in enumerate(v.models): models = {} models[model] = v.models[model] messages = [ XOSProcessor._find_message_by_model_name( v.messages, model) ] rendered[model] = template.render({ "proto": { "message_table": models, "messages": messages, "policies": v.policies, "message_names": [m["name"] for m in v.messages], }, "context": context, "options": v.options, }) if str(v.options.get("legacy", "false")).strip('"').lower() == "true": suffix = "_decl." + args.dest_extension else: suffix = "." + args.dest_extension XOSProcessor._write_file_per_model(rendered, args.output, suffix, args.quiet) else: rendered = template.render({ "proto": { "message_table": v.models, "messages": v.messages, "policies": v.policies, "message_names": [m["name"] for m in v.messages], }, "context": context, "options": v.options, }) if args.output is not None and args.write_to_file == "target": XOSProcessor._write_split_target(rendered, args.output, args.quiet) elif args.output is not None and args.write_to_file == "single": XOSProcessor._write_single_file(rendered, args.output, args.dest_file, args.quiet) return rendered
def process(args, operator=None): # Setting defaults if not hasattr(args, 'attic'): args.attic = None if not hasattr(args, 'write_to_file'): args.write_to_file = None if not hasattr(args, 'dest_file'): args.dest_file = None if not hasattr(args, 'dest_extension'): args.dest_extension = None if not hasattr(args, 'output'): args.output = None if not hasattr(args, 'quiet'): args.quiet = True # Validating if args.write_to_file == 'single' and args.dest_file is None: raise Exception( "[XosGenX] write_to_file option is specified as 'single' but no dest_file is provided" ) if args.write_to_file == 'model' and (args.dest_extension is None): raise Exception( "[XosGenX] write_to_file option is specified as 'model' but no dest_extension is provided" ) if args.output is not None and not os.path.isabs(args.output): raise Exception( "[XosGenX] The output dir must be an absolute path!") if args.output is not None and not os.path.isdir(args.output): raise Exception("[XosGenX] The output dir must be a directory!") if hasattr(args, 'files'): inputs = XOSProcessor._read_input_from_files(args.files) elif hasattr(args, 'inputs'): inputs = args.inputs else: raise Exception("[XosGenX] No inputs provided!") if not operator: operator = args.target template_path = XOSProcessor._get_template(operator) else: template_path = operator [template_folder, template_name] = os.path.split(template_path) os_template_loader = jinja2.FileSystemLoader( searchpath=[template_folder]) os_template_env = jinja2.Environment(loader=os_template_loader) os_template_env = XOSProcessor._load_jinja2_extensions( os_template_env, args.attic) template = os_template_env.get_template(template_name) context = XOSProcessor._add_context(args) parser = plyxproto.ProtobufAnalyzer() try: ast = parser.parse_string(inputs, debug=0) except plyxproto.ParsingError, e: line, start, end = e.error_range ptr = XOSProcessor._find_last_nonempty_line(inputs, start) if start == 0: beginning = '' else: beginning = inputs[ptr:start - 1] line_end_char = inputs[start + end:].find('\n') line_end = inputs[line_end_char] if e.message: error = e.message else: error = "xproto parsing error" print error + "\n" + Fore.YELLOW + "Line %d:" % line + Fore.WHITE print beginning + Fore.YELLOW + inputs[start - 1:start + end] + Fore.WHITE + line_end exit(1)
def process(args, operator=None): # Setting defaults if not hasattr(args, "attic"): args.attic = None if not hasattr(args, "write_to_file"): args.write_to_file = None if not hasattr(args, "dest_file"): args.dest_file = None if not hasattr(args, "dest_extension"): args.dest_extension = None if not hasattr(args, "output"): args.output = None if not hasattr(args, "quiet"): args.quiet = True # Validating if args.write_to_file == "single" and args.dest_file is None: raise Exception( "[XosGenX] write_to_file option is specified as 'single' but no dest_file is provided" ) if args.write_to_file == "model" and (args.dest_extension is None): raise Exception( "[XosGenX] write_to_file option is specified as 'model' but no dest_extension is provided" ) if args.output is not None and not os.path.isabs(args.output): raise Exception( "[XosGenX] The output dir (%s) must be an absolute path!" % args.output) if args.output is not None and not os.path.isdir(args.output): raise Exception( "[XosGenX] The output dir (%s) must be a directory!" % args.output) if hasattr(args, "files"): (inputs, line_map) = XOSProcessor._read_input_from_files(args.files) elif hasattr(args, "inputs"): inputs = args.inputs line_map = [] else: raise Exception("[XosGenX] No inputs provided!") context = XOSProcessor._add_context(args) parser = plyxproto.ProtobufAnalyzer() try: ast = parser.parse_string(inputs, debug=0) except plyxproto.ParsingError as e: if e.message: error = e.message else: error = "xproto parsing error" if e.error_range is None: # No line number information print(error + "\n") else: line, start, end = e.error_range ptr = XOSProcessor._find_last_nonempty_line(inputs, start) if start == 0: beginning = "" else: beginning = inputs[ptr:start - 1] line_end_char = inputs[start + end:].find("\n") line_end = inputs[line_end_char] print(error + "\n" + Fore.YELLOW + "Line %d:" % line + Fore.WHITE) print(beginning + Fore.YELLOW + inputs[start - 1:start + end] + Fore.WHITE + line_end) exit(1) v = XOSProcessor._attach_parser(ast, args) if args.include_models or args.include_apps: for message in v.messages: message["is_included"] = False if message["name"] in args.include_models: message["is_included"] = True else: app_label = (message.get("options", {}).get("app_label").strip('"')) if app_label in args.include_apps: message["is_included"] = True else: for message in v.messages: message["is_included"] = True validator = XProtoValidator(v.models, line_map) validator.validate() if validator.errors: if args.strict_validation or (args.verbosity >= 0): validator.print_errors() fatal_errors = [ x for x in validator.errors if x["severity"] == "ERROR" ] if fatal_errors and args.strict_validation: sys.exit(-1) if args.lint: return "" if not operator: operator = args.target template_path = XOSProcessor._get_template(operator) else: template_path = operator [template_folder, template_name] = os.path.split(template_path) os_template_loader = jinja2.FileSystemLoader( searchpath=[template_folder]) os_template_env = jinja2.Environment(loader=os_template_loader) os_template_env = XOSProcessor._load_jinja2_extensions( os_template_env, args.attic) template = os_template_env.get_template(template_name) if args.output is not None and args.write_to_file == "model": # Handle the case where each model is written to a separate python file. rendered = {} for i, model in enumerate(v.models): model_dict = v.models[model] messages = [ XOSProcessor._find_message_by_model_name( v.messages, model) ] rendered[model] = template.render({ "proto": { "message_table": { model: model_dict }, "messages": messages, "policies": v.policies, "message_names": [m["name"] for m in v.messages], }, "context": context, "options": v.options, }) if not rendered[model]: print("Not saving model %s as it is empty" % model, file=sys.stderr) else: legacy = jinja2_extensions.base.xproto_list_evaluates_true( [ model_dict.get("options", {}).get("custom_python", None), model_dict.get("options", {}).get("legacy", None), v.options.get("custom_python", None), v.options.get("legacy", None) ]) if legacy: file_name = "%s/%s_decl.%s" % ( args.output, model.lower(), args.dest_extension) else: file_name = "%s/%s.%s" % (args.output, model.lower(), args.dest_extension) file = open(file_name, "w") file.write(rendered[model]) file.close() if not args.quiet: print("Saved: %s" % file_name, file=sys.stderr) else: # Handle the case where all models are written to the same python file. rendered = template.render({ "proto": { "message_table": v.models, "messages": v.messages, "policies": v.policies, "message_names": [m["name"] for m in v.messages], }, "context": context, "options": v.options, }) if args.output is not None and args.write_to_file == "target": XOSProcessor._write_split_target(rendered, args.output, args.quiet) elif args.output is not None and args.write_to_file == "single": XOSProcessor._write_single_file(rendered, args.output, args.dest_file, args.quiet) return rendered