def srv_generator(msg_context, spec, search_path): for mspec in (spec.request, spec.response): for l in msg_generator(msg_context, mspec, search_path): yield l name = spec.short_name req, resp = ["%s%s"%(name, suff) for suff in ['Request', 'Response']] fulltype = spec.full_name genmsg.msg_loader.load_depends(msg_context, spec, search_path) md5 = genmsg.compute_md5(msg_context, spec) yield "module %s\n"%spec.package.capitalize() yield "class %s\n"%name yield """ def self.type '%s' end """%fulltype yield """ def self.md5sum '%s' end """%md5 yield """ def self.request_class %s end """%req yield """ def self.response_class %s end end end"""%resp
def __init__(self, msg_context, spec, search_path): self.msg_context = msg_context self.spec = spec self.search_path = search_path self.name = spec.short_name self.pkg = spec.package self.md5 = genmsg.compute_md5(msg_context, spec)
def srv_generator(msg_context, spec, search_path): for mspec in (spec.request, spec.response): for l in msg_generator(msg_context, mspec, search_path): yield l name = spec.short_name req, resp = ["%s%s" % (name, suff) for suff in ['Request', 'Response']] fulltype = spec.full_name genmsg.msg_loader.load_depends(msg_context, spec, search_path) md5 = genmsg.compute_md5(msg_context, spec) yield "module %s\n" % spec.package.capitalize() yield "class %s\n" % name yield """ def self.type '%s' end """ % fulltype yield """ def self.md5sum '%s' end """ % md5 yield """ def self.request_class %s end """ % req yield """ def self.response_class %s end end end""" % resp
def _compute_md5(msg_context, f): from genmsg import load_depends, compute_md5 from genmsg.msg_loader import load_msg_from_string text = open(f, 'r').read() short_name = os.path.basename(f)[:-len('.msg')] full_name = "%s/%s"%(TEST_CTX, short_name) spec = load_msg_from_string(msg_context, text, full_name) search_path = get_search_path() load_depends(msg_context, spec, search_path) return compute_md5(msg_context, spec)
def _compute_md5(msg_context, f): from genmsg import load_depends, compute_md5 from genmsg.msg_loader import load_msg_from_string text = open(f, 'r').read() short_name = os.path.basename(f)[:-len('.msg')] full_name = "%s/%s" % (TEST_CTX, short_name) spec = load_msg_from_string(msg_context, text, full_name) search_path = get_search_path() load_depends(msg_context, spec, search_path) return compute_md5(msg_context, spec)
def srv_generator(msg_context, spec, search_path): for mspec in (spec.request, spec.response): for l in msg_generator(msg_context, mspec, search_path): yield l name = spec.short_name req, resp = ["%s%s"%(name, suff) for suff in ['Request', 'Response']] fulltype = spec.full_name genmsg.msg_loader.load_depends(msg_context, spec, search_path) md5 = genmsg.compute_md5(msg_context, spec) yield "class %s(object):"%name yield " _type = '%s'"%fulltype yield " _md5sum = '%s'"%md5 yield " _request_class = %s"%req yield " _response_class = %s"%resp
def srv_generator(msg_context, spec, search_path): for mspec in (spec.request, spec.response): for l in msg_generator(msg_context, mspec, search_path): yield l name = spec.short_name req, resp = ["%s%s" % (name, suff) for suff in ["Request", "Response"]] fulltype = spec.full_name genmsg.msg_loader.load_depends(msg_context, spec, search_path) md5 = genmsg.compute_md5(msg_context, spec) yield "class %s(object):" % name yield " _type = '%s'" % fulltype yield " _md5sum = '%s'" % md5 yield " _request_class = %s" % req yield " _response_class = %s" % resp
def msg_generator(msg_context, spec, search_path): """ Python code generator for .msg files. Generates a Python from a :class:`genmsg.MsgSpec`. :param spec: parsed .msg :class:`genmsg.MsgSpec` instance :param search_path: dictionary mapping message namespaces to a directory locations """ # #2990: have to compute md5sum before any calls to make_python_safe # generate dependencies dictionary. omit files calculation as we # rely on in-memory MsgSpecs instead so that we can generate code # for older versions of msg files try: genmsg.msg_loader.load_depends(msg_context, spec, search_path) except InvalidMsgSpec as e: raise MsgGenerationException("Cannot generate .msg for %s/%s: %s"%(package, name, str(e))) md5sum = genmsg.compute_md5(msg_context, spec) # remap spec names to be Python-safe spec = make_python_safe(spec) spec_names = spec.names # #1807 : this will be much cleaner when msggenerator library is # rewritten to not use globals clear_patterns() yield '# This Python file uses the following encoding: utf-8' yield '"""autogenerated by genpy from %s.msg. Do not edit."""'%spec.full_name yield 'import sys' yield 'python3 = True if sys.hexversion > 0x03000000 else False' yield 'import genpy\nimport struct\n' import_strs = [] for t in spec.types: import_strs.extend(compute_import(msg_context, spec.package, t)) import_strs = set(import_strs) for i in import_strs: if i: yield i yield '' fulltype = spec.full_name name = spec.short_name #Yield data class first, e.g. Point2D yield 'class %s(genpy.Message):'%spec.short_name yield ' _md5sum = "%s"'%(md5sum) yield ' _type = "%s"'%(fulltype) yield ' _has_header = %s #flag to mark the presence of a Header object'%spec.has_header() full_text = compute_full_text_escaped(msg_context, spec) # escape trailing double-quote, unless already escaped, before wrapping in """ if full_text.endswith('"') and not full_text.endswith(r'\"'): full_text = full_text[:-1] + r'\"' yield ' _full_text = """%s"""'%full_text if spec.constants: yield ' # Pseudo-constants' for c in spec.constants: if c.type == 'string': val = c.val if '"' in val and "'" in val: # crude escaping of \ and " escaped = c.val.replace('\\', '\\\\') escaped = escaped.replace('\"', '\\"') yield ' %s = "%s"'%(c.name, escaped) elif '"' in val: #use raw encoding for prettiness yield " %s = r'%s'"%(c.name, val) elif "'" in val: #use raw encoding for prettiness yield ' %s = r"%s"'%(c.name, val) else: yield " %s = '%s'"%(c.name, val) else: yield ' %s = %s'%(c.name, c.val) yield '' if len(spec_names): yield " __slots__ = ['"+"','".join(spec_names)+"']" yield " _slot_types = ['"+"','".join(spec.types)+"']" else: yield " __slots__ = []" yield " _slot_types = []" yield """ def __init__(self, *args, **kwds): \"\"\" Constructor. Any message fields that are implicitly/explicitly set to None will be assigned a default value. The recommend use is keyword arguments as this is more robust to future message changes. You cannot mix in-order arguments and keyword arguments. The available fields are: %s :param args: complete set of field values, in .msg order :param kwds: use keyword arguments corresponding to message field names to set specific fields. \"\"\" if args or kwds: super(%s, self).__init__(*args, **kwds)"""%(','.join(spec_names), name) if len(spec_names): yield " #message fields cannot be None, assign default values for those that are" for (t, s) in zip(spec.types, spec_names): yield " if self.%s is None:"%s yield " self.%s = %s"%(s, default_value(msg_context, t, spec.package)) if len(spec_names) > 0: yield " else:" for (t, s) in zip(spec.types, spec_names): yield " self.%s = %s"%(s, default_value(msg_context, t, spec.package)) yield """ def _get_types(self): \"\"\" internal API method \"\"\" return self._slot_types def serialize(self, buff): \"\"\" serialize message into buffer :param buff: buffer, ``StringIO`` \"\"\"""" for y in serialize_fn_generator(msg_context, spec): yield " "+ y yield """ def deserialize(self, str): \"\"\" unpack serialized message in str into this message instance :param str: byte array of serialized message, ``str`` \"\"\"""" for y in deserialize_fn_generator(msg_context, spec): yield " " + y yield "" yield """ def serialize_numpy(self, buff, numpy): \"\"\" serialize message with numpy array types into buffer :param buff: buffer, ``StringIO`` :param numpy: numpy python module \"\"\"""" for y in serialize_fn_generator(msg_context, spec, is_numpy=True): yield " "+ y yield """ def deserialize_numpy(self, str, numpy): \"\"\" unpack serialized message in str into this message instance using numpy for array types :param str: byte array of serialized message, ``str`` :param numpy: numpy python module \"\"\"""" for y in deserialize_fn_generator(msg_context, spec, is_numpy=True): yield " " + y yield "" # #1807 : this will be much cleaner when msggenerator library is # rewritten to not use globals yield '_struct_I = genpy.struct_I' yield 'def _get_struct_I():' yield ' global _struct_I' yield ' return _struct_I' patterns = get_patterns() for p in set(patterns): # I patterns are already optimized if p == 'I': continue var_name = '_struct_%s'%(p.replace('<','')) yield '%s = None' % var_name yield 'def _get%s():' % var_name yield ' global %s' % var_name yield ' if %s is None:' % var_name yield ' %s = struct.Struct("<%s")' % (var_name, p) yield ' return %s' % var_name clear_patterns()
def msg_generator(msg_context, spec, search_path): """ Python code generator for .msg files. Generates a Python from a :class:`genmsg.MsgSpec`. :param spec: parsed .msg :class:`genmsg.MsgSpec` instance :param search_path: dictionary mapping message namespaces to a directory locations """ # #2990: have to compute md5sum before any calls to make_python_safe # generate dependencies dictionary. omit files calculation as we # rely on in-memory MsgSpecs instead so that we can generate code # for older versions of msg files try: genmsg.msg_loader.load_depends(msg_context, spec, search_path) except InvalidMsgSpec as e: raise MsgGenerationException("Cannot generate .msg for %s/%s: %s" % (package, name, str(e))) md5sum = genmsg.compute_md5(msg_context, spec) # remap spec names to be Python-safe spec = make_python_safe(spec) spec_names = spec.names # #1807 : this will be much cleaner when msggenerator library is # rewritten to not use globals clear_patterns() yield '"""autogenerated by genpy from %s.msg. Do not edit."""' % spec.full_name yield "import sys" yield "python3 = True if sys.hexversion > 0x03000000 else False" yield "import genpy\nimport struct\n" import_strs = [] for t in spec.types: import_strs.extend(compute_import(msg_context, spec.package, t)) import_strs = set(import_strs) for i in import_strs: if i: yield i yield "" fulltype = spec.full_name name = spec.short_name # Yield data class first, e.g. Point2D yield "class %s(genpy.Message):" % spec.short_name yield ' _md5sum = "%s"' % (md5sum) yield ' _type = "%s"' % (fulltype) yield " _has_header = %s #flag to mark the presence of a Header object" % spec.has_header() # note: we introduce an extra newline to protect the escaping from quotes in the message yield ' _full_text = """%s\n"""' % compute_full_text_escaped(msg_context, spec) if spec.constants: yield " # Pseudo-constants" for c in spec.constants: if c.type == "string": val = c.val if '"' in val and "'" in val: # crude escaping of \ and " escaped = c.val.replace("\\", "\\\\") escaped = escaped.replace('"', '\\"') yield ' %s = "%s"' % (c.name, escaped) elif '"' in val: # use raw encoding for prettiness yield " %s = r'%s'" % (c.name, val) elif "'" in val: # use raw encoding for prettiness yield ' %s = r"%s"' % (c.name, val) else: yield " %s = '%s'" % (c.name, val) else: yield " %s = %s" % (c.name, c.val) yield "" if len(spec_names): yield " __slots__ = ['" + "','".join(spec_names) + "']" yield " _slot_types = ['" + "','".join(spec.types) + "']" else: yield " __slots__ = []" yield " _slot_types = []" yield """ def __init__(self, *args, **kwds): \"\"\" Constructor. Any message fields that are implicitly/explicitly set to None will be assigned a default value. The recommend use is keyword arguments as this is more robust to future message changes. You cannot mix in-order arguments and keyword arguments. The available fields are: %s :param args: complete set of field values, in .msg order :param kwds: use keyword arguments corresponding to message field names to set specific fields. \"\"\" if args or kwds: super(%s, self).__init__(*args, **kwds)""" % ( ",".join(spec_names), name, ) if len(spec_names): yield " #message fields cannot be None, assign default values for those that are" for (t, s) in zip(spec.types, spec_names): yield " if self.%s is None:" % s yield " self.%s = %s" % (s, default_value(msg_context, t, spec.package)) if len(spec_names) > 0: yield " else:" for (t, s) in zip(spec.types, spec_names): yield " self.%s = %s" % (s, default_value(msg_context, t, spec.package)) yield """ def _get_types(self): \"\"\" internal API method \"\"\" return self._slot_types def serialize(self, buff): \"\"\" serialize message into buffer :param buff: buffer, ``StringIO`` \"\"\"""" for y in serialize_fn_generator(msg_context, spec): yield " " + y yield """ def deserialize(self, str): \"\"\" unpack serialized message in str into this message instance :param str: byte array of serialized message, ``str`` \"\"\"""" for y in deserialize_fn_generator(msg_context, spec): yield " " + y yield "" yield """ def serialize_numpy(self, buff, numpy): \"\"\" serialize message with numpy array types into buffer :param buff: buffer, ``StringIO`` :param numpy: numpy python module \"\"\"""" for y in serialize_fn_generator(msg_context, spec, is_numpy=True): yield " " + y yield """ def deserialize_numpy(self, str, numpy): \"\"\" unpack serialized message in str into this message instance using numpy for array types :param str: byte array of serialized message, ``str`` :param numpy: numpy python module \"\"\"""" for y in deserialize_fn_generator(msg_context, spec, is_numpy=True): yield " " + y yield "" # #1807 : this will be much cleaner when msggenerator library is # rewritten to not use globals yield "_struct_I = genpy.struct_I" patterns = get_patterns() for p in set(patterns): # I patterns are already optimized if p == "I": continue var_name = "_struct_%s" % (p.replace("<", "")) yield '%s = struct.Struct("<%s")' % (var_name, p) clear_patterns()
def msg_generator_internal(msg_context, spec, search_path): """ Python code generator for .msg files. Takes in a package name, message name, and message specification and generates a Python message class. @param package: name of package for message @type package: str @param name: base type name of message, e.g. 'Empty', 'String' @type name: str @param spec: parsed .msg specification @type spec: L{MsgSpec} """ # #2990: have to compute md5sum before any calls to make_python_safe # generate dependencies dictionary. omit files calculation as we # rely on in-memory MsgSpecs instead so that we can generate code # for older versions of msg files try: genmsg.msg_loader.load_depends(msg_context, spec, search_path) except InvalidMsgSpec as e: raise MsgGenerationException("Cannot generate .msg for %s/%s: %s"%(package, name, str(e))) md5sum = genmsg.compute_md5(msg_context, spec) # remap spec names to be Python-safe spec = make_ruby_safe(spec) spec_names = spec.names # for not capital class like tfMessages name = spec.short_name capitalized_name = name[0].upper() + name[1:] # #1807 : this will be much cleaner when msggenerator library is # rewritten to not use globals clear_patterns() yield '# autogenerated by genrb from %s.msg. Do not edit.'%name yield "require 'ros/message'\n" import_strs = [] for t in spec.types: import_strs.extend(compute_import(msg_context, spec.package, t)) import_strs = set(import_strs) for i in import_strs: if i: yield i yield '' yield "module %s\n"%spec.package.capitalize() fulltype = '%s%s%s'%(spec.package, genmsg.SEP, name) #Yield data class first, e.g. Point2D yield 'class %s <::ROS::Message'%capitalized_name yield """ def self.md5sum \"%s\" end """%(md5sum) yield """ def self.type \"%s\" end """%(fulltype) if spec.has_header(): bool_val = 'true' else: bool_val = 'false' yield """ def has_header? %s end """%bool_val # note: we introduce an extra newline to protect the escaping from quotes in the message yield """ def message_definition \"%s\n\" end"""%compute_full_text_escaped(msg_context, spec) if spec.constants: yield ' # Pseudo-constants' for c in spec.constants: if c.type == 'string': val = c.val if '"' in val and "'" in val: # crude escaping of \ and " escaped = c.val.replace('\\', '\\\\') escaped = escaped.replace('\"', '\\"') yield ' %s = "%s"'%(c.name, escaped) elif '"' in val: #use raw encoding for prettiness yield " %s = r'%s'"%(c.name, val) elif "'" in val: #use raw encoding for prettiness yield ' %s = r"%s"'%(c.name, val) else: yield " %s = '%s'"%(c.name, val) else: yield ' %s = %s'%(c.name, c.val) yield '' yield " attr_accessor "+", ".join([":"+x for x in spec_names])+"\n" yield '_REPLACE_FOR_STRUCT_' if len(spec_names): yield " @@struct_L = ::ROS::Struct.new(\"L\")" yield " @@slot_types = ['"+"','".join(spec.types)+"']" else: yield " @@struct_L = ::ROS::Struct.new(\"L\")" yield " @@slot_types = []" yield """ # Constructor. You can set the default values using keyword operators. # # @param [Hash] args keyword for initializing values""" for (t, s) in zip(spec.types, spec_names): yield " # @option args [%s] :%s initialize value"%(t, s) yield " def initialize(args={})" if len(spec_names): yield " # message fields cannot be None, assign default values for those that are" if len(spec_names) > 0: for (t, s) in zip(spec.types, spec_names): yield """ if args[:%s] @%s = args[:%s] else"""%(s, s, s) yield " @%s = %s"%(s, default_value(msg_context, t, spec.package)) yield " end" yield " end" # end of initialize yield """ # internal API method # @return [String] Message type string. def _get_types @slot_types end # serialize message into buffer # @param [IO] buff buffer def serialize(buff)""" for y in serialize_fn_generator(msg_context, spec): yield " "+ y yield " end" yield """ # unpack serialized message in str into this message instance # @param [String] str: byte array of serialized message def deserialize(str) """ for y in deserialize_fn_generator(msg_context, spec): yield " " + y yield " end" yield "end # end of class" yield "end # end of module"
def msg_generator_internal(msg_context, spec, search_path): """ Python code generator for .msg files. Takes in a package name, message name, and message specification and generates a Python message class. @param package: name of package for message @type package: str @param name: base type name of message, e.g. 'Empty', 'String' @type name: str @param spec: parsed .msg specification @type spec: L{MsgSpec} """ # #2990: have to compute md5sum before any calls to make_python_safe # generate dependencies dictionary. omit files calculation as we # rely on in-memory MsgSpecs instead so that we can generate code # for older versions of msg files try: genmsg.msg_loader.load_depends(msg_context, spec, search_path) except InvalidMsgSpec as e: raise MsgGenerationException("Cannot generate .msg for %s/%s: %s" % (package, name, str(e))) md5sum = genmsg.compute_md5(msg_context, spec) # remap spec names to be Python-safe spec = make_ruby_safe(spec) spec_names = spec.names # for not capital class like tfMessages name = spec.short_name capitalized_name = name[0].upper() + name[1:] # #1807 : this will be much cleaner when msggenerator library is # rewritten to not use globals clear_patterns() yield '# autogenerated by genrb from %s.msg. Do not edit.' % name yield "require 'ros/message'\n" import_strs = [] for t in spec.types: import_strs.extend(compute_import(msg_context, spec.package, t)) import_strs = set(import_strs) for i in import_strs: if i: yield i yield '' yield "module %s\n" % spec.package.capitalize() fulltype = '%s%s%s' % (spec.package, genmsg.SEP, name) #Yield data class first, e.g. Point2D yield 'class %s <::ROS::Message' % capitalized_name yield """ def self.md5sum \"%s\" end """ % (md5sum) yield """ def self.type \"%s\" end """ % (fulltype) if spec.has_header(): bool_val = 'true' else: bool_val = 'false' yield """ def has_header? %s end """ % bool_val # note: we introduce an extra newline to protect the escaping from quotes in the message yield """ def message_definition \"%s\n\" end""" % compute_full_text_escaped(msg_context, spec) if spec.constants: yield ' # Pseudo-constants' for c in spec.constants: if c.type == 'string': val = c.val if '"' in val and "'" in val: # crude escaping of \ and " escaped = c.val.replace('\\', '\\\\') escaped = escaped.replace('\"', '\\"') yield ' %s = "%s"' % (c.name, escaped) elif '"' in val: #use raw encoding for prettiness yield " %s = r'%s'" % (c.name, val) elif "'" in val: #use raw encoding for prettiness yield ' %s = r"%s"' % (c.name, val) else: yield " %s = '%s'" % (c.name, val) else: yield ' %s = %s' % (c.name, c.val) yield '' yield " attr_accessor " + ", ".join([":" + x for x in spec_names]) + "\n" yield '_REPLACE_FOR_STRUCT_' if len(spec_names): yield " @@struct_L = ::ROS::Struct.new(\"L\")" yield " @@slot_types = ['" + "','".join(spec.types) + "']" else: yield " @@struct_L = ::ROS::Struct.new(\"L\")" yield " @@slot_types = []" yield """ # Constructor. You can set the default values using keyword operators. # # @param [Hash] args keyword for initializing values""" for (t, s) in zip(spec.types, spec_names): yield " # @option args [%s] :%s initialize value" % (t, s) yield " def initialize(args={})" if len(spec_names): yield " # message fields cannot be None, assign default values for those that are" if len(spec_names) > 0: for (t, s) in zip(spec.types, spec_names): yield """ if args[:%s] @%s = args[:%s] else""" % (s, s, s) yield " @%s = %s" % ( s, default_value(msg_context, t, spec.package)) yield " end" yield " end" # end of initialize yield """ # internal API method # @return [String] Message type string. def _get_types @slot_types end # serialize message into buffer # @param [IO] buff buffer def serialize(buff)""" for y in serialize_fn_generator(msg_context, spec): yield " " + y yield " end" yield """ # unpack serialized message in str into this message instance # @param [String] str: byte array of serialized message def deserialize(str) """ for y in deserialize_fn_generator(msg_context, spec): yield " " + y yield " end" yield "end # end of class" yield "end # end of module"