diff options
author | Alexandru Scvortov <alexandru@rabbitmq.com> | 2010-07-07 16:34:20 +0100 |
---|---|---|
committer | Alexandru Scvortov <alexandru@rabbitmq.com> | 2010-07-07 16:34:20 +0100 |
commit | ff940263e313151a3b6f4a273c212e9ba961ddae (patch) | |
tree | 84094cfc958a77f6d41faae11d27b0656823135f | |
parent | b27383147d606ccb1cdf178bb89c59cd33a5a15e (diff) | |
parent | 4c2c99f8c4d68ffc857346c0db5131667dfae838 (diff) | |
download | rabbitmq-codegen-git-ff940263e313151a3b6f4a273c212e9ba961ddae.tar.gz |
merge bug22901 into defaultrabbitmq_v1_8_1
-rw-r--r-- | amqp_codegen.py | 123 |
1 files changed, 73 insertions, 50 deletions
diff --git a/amqp_codegen.py b/amqp_codegen.py index 9da1aca8..a10cc6d9 100644 --- a/amqp_codegen.py +++ b/amqp_codegen.py @@ -33,6 +33,7 @@ from __future__ import nested_scopes import re import sys from os import remove +from optparse import OptionParser try: try: @@ -61,57 +62,66 @@ def insert_base_types(d): class AmqpSpecFileMergeConflict(Exception): pass -def default_spec_value_merger(key, old, new): - if old is None or old == new: +# If ignore_conflicts is true, then we allow acc and new to conflict, +# with whatever's already in acc winning and new being ignored. If +# ignore_conflicts is false, acc and new must not conflict. + +def default_spec_value_merger(key, acc, new, ignore_conflicts): + if acc is None or acc == new or ignore_conflicts: return new - raise AmqpSpecFileMergeConflict(key, old, new) + else: + raise AmqpSpecFileMergeConflict(key, acc, new) -def extension_info_merger(key, old, new): - return old + [new] +def extension_info_merger(key, acc, new, ignore_conflicts): + return acc + [new] -def domains_merger(key, old, new): - o = dict((k, v) for [k, v] in old) +def domains_merger(key, acc, new, ignore_conflicts): + merged = dict((k, v) for [k, v] in acc) for [k, v] in new: - if o.has_key(k): - raise AmqpSpecFileMergeConflict(key, old, new) - o[k] = v - return [[k, v] for (k, v) in o.iteritems()] - -def merge_dict_lists_by(dict_key, old, new, description): - old_index = set(v[dict_key] for v in old) - result = list(old) # shallow copy + if merged.has_key(k): + if not ignore_conflicts: + raise AmqpSpecFileMergeConflict(key, acc, new) + else: + merged[k] = v + + return [[k, v] for (k, v) in merged.iteritems()] + +def merge_dict_lists_by(dict_key, acc, new, ignore_conflicts): + acc_index = set(v[dict_key] for v in acc) + result = list(acc) # shallow copy for v in new: - if v[dict_key] in old_index: - raise AmqpSpecFileMergeConflict(description, old, new) - result.append(v) + if v[dict_key] in acc_index: + if not ignore_conflicts: + raise AmqpSpecFileMergeConflict(description, acc, new) + else: + result.append(v) return result -def constants_merger(key, old, new): - return merge_dict_lists_by("name", old, new, key) - -def methods_merger(classname, old, new): - return merge_dict_lists_by("name", old, new, ("class-methods", classname)) - -def properties_merger(classname, old, new): - oldnames = set(v["name"] for v in old) - newnames = set(v["name"] for v in new) - clashes = oldnames.intersection(newnames) - if clashes: - raise AmqpSpecFileMergeConflict(("class-properties", classname), old, new) - return old + new - -def class_merger(old, new): - old["methods"] = methods_merger(old["name"], old["methods"], new["methods"]) - old["properties"] = properties_merger(old["name"], - old.get("properties", []), - new.get("properties", [])) - -def classes_merger(key, old, new): - old_dict = dict((v["name"], v) for v in old) - result = list(old) # shallow copy +def constants_merger(key, acc, new, ignore_conflicts): + return merge_dict_lists_by("name", acc, new, ignore_conflicts) + +def methods_merger(classname, acc, new, ignore_conflicts): + return merge_dict_lists_by("name", acc, new, ignore_conflicts) + +def properties_merger(classname, acc, new, ignore_conflicts): + return merge_dict_lists_by("name", acc, new, ignore_conflicts) + +def class_merger(acc, new, ignore_conflicts): + acc["methods"] = methods_merger(acc["name"], + acc["methods"], + new["methods"], + ignore_conflicts) + acc["properties"] = properties_merger(acc["name"], + acc.get("properties", []), + new.get("properties", []), + ignore_conflicts) + +def classes_merger(key, acc, new, ignore_conflicts): + acc_dict = dict((v["name"], v) for v in acc) + result = list(acc) # shallow copy for w in new: - if w["name"] in old_dict: - class_merger(old_dict[w["name"]], w) + if w["name"] in acc_dict: + class_merger(acc_dict[w["name"]], w, ignore_conflicts) else: result.append(w) return result @@ -123,23 +133,28 @@ mergers = { "classes": (classes_merger, []), } -def merge_load_specs(filenames): +def merge_load_specs(filenames, ignore_conflicts): handles = [file(filename) for filename in filenames] docs = [json.load(handle) for handle in handles] spec = {} for doc in docs: for (key, value) in doc.iteritems(): (merger, default_value) = mergers.get(key, (default_spec_value_merger, None)) - spec[key] = merger(key, spec.get(key, default_value), value) + spec[key] = merger(key, spec.get(key, default_value), value, ignore_conflicts) for handle in handles: handle.close() return spec class AmqpSpec: + # Slight wart: use a class member rather than change the ctor signature + # to avoid breaking everyone else's code. + ignore_conflicts = False + def __init__(self, filenames): - self.spec = merge_load_specs(filenames) + self.spec = merge_load_specs(filenames, AmqpSpec.ignore_conflicts) self.major = self.spec['major-version'] self.minor = self.spec['minor-version'] + self.revision = self.spec.has_key('revision') and self.spec['revision'] or 0 self.port = self.spec['port'] self.domains = {} @@ -250,7 +265,7 @@ def do_main(header_fn, body_fn): def do_main_dict(funcDict): def usage(): print >> sys.stderr , "Usage:" - print >> sys.stderr , " %s <function> <path_to_amqp_spec.json> <path_to_output_file>" % (sys.argv[0]) + print >> sys.stderr , " %s <function> <path_to_amqp_spec.json>... <path_to_output_file>" % (sys.argv[0]) print >> sys.stderr , " where <function> is one of %s" % ", ".join([k for k in funcDict.keys()]) def execute(fn, amqp_specs, out_file): @@ -267,12 +282,20 @@ def do_main_dict(funcDict): sys.stdout = stdout f.close() - if len(sys.argv) < 4: + parser = OptionParser() + parser.add_option("--ignore-conflicts", action="store_true", dest="ignore_conflicts", default=False) + (options, args) = parser.parse_args() + + if len(args) < 3: usage() sys.exit(1) else: - if funcDict.has_key(sys.argv[1]): - execute(funcDict[sys.argv[1]], sys.argv[2:-1], sys.argv[-1]) + function = args[0] + sources = args[1:-1] + dest = args[-1] + AmqpSpec.ignore_conflicts = options.ignore_conflicts + if funcDict.has_key(function): + execute(funcDict[function], sources, dest) else: usage() sys.exit(1) |