#!/usr/bin/env python # # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, # software distributed under the License is distributed on an # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. # import sys, os, xml from qpid.spec import load, pythonize from textwrap import TextWrapper from xml.sax.handler import ContentHandler class Block: def __init__(self, children): self.children = children def emit(self, out): for child in self.children: if not hasattr(child, "emit"): raise ValueError(child) child.emit(out) if not self.children: out.line("pass") class If: def __init__(self, expr, cons, alt = None): self.expr = expr self.cons = cons self.alt = alt def emit(self, out): out.line("if ") self.expr.emit(out) out.write(":") out.level += 1 self.cons.emit(out) out.level -= 1 if self.alt: out.line("else:") out.level += 1 self.alt.emit(out) out.level -= 1 class Stmt: def __init__(self, code): self.code = code def emit(self, out): out.line(self.code) class Expr: def __init__(self, code): self.code = code def emit(self, out): out.write(self.code) class Abort: def __init__(self, expr): self.expr = expr def emit(self, out): out.line("assert False, ") self.expr.emit(out) WRAPPER = TextWrapper() def wrap(text): return WRAPPER.wrap(" ".join(text.split())) class Doc: def __init__(self, text): self.text = text def emit(self, out): out.line('"""') for line in wrap(self.text): out.line(line) out.line('"""') class Frame: def __init__(self, attrs): self.attrs = attrs self.children = [] self.text = None def __getattr__(self, attr): return self.attrs[attr] def isunicode(s): if isinstance(s, str): return False for ch in s: if ord(ch) > 127: return True return False def string_literal(s): if s == None: return None if isunicode(s): return "%r" % s else: return "%r" % str(s) TRUTH = { "1": True, "0": False, "true": True, "false": False } LITERAL = { "shortstr": string_literal, "longstr": string_literal, "bit": lambda s: TRUTH[s.lower()], "longlong": lambda s: "%r" % long(s) } def literal(s, field): return LITERAL[field.type](s) def palexpr(s, field): if s.startswith("$"): return "msg.%s" % s[1:] else: return literal(s, field) class Translator(ContentHandler): def __init__(self, spec): self.spec = spec self.stack = [] self.content = None self.root = Frame(None) self.push(self.root) def emit(self, out): blk = Block(self.root.children) blk.emit(out) out.write("\n") def peek(self): return self.stack[-1] def pop(self): return self.stack.pop() def push(self, frame): self.stack.append(frame) def startElement(self, name, attrs): self.push(Frame(attrs)) def endElement(self, name): frame = self.pop() if hasattr(self, name): child = getattr(self, name)(frame) else: child = self.handle(name, frame) if child: self.peek().children.append(child) def characters(self, text): frame = self.peek() if frame.text: frame.text += text else: frame.text = text def handle(self, name, frame): for klass in self.spec.classes: pyklass = pythonize(klass.name) if name.startswith(pyklass): name = name[len(pyklass) + 1:] break else: raise ValueError("unknown class: %s" % name) for method in klass.methods: pymethod = pythonize(method.name) if name == pymethod: break else: raise ValueError("unknown method: %s" % name) args = ["%s = %s" % (key, palexpr(val, method.fields.bypyname[key])) for key, val in frame.attrs.items()] if method.content and self.content: args.append("content = %r" % string_literal(self.content)) code = "ssn.%s_%s(%s)" % (pyklass, pymethod, ", ".join(args)) if pymethod == "consume": code = "consumer_tag = %s.consumer_tag" % code return Stmt(code) def pal(self, frame): return Block([Doc(frame.text)] + frame.children) def include(self, frame): base, ext = os.path.splitext(frame.filename) return Stmt("from %s import *" % base) def session(self, frame): return Block([Stmt("cli = open()"), Stmt("ssn = cli.channel(0)"), Stmt("ssn.channel_open()")] + frame.children) def empty(self, frame): return If(Expr("msg == None"), Block(frame.children)) def abort(self, frame): return Abort(Expr(string_literal(frame.text))) def wait(self, frame): return Stmt("msg = ssn.queue(consumer_tag).get(timeout=%r)" % (int(frame.timeout)/1000)) def basic_arrived(self, frame): if frame.children: return If(Expr("msg != None"), Block(frame.children)) def basic_content(self, frame): self.content = frame.text class Emitter: def __init__(self, out): self.out = out self.level = 0 def write(self, code): self.out.write(code) def line(self, code): self.write("\n%s%s" % (" "*self.level, code)) def flush(self): self.out.flush() def close(self): self.out.close() for f in sys.argv[2:]: base, ext = os.path.splitext(f) spec = load(sys.argv[1]) t = Translator(spec) xml.sax.parse(f, t) # out = Emitter(open("%s.py" % base)) out = Emitter(sys.stdout) t.emit(out) out.close()