Making makerule.py mirror user interaction of checkbag.py

This commit is contained in:
Jeremy Leibs 2009-09-23 15:44:16 +00:00
parent 6b406d5f47
commit f710e17df5
2 changed files with 120 additions and 20 deletions

View File

@ -38,12 +38,49 @@ import roslib; roslib.load_manifest(PKG)
import sys
import rosbagmigration
from optparse import OptionParser
import os
import re
import roslib.message
def print_trans(old,new,indent):
from_txt = "%s [%s]"%(old._type, old._md5sum)
if new is not None:
to_txt= "%s [%s]"%(new._type, new._md5sum)
else:
to_txt = "Unknown"
print " "*indent + " * From: %s"%(from_txt,)
print " "*indent + " To: %s"%(to_txt,)
if __name__ == '__main__':
if len(sys.argv) >= 3:
parser = OptionParser(usage="usage: makerule.py msg.saved [-a] output_rulefile [rulefile1, rulefile2, ...] [-n]")
parser.add_option("-a","--append",action="store_true",dest="append",default=False)
parser.add_option("-n","--noplugins",action="store_true",dest="noplugins",default=False)
(options, args) = parser.parse_args()
all_rules = []
if len(args) >= 2:
rulefile = args[1]
if os.path.isfile(rulefile) and not options.append:
print >> sys.stderr, "The file %s already exists. Include -a if you intend to append."%rulefile
exit(1)
if not os.path.isfile(rulefile) and options.append:
print >> sys.stderr, "The file %s does not exist, and so -a is invalid."%rulefile
exit(1)
if options.append:
append_rule = [rulefile]
else:
append_rule = []
f = open(sys.argv[1])
if f is None:
@ -59,6 +96,7 @@ if __name__ == '__main__':
old_type = type_match.groups()[0]
old_full_text = f.read()
f.close()
old_class = roslib.genpy.generate_dynamic(old_type,old_full_text)[old_type]
@ -66,28 +104,63 @@ if __name__ == '__main__':
print >> sys.stderr, "Could not generate class from full definition file."
sys.exit()
new_class = roslib.message.get_message_class(sys.argv[2])
mm = rosbagmigration.MessageMigrator(args[2:]+append_rule,not options.noplugins)
if new_class is None:
print >> sys.stderr, "Could not find class corresponding to %s"%sys.argv[2]
sys.exit()
migrations = rosbagmigration.checkmessages(mm, [old_class])
# If the type and md5sum match, there is nothing necessary to do
if ((old_class._type, old_class._md5sum) == (new_class._type, new_class._md5sum)):
print >> sys.stderr, "Types already match, nothing to do."
sys.exit()
mm = rosbagmigration.MessageMigrator(sys.argv[3:])
if migrations == []:
print "Saved definition is up to date"
exit(0)
else:
print "The following migrations need to occur:"
for m in migrations:
all_rules.extend(m[1])
new_rule = mm.make_update_rule(old_class, new_class)
R = new_rule(mm, "GENERATED")
R.find_sub_paths()
print_trans(m[0][0].old_class, m[0][-1].new_class, 0)
if len(m[1]) > 0:
print " %d rules missing:"%(len(m[1]))
for r in m[1]:
print_trans(r.old_class, r.new_class,1)
# Print rule definition and all additionally necessery definitions
R.print_def()
[r.print_def() for r in mm.get_invalid_rules()]
if rulefile is not None:
output = ""
rules_left = mm.filter_rules_unique(all_rules)
if rules_left == []:
print "\nNo additional rule files needed to be generated. %s not created."%(rulefile)
exit(0)
while rules_left != []:
extra_rules = []
for r in rules_left:
if r.new_class is None:
print "The message type %s appears to have moved. Please enter the type to migrate it to."%(r.old_class._type,)
new_type = raw_input('>')
new_class = roslib.scriptutil.get_message_class(new_type)
while new_class is None:
print "\'%s\' could not be found in your system. Please make sure it is built."%new_type
new_type = raw_input('>')
new_class = roslib.scriptutil.get_message_class(new_type)
new_rule = mm.make_update_rule(r.old_class, new_class)
R = new_rule(mm, 'GENERATED.' + new_rule.__name__)
R.find_sub_paths()
new_rules = [r for r in mm.expand_rules(R.sub_rules) if r.valid == False]
extra_rules.extend(new_rules)
print 'Creating the migration rule for %s requires additional missing rules:'%new_type
for nr in new_rules:
print_trans(nr.old_class, nr.new_class,1)
output += R.get_class_def()
else:
output += r.get_class_def()
rules_left = mm.filter_rules_unique(extra_rules)
f = open(rulefile, 'a')
f.write(output)
f.close()
print "\nThe necessary rule files have been written to: %s"%(rulefile,)
else:
print "rulefile not specified"
else:
print "usage: makerule.py <msg_full_text> <new_msg_name> [rulefile1, rulefile2, ...]"
parser.error("Incorrect number of arguments")

View File

@ -84,6 +84,33 @@ def checkbag(migrator, inbag):
return migrations
## Check whether a bag file can be played in the current system
#
# @param migrator The message migrator to use
# @param message_list A list of message classes.
# @returns A list of tuples for each type in the bag file. The first
# element of each tuple is the full migration path for the type. The
# second element of the tuple is the expanded list of invalid rules
# for that particular path.
def checkmessages(migrator, messages):
checked = Set()
migrations = []
for msg in messages:
key = get_message_key(msg)
if key not in checked:
target = migrator.find_target(msg)
# Even in the case of a zero-length path (matching md5sums), we still want
# to migrate in the event of a type change (message move).
path = migrator.find_path(msg, target)
if (path != []):
migrations.append((path, [r for r in migrator.expand_rules([sn.rule for sn in path]) if r.valid == False]))
checked.add(key)
return migrations
## Fix a bag so that it can be played in the current system
#
# @param migrator The message migrator to use