Beispiel #1
0
class _ClassDelegate(classy):
    """Type whose attributes/methods are delegated to ``cls.get()``"""

    __slots__ = ()

    get = None  # dummy

    decorate(classmethod)

    def __class_init__(cls, name, bases, cdict, supr):
        meta = type(cls)
        if getattr(meta, '__for_class__', None) is not cls:
            cls.__class__ = meta = type(meta)(cls.__name__ + 'Class', (meta, ),
                                              dict(_std_attrs,
                                                   __module__=cls.__module__,
                                                   __for_class__=cls))
            # XXX activate_attrs(meta)?

        supr()(cls, name, bases, cdict, supr)

        if 'get' not in cdict:
            cls.get = staticmethod(classmethod(lookup).__get__(None, cls))

        for k, v in cdict.items():
            if not isinstance(k, basestring):
                continue
            if not isinstance(v,
                              (classmethod, staticmethod)) and not _ignore(k):
                redirect_attribute(cls, k, v)
Beispiel #2
0
class MethodList(Method):
    """A list of related methods"""

    can_tail = False
    _sorted_items = None

    def __init__(self, items=(), tail=None):
        self.items = list(items)
        self.tail = tail

    decorate(classmethod)
    def make(cls, body, signature=(), serial=0):
        return cls( [(serial, signature, body)] )

    def __repr__(self):
        data = self.items, self.tail
        return self.__class__.__name__+repr(data)

    def tail_with(self, tail):
        return self.__class__(self.items, tail)

    def merge(self, other):
        if other.__class__ is not self.__class__:
            raise TypeError("Incompatible action types for merge", self, other)
        return self.__class__(
            self.items+other.items, combine_actions(self.tail, other.tail)
        )

    def compiled(self, engine):
        wrappers = tuple(engine.rules.methodlist_wrappers)
        bodies = [compile_method(body,engine) for sig, body in self.sorted()]
        return engine.apply_template(list_template, tuple(bodies), wrappers)









    def sorted(self):
        if self._sorted_items is not None:
            return self._sorted_items

        self.items.sort()
        rest = [(s,b) for (serial, s, b) in self.items]

        self._sorted_items = items = []
        seen = set()
        while rest:
            best = dominant_signatures(rest)
            list(map(rest.remove, best))
            for s,b in best:
                if b not in seen:
                    seen.add(b)
                    items.append((s,b))
        return items
Beispiel #3
0
class State(_ClassDelegate):
    """A thread's current configuration and state"""
    def __new__(cls, *rules, **attrs):
        return attrs and object.__new__(cls) or empty()

    def __init__(self, **attrs):
        """Create an empty state with `rules` in effect"""
        self.__dict__.update(attrs)

    def __getitem__(self, key):
        """Get the rule for `key`"""
        return self.getRule(key)

    def __setitem__(self, key, rule):
        """Set the rule for `key`"""
        return self.setRule(key, rule)

    def swap(self):
        """Make this state current and return the old one"""
        raise NotImplementedError("Can't switch to the root state")

    def child(self, *rules):
        """Return a new child state of this one, with `rules` in effect"""
        raise NotImplementedError  # this method is replaced on each instance

    def __enter__(self):
        """Make this state a single-use nested state"""
        raise NotImplementedError("Can't enter the root state")

    def __exit__(self, typ, val, tb):
        """Close this state and invoke exit callbacks"""
        raise NotImplementedError("Can't exit the root state")

    def on_exit(self, callback):
        """Add a `callback(typ,val,tb)` to be invoked at ``__exit__`` time"""
        raise NotImplementedError  # this method is replaced on each instance

    decorate(staticmethod)

    def get(key=None):
        """Return the current state (no args) or a current rule (w/key)"""
        # this method is replaced later below
        raise NotImplementedError

    parent = None
        for ob in args:
            if callable(ob):
                last = ob(self)
            else:
                try:
                    f = generate_types[type(ob)]
                except KeyError:
                    raise TypeError("Can't generate", ob)
                else:
                    last = f(self, ob)
        return last

    def return_(self, ob=None):
        return self(ob, Code.RETURN_VALUE)

    decorate(classmethod)

    def from_function(cls, function, copy_lineno=False):
        code = cls.from_code(function.func_code, copy_lineno)
        return code

    decorate(classmethod)

    def from_code(cls, code, copy_lineno=False):
        import inspect

        self = cls.from_spec(code.co_name, *inspect.getargs(code))
        if copy_lineno:
            self.set_lineno(code.co_firstlineno)
            self.co_filename = code.co_filename
        self.co_freevars = code.co_freevars  # XXX untested!
# unit tests...
if __name__ == "__main__":
    logging.basicConfig(level=logging.WARNING,
                    format='%(name)s %(levelname)s %(filename)s, %(funcName)s, Line: %(lineno)d:  %(message)s',)
    log = getLog("foobar.bubble")
    root = getLog(name="")
    log.setLevel(logging.WARNING)
    root.setLevel(logging.DEBUG)

    log.debug(" --> debug")
    log.error(" --> error")
    log.warning(" --> warning")
    log.warn(" --> warn")

    decorate(traceLog(log))
    def testFunc(arg1, arg2="default", *args, **kargs):
        return 42

    testFunc("hello", "world", logger=root)
    testFunc("happy", "joy", name="skippy")
    testFunc("hi")

    decorate(traceLog(root))
    def testFunc22():
        return testFunc("archie", "bunker")

    testFunc22()

    decorate(traceLog(root))
    def testGen():
Beispiel #6
0
class BitmapIndex(AddOn):
    """Index that computes selectivity and handles basic caching w/bitmaps"""

    known_cases = 0
    match = True,

    decorate(staticmethod)

    def addon_key(*args):
        # Always use BitmapIndex as the add-on key
        return (BitmapIndex, ) + args

    def __new__(cls, engine, expr):
        if cls is BitmapIndex:
            cls = bitmap_index_type(engine, expr)
        return super(BitmapIndex, cls).__new__(cls)

    def __init__(self, engine, expr):
        self.extra = {}
        self.null = self.all_seeds = {}  # seed -> inc_cri, exc_cri
        self.criteria_bits = {}  # cri  -> case bits
        self.case_seeds = []  # case -> seed set
        self.criteria_seeds = {}  # cri  -> seeds

    def add_case(self, case_id, criterion):
        if criterion in self.criteria_seeds:
            seeds = self.criteria_seeds[criterion]
        else:
            self.criteria_bits.setdefault(criterion, 0)
            seeds = self.criteria_seeds[criterion] = self.add_criterion(
                criterion)

        case_seeds = self.case_seeds
        if case_id == len(case_seeds):
            case_seeds.append(seeds)
        else:
            self._extend_cases(case_id)
            case_seeds[case_id] = seeds

        bit = to_bits([case_id])
        self.known_cases |= bit
        self.criteria_bits[criterion] |= bit

    def add_criterion(self, criterion):
        """Ensure `criterion` is indexed, return its "applicable seeds" set
        
        As a side effect, ``self.all_seeds`` must be updated to include any
        new seeds required by `criterion`.
        """
        raise NotImplementedError

    def _extend_cases(self, case_id):
        if case_id >= len(self.case_seeds):
            self.case_seeds.extend([self.null] *
                                   (case_id + 1 - len(self.case_seeds)))

    def selectivity(self, cases):
        if cases and cases[-1] >= len(self.case_seeds):
            self._extend_cases(cases[-1])
        cases = list(map(self.case_seeds.__getitem__, cases))
        return (len(self.all_seeds), sum(map(len, cases)))

    def seed_bits(self, cases):
        bits = self.criteria_bits
        return cases ^ (self.known_cases & cases), dict([
            (seed, (sum([bits[i]
                         for i in inc]) & cases, sum([bits[e]
                                                      for e in exc]) & cases))
            for seed, (inc, exc) in self.all_seeds.items()
        ])

    def expanded_sets(self):
        return [(seed, [list(from_bits(inc)),
                        list(from_bits(exc))])
                for seed, (inc,
                           exc) in self.seed_bits(self.known_cases)[1].items()]

    def reseed(self, criterion):
        self.add_criterion(criterion)

    def include(self, seed, criterion, exclude=False):
        try:
            s = self.all_seeds[seed]
        except KeyError:
            s = self.all_seeds[seed] = set(), set()
        s[exclude].add(criterion)
        self.criteria_bits.setdefault(criterion, 0)

    def exclude(self, seed, criterion):
        self.include(seed, criterion, True)
Beispiel #7
0
# unit tests...
if __name__ == "__main__":
    logging.basicConfig(
        level=logging.WARNING,
        format=
        '%(name)s %(levelname)s %(filename)s, %(funcName)s, Line: %(lineno)d:  %(message)s',
    )
    log = getLog("foobar.bubble")
    root = getLog(name="")
    log.setLevel(logging.WARNING)
    root.setLevel(logging.DEBUG)

    log.debug(" --> debug")
    log.error(" --> error")

    decorate(traceLog(log))

    def testFunc(arg1, arg2="default", *args, **kargs):
        return 42

    testFunc("hello", "world", logger=root)
    testFunc("happy", "joy", name="skippy")
    testFunc("hi")

    decorate(traceLog(root))

    def testFunc22():
        return testFunc("archie", "bunker")

    testFunc22()
Beispiel #8
0
class Method(with_metaclass(MethodType)):
    """A simple method w/optional chaining"""

    def __init__(self, body, signature=(), serial=0, tail=None):
        self.body = body
        self.signature = signature
        self.serial = serial
        self.tail = tail
        self.can_tail = False
        try:
            args = inspect.getargspec(body)[0]
        except TypeError:
            pass
        else:
            if args and args[0]=='next_method':
                if getattr(body, 'im_self', None) is None:  # already bound?
                    self.can_tail = True

    decorate(classmethod)
    def make(cls, body, signature=(), serial=0):
        return cls(body, signature, serial)

    def __repr__(self):
        data = (self.body, self.signature, self.serial, self.tail)
        return self.__class__.__name__+repr(data)

    def __call__(self, *args, **kw):
        """Slow way to call a method -- use compile_method instead!"""
        return compile_method(self)(*args, **kw)
        
    def override(self, other):
        if not self.can_tail:
            return self
        return self.tail_with(combine_actions(self.tail, other))

    def tail_with(self, tail):
        return self.__class__(self.body, self.signature, self.serial, tail)




    def merge(self, other):
        #if self.__class__ is other.__class__ and self.body is other.body:
        #    XXX need to merge signatures?
        #    return self.__class__(
        #        self.body, ???, ???, combine_actions(self.tail, other.tail)
        #    )
        return AmbiguousMethods([self,other])

    decorate(classmethod)
    def make_decorator(cls, name, doc=None):
        if doc is None:
            doc = "Extend a generic function with a method of type ``%s``" \
                  % cls.__name__
        if cls is Method:
            maker = None   # allow gf's to use something else instead of Method
        else:
            maker = cls.make
        def decorate(f, pred=(), depth=2, frame=None):
            def callback(frame, name, func, old_locals):
                assert f is not func    # XXX
                kind, module, locals_, globals_ = frameinfo(frame)
                context = ParseContext(func, maker, locals_, globals_, lineno)
                def register_for_class(cls, f=f):
                    _register_rule(f, pred, context, cls)
                    return cls
                if kind=='class':
                    # 'when()' in class body; defer adding the method
                    decorate_class(register_for_class, frame=frame)
                else:
                    register_for_class(None)
                if old_locals.get(name) is f:
                    return f    # prevent overwriting if name is the same
                return func
            rv = decorate_assignment(callback, depth, frame)
            if frame is None: frame = sys._getframe(depth-1)
            lineno = frame.f_lineno # this isn't valid w/out active trace!
            return rv
        decorate = with_name(decorate, name)
        decorate.__doc__ = doc
        return decorate

    def compiled(self, engine):
        body = compile_method(self.body, engine)
        if not self.can_tail:
            return body
        else:
            return types.MethodType(body, compile_method(self.tail, engine))
Beispiel #9
0
class Code(object):
    co_argcount = 0
    co_stacksize = 0
    co_flags = CO_OPTIMIZED | CO_NEWLOCALS      # typical usage
    co_filename = '<generated code>'
    co_name = '<lambda>'
    co_firstlineno = 0
    co_freevars = ()
    co_cellvars = ()
    _last_lineofs = 0
    _last_line = 0
    _ss = 0
    _tmp_level = 0

    def __init__(self):
        self.co_code = array('B')
        self.co_consts = [None]
        self.co_names = []
        self.co_varnames = []
        self.co_lnotab = array('B')
        self.emit = self.co_code.append
        self.blocks = []
        self.stack_history = []

    def emit_arg(self, op, arg):
        emit = self.emit
        if arg>0xFFFF:
            emit(EXTENDED_ARG)
            emit((arg>>16)&255)
            emit((arg>>24)&255)
        emit(op)
        emit(arg&255)
        emit((arg>>8)&255)

    def locals_written(self):
        vn = self.co_varnames
        hl = dict.fromkeys([STORE_FAST, DELETE_FAST])
        return dict.fromkeys([vn[arg] for ofs, op, arg in self if op in hl])




    def set_lineno(self, lno):
        if not self.co_firstlineno:
            self.co_firstlineno = self._last_line = lno
            return

        append = self.co_lnotab.append
        incr_line = lno - self._last_line
        incr_addr = len(self.co_code) - self._last_lineofs
        if not incr_line:
            return

        if incr_addr<=0 or incr_line<=0:
             return

        while incr_addr>255:
            append(255)
            append(0)
            incr_addr -= 255

        while incr_line>255:
            append(incr_addr)
            append(255)
            incr_line -= 255
            incr_addr = 0

        if incr_addr or incr_line:
            append(incr_addr)
            append(incr_line)

        self._last_line = lno
        self._last_lineofs = len(self.co_code)

    def YIELD_VALUE(self):
        self.stackchange(stack_effects[YIELD_VALUE])
        self.co_flags |= CO_GENERATOR
        return self.emit(YIELD_VALUE)






    def LOAD_CONST(self, const):
        self.stackchange((0,1))
        pos = 0
        hashable = True
        try:
            hash(const)
        except TypeError:
            hashable = False
        while 1:
            try:
                arg = self.co_consts.index(const, pos)
                it = self.co_consts[arg]
            except ValueError:
                arg = len(self.co_consts)
                self.co_consts.append(const)
                break
            else:
                if type(it) is type(const) and (hashable or it is const):
                    break
            pos = arg+1
            continue
        return self.emit_arg(LOAD_CONST, arg)

    def CALL_FUNCTION(self, argc=0, kwargc=0, op=CALL_FUNCTION, extra=0):
        self.stackchange((1+argc+2*kwargc+extra,1))
        emit = self.emit
        emit(op); emit(argc); emit(kwargc)

    def CALL_FUNCTION_VAR(self, argc=0, kwargc=0):
        self.CALL_FUNCTION(argc,kwargc,CALL_FUNCTION_VAR, 1)    # 1 for *args

    def CALL_FUNCTION_KW(self, argc=0, kwargc=0):
        self.CALL_FUNCTION(argc,kwargc,CALL_FUNCTION_KW, 1)     # 1 for **kw

    def CALL_FUNCTION_VAR_KW(self, argc=0, kwargc=0):
        self.CALL_FUNCTION(argc,kwargc,CALL_FUNCTION_VAR_KW, 2) # 2 *args,**kw

    def BUILD_TUPLE(self, count):
        self.stackchange((count,1))
        self.emit_arg(BUILD_TUPLE,count)

    def BUILD_LIST(self, count):
        self.stackchange((count,1))
        self.emit_arg(BUILD_LIST,count)

    def UNPACK_SEQUENCE(self, count):
        self.stackchange((1,count))
        self.emit_arg(UNPACK_SEQUENCE,count)

    def RETURN_VALUE(self):
        self.stackchange((1,0))
        self.emit(RETURN_VALUE)
        self.stack_unknown()

    def BUILD_SLICE(self, count):
        assert count in (2,3), "Invalid number of arguments for BUILD_SLICE"
        self.stackchange((count,1))
        self.emit_arg(BUILD_SLICE,count)

    def DUP_TOPX(self, count):
        self.stackchange((count,count*2))
        self.emit_arg(DUP_TOPX,count)

    def RAISE_VARARGS(self, argc):
        assert 0<=argc<=3, "Invalid number of arguments for RAISE_VARARGS"
        self.stackchange((argc,0))
        self.emit_arg(RAISE_VARARGS,argc)

    def MAKE_FUNCTION(self, ndefaults):
        self.stackchange((1+ndefaults,1))
        self.emit_arg(MAKE_FUNCTION, ndefaults)

    def MAKE_CLOSURE(self, ndefaults, freevars):
        if sys.version>='2.5':
            freevars = 1
        self.stackchange((1+freevars+ndefaults,1))
        self.emit_arg(MAKE_CLOSURE, ndefaults)

    def here(self):
        return len(self.co_code)


    if 'UNARY_CONVERT' not in opcode:
        def UNARY_CONVERT(self):
            self(Const(repr))
            self.ROT_TWO()
            self.CALL_FUNCTION(1, 0)

    if 'BINARY_DIVIDE' not in opcode:
        def BINARY_DIVIDE(self):
            self.BINARY_TRUE_DIVIDE()

    if 'DUP_TOPX' not in opcode:
        def DUP_TOPX(self, count):
            self.stackchange((count,count*2))
            if count==2:
                self.emit(DUP_TOP_TWO)
            else:
                raise RuntimeError("Python 3 only supports DUP_TOP_TWO")

    if 'SLICE_0' not in opcode:
        def SLICE_0(self):
            self(None, None, Code.SLICE_3)
        def SLICE_1(self):
            self(None, Code.SLICE_3)
        def SLICE_2(self):
            self(None, Code.ROT_TWO, Code.SLICE_3)
        def SLICE_3(self):
            self.BUILD_SLICE(2)
            self.BINARY_SUBSCR()           
            

    def set_stack_size(self, size):
        if size<0:
            raise AssertionError("Stack underflow")
        if size>self.co_stacksize:
            self.co_stacksize = size
        bytes = len(self.co_code) - len(self.stack_history) + 1
        if bytes>0:
            self.stack_history.extend([self._ss]*bytes)
        self._ss = size


    def get_stack_size(self):
        return self._ss

    stack_size = property(get_stack_size, set_stack_size)

    def stackchange(self, inout):
        (inputs,outputs) = inout
        if self._ss is None:
            raise AssertionError("Unknown stack size at this location")
        self.stack_size -= inputs   # check underflow
        self.stack_size += outputs  # update maximum height


    def stack_unknown(self):
        self._ss = None

    def branch_stack(self, location, expected):
        if location >= len(self.stack_history):
            if location > len(self.co_code):
                raise AssertionError("Forward-looking stack prediction!",
                    location, len(self.co_code)
                )
            actual = self.stack_size
            if actual is None:
                self.stack_size = actual = expected
                self.stack_history[location] = actual
        else:
            actual = self.stack_history[location]
            if actual is None:
                self.stack_history[location] = actual = expected

        if actual != expected:
            raise AssertionError(
                "Stack level mismatch: actual=%s expected=%s"
                % (actual, expected)
            )





    def jump(self, op, arg=None):
        def jump_target(offset):
            target = offset
            #print op
            #print hasjabs
            if op not in hasjabs:
                target = target - (posn+3)
                if target<0:
                    raise AssertionError("Relative jumps can't go backwards")
                if True:
                    target = offset - (posn+6)
            return target

        def backpatch(offset):
            target = jump_target(offset)
            #if target>0xFFFF:
            #    print hasjabs
            #    print hasjrel
            #    print op
            #    print "ofs: " + hex(offset) + ", tgt: " + hex(target) + ", posn: " + hex(posn)
                #exit(0)
                #raise AssertionError("Forward jump span must be <64K bytes")
            assert(op!=120)
            self.patch_arg(posn, 0x1FFFF, target,op)
            self.branch_stack(offset, old_level)

        if op==FOR_ITER:
            old_level = self.stack_size = self.stack_size - 1
            self.stack_size += 2
        else:
            old_level = self.stack_size
        self.stack_size -= (op in (JUMP_IF_TRUE_OR_POP, JUMP_IF_FALSE_OR_POP))
        posn = self.here()
        if arg is not None:
            print "jt: " + hex(jump_target(arg))
            self.emit_arg(op, jump_target(arg))
            self.branch_stack(arg, old_level)
            lbl = None
        else:
            self.emit_arg(op, 0x1FFFF)
            def lbl(code=None):
                backpatch(self.here())
        if op in (JUMP_FORWARD, JUMP_ABSOLUTE, CONTINUE_LOOP):
            self.stack_unknown()
        return lbl

    def COMPARE_OP(self, op):
        self.stackchange((2,1))
        self.emit_arg(COMPARE_OP, compares[op])

    def setup_block(self, op):
        jmp = self.jump(op)
        self.blocks.append((op,self.stack_size,jmp))
        return jmp

    def SETUP_EXCEPT(self):
        ss = self.stack_size
        self.stack_size = ss+3  # simulate the level at "except:" time
        self.setup_block(SETUP_EXCEPT)
        self.stack_size = ss    # restore the current level

    def SETUP_FINALLY(self):
        ss = self.stack_size
        self.stack_size = ss+3  # allow for exceptions
        self.stack_size = ss+1  # simulate the level after the None is pushed
        self.setup_block(SETUP_FINALLY)
        self.stack_size = ss    # restore original level

    def SETUP_LOOP(self):
        self.setup_block(SETUP_LOOP)

    def POP_BLOCK(self):
        if not self.blocks:
            raise AssertionError("Not currently in a block")

        why, level, fwd = self.blocks.pop()
        self.emit(POP_BLOCK)

        if why!=SETUP_LOOP:
            if why==SETUP_FINALLY:
                self.LOAD_CONST(None)
                fwd()
            else:
                self.stack_size = level-3   # stack level resets here
                else_ = self.JUMP_FORWARD()
                fwd()
                return else_
        else:
            return fwd


    if 'JUMP_IF_TRUE_OR_POP' not in opcode:
        def JUMP_IF_TRUE_OR_POP(self, address=None):
            lbl = self.JUMP_IF_TRUE(address)
            self.POP_TOP()
            return lbl
        globals()['JUMP_IF_TRUE_OR_POP'] = -1

    if 'JUMP_IF_FALSE_OR_POP' not in opcode:
        def JUMP_IF_FALSE_OR_POP(self, address=None):
            lbl = self.JUMP_IF_FALSE(address)
            self.POP_TOP()
            return lbl
        globals()['JUMP_IF_FALSE_OR_POP'] = -1

    if 'JUMP_IF_TRUE' not in opcode:
        def JUMP_IF_TRUE(self, address=None):
            self.DUP_TOP()
            return self.POP_JUMP_IF_TRUE(address)
    else:
        globals()['POP_JUMP_IF_TRUE'] = -1

    if 'JUMP_IF_FALSE' not in opcode:
        def JUMP_IF_FALSE(self, address=None):
            self.DUP_TOP()
            return self.POP_JUMP_IF_FALSE(address)
    else:
        globals()['POP_JUMP_IF_FALSE'] = -1

    if 'LIST_APPEND' in opcode and LIST_APPEND>=HAVE_ARGUMENT:
        def LIST_APPEND(self, depth):
            self.stackchange((depth+1, depth))
            self.emit_arg(LIST_APPEND, depth)









    def assert_loop(self):
        for why,level,fwd in self.blocks:
            if why==SETUP_LOOP:
                return
        raise AssertionError("Not inside a loop")

    def BREAK_LOOP(self):
        self.assert_loop(); self.emit(BREAK_LOOP)
        self.stack_unknown()

    def CONTINUE_LOOP(self, label):
        self.assert_loop()
        if self.blocks[-1][0]==SETUP_LOOP:
            op = JUMP_ABSOLUTE  # more efficient if not in a nested block
        else:
            op = CONTINUE_LOOP
        return self.jump(op, label)

    def __call__(self, *args):
        last = None
        for ob in args:
            if hasattr(ob, '__call__'):
                last = ob(self)
            else:
                try:
                    f = generate_types[type(ob)]
                except KeyError:
                    raise TypeError("Can't generate", ob)
                else:
                    last = f(self, ob)
        return last

    def return_(self, ob=None):
        return self(ob, Code.RETURN_VALUE)

    decorate(classmethod)
    def from_function(cls, function, copy_lineno=False):
        code = cls.from_code(getattr(function, CODE), copy_lineno)
        return code


    decorate(classmethod)
    def from_code(cls, code, copy_lineno=False):
        import inspect
        self = cls.from_spec(code.co_name, *inspect.getargs(code))
        if copy_lineno:
            self.set_lineno(code.co_firstlineno)
            self.co_filename = code.co_filename
        self.co_freevars = code.co_freevars     # XXX untested!
        return self

    decorate(classmethod)
    def from_spec(cls, name='<lambda>', args=(), var=None, kw=None):
        self = cls()
        self.co_name = name
        self.co_argcount = len(args)
        self.co_varnames.extend(args)
        if var:
            self.co_varnames.append(var)
            self.co_flags |= CO_VARARGS
        if kw:
            self.co_varnames.append(kw)
            self.co_flags |= CO_VARKEYWORDS

        def tuple_arg(args):
            self.UNPACK_SEQUENCE(len(args))
            for arg in args:
                if not isinstance(arg, basestring):
                    tuple_arg(arg)
                else:
                    self.STORE_FAST(arg)

        for narg, arg in enumerate(args):
            if not isinstance(arg, basestring):
                dummy_name = '.'+str(narg)
                self.co_varnames[narg] = dummy_name
                self.LOAD_FAST(dummy_name)
                tuple_arg(arg)

        return self


    def patch_arg(self, offset, oldarg, newarg, op):
        assert(op!=120)	
        code = self.co_code
        if (newarg>0xFFFF) and (oldarg<=0xFFFF):
            raise AssertionError("Can't change argument size", oldarg, newarg)
        code[offset+1] = newarg & 255
        code[offset+2] = (newarg>>8) & 255
        if newarg>0xFFFF or oldarg>0xFFFF or op == 120:
            code[offset+1] = (newarg>>16) & 255
            code[offset+2] = (newarg>>24) & 255
            code[offset+4] = (newarg>>0) & 255
            code[offset+5] = (newarg>>8) & 255

    def nested(self, name='<lambda>', args=(), var=None, kw=None, cls=None):
        if cls is None:
            cls = self.__class__
        code = cls.from_spec(name, args, var, kw)
        code.co_filename=self.co_filename
        return code

    def __iter__(self):
        i = 0
        extended_arg = 0
        code = self.co_code
        n = len(code)
        while i < n:
            op = code[i]
            if op >= HAVE_ARGUMENT:
                oparg = code[i+1] + code[i+2]*256 + extended_arg
                extended_arg = 0
                if op == EXTENDED_ARG:
                    extended_arg = oparg*long(65536)
                    i+=3
                    continue
                yield i, op, oparg
                i += 3
            else:
                yield i, op, None
                i += 1




    def makefree(self, names):
        nowfree = dict.fromkeys(self.co_freevars)
        newfree = [n for n in names if n not in nowfree]
        if newfree:
            self.co_freevars += tuple(newfree)
            self._locals_to_cells()

    def makecells(self, names):
        nowcells = dict.fromkeys(self.co_cellvars+self.co_freevars)
        newcells = [n for n in names if n not in nowcells]
        if newcells:
            if not (self.co_flags & CO_OPTIMIZED):
                raise AssertionError("Can't use cellvars in unoptimized scope")
            cc = len(self.co_cellvars)
            nc = len(newcells)
            self.co_cellvars += tuple(newcells)
            if self.co_freevars:
                self._patch(
                    deref_to_deref,
                    dict([(n+cc,n+cc+nc)for n in range(len(self.co_freevars))])
                )
            self._locals_to_cells()

    def _locals_to_cells(self):
        freemap = dict(
            [(n,p) for p,n in enumerate(self.co_cellvars+self.co_freevars)]
        )
        argmap = dict(
            [(p,freemap[n]) for p,n in enumerate(self.co_varnames)
                if n in freemap]
        )
        if argmap:
            for ofs, op, arg in self:
                if op==DELETE_FAST and arg in argmap:
                    raise AssertionError(
                        "Can't delete local %r used in nested scope"
                        % self.co_varnames[arg]
                    )
            self._patch(fast_to_deref, argmap)


    def _patch(self, opmap, argmap={}):
        code = self.co_code
        for ofs, op, arg in self:
            if op in opmap:
                print op
                if arg in argmap:
                    self.patch_arg(ofs, arg, argmap[arg],op)
                elif arg is not None:
                    continue
                code[ofs] = opmap[op]

    def code(self, parent=None):
        if self.blocks:
            raise AssertionError("%d unclosed block(s)" % len(self.blocks))

        flags = self.co_flags & ~CO_NOFREE
        if parent is not None:
            locals_written = self.locals_written()
            self.makefree([
                n for n in self.co_varnames[
                    self.co_argcount
                    + ((self.co_flags & CO_VARARGS)==CO_VARARGS)
                    + ((self.co_flags & CO_VARKEYWORDS)==CO_VARKEYWORDS)
                    :
                ] if n not in locals_written
            ])

        if not self.co_freevars and not self.co_cellvars:
            flags |= CO_NOFREE
        elif parent is not None and self.co_freevars:
            parent.makecells(self.co_freevars)

        return NEW_CODE(
            self.co_argcount, len(self.co_varnames),
            self.co_stacksize, flags, to_code(self.co_code),
            tuple(self.co_consts), tuple(self.co_names),
            tuple(self.co_varnames),
            self.co_filename, self.co_name, self.co_firstlineno,
            to_code(self.co_lnotab), self.co_freevars, self.co_cellvars
        )
Beispiel #10
0
class Graph:
    def __init__(self, iterable=()):
        self.kvl = {}
        self.has_key = self.kvl.has_key
        for k, v in iterable:
            self[k] = v

    decorate(classmethod)

    def fromkeys(cls, keys):
        return cls([(k, k) for k in keys])

    def neighbors(self, key):
        return self.kvl.get(key, [])

    def __getitem__(self, key):
        return self.kvl[key][0]

    def restrict(self, other):
        if not isinstance(other, Graph):
            other = Graph(other)
        kvl = other.kvl
        return Graph([(k, v) for k, v in self if k in kvl])

    def __sub__(self, other):
        return Graph(Set(self) - Set(other))

    def __eq__(self, other):
        return Set(self) == Set(other)

    def __ne__(self, other):
        return Set(self) != Set(other)

    def __len__(self):
        return sum([len(v) for v in self.kvl.values()])

    def reachable(self, key):
        oldkey = key
        stack = [key]
        found = Set()
        add = found.add
        extend = stack.extend
        while stack:
            key = stack.pop()
            if key not in found:
                next = self.kvl.get(key, [])
                stack.extend(next)
                add(key)
        found.remove(oldkey)
        return found

    def __repr__(self):
        keys = list(self)
        keys.sort()
        return "Graph(%r)" % keys

    def __iter__(self):
        for k, vl in self.kvl.items():
            for v in vl:
                yield k, v

    def __setitem__(self, key, val):
        vl = self.kvl.setdefault(key, [])
        if val not in vl:
            vl.append(val)

    add = __setitem__

    def __invert__(self):
        return Graph([(v, k) for k, v in self])

    def __add__(self, other):
        return Graph(list(self) + list(other))

    def __iadd__(self, other):
        for k, v in other:
            self[k] = v
        return self

    __ior__ = __iadd__

    def __or__(self, other):
        return Graph(list(self) + list(other))

    def __mul__(self, other):
        if not isinstance(other, Graph):
            other = Graph(other)
        all = other.kvl
        return Graph([(k, v2) for k, v in self if v in all for v2 in all[v]])

    def __contains__(self, (key, val)):
        return val in self.kvl.get(key, ())
Beispiel #11
0
class Bootstrap(AbstractInterpreter):
    """Invoke and use an arbitrary 'IExecutable' object

    This class is designed to allow specification of an arbitrary
    name or URL on the command line to retrieve and invoke the
    designated object.

    If the name is not a scheme-prefixed URL, it is first converted to
    a name in the 'peak.running.shortcuts' configuration property namespace,
    thus allowing simpler names to be used.  For example, 'runIni' is a
    shortcut for '"import:peak.running.commands:IniInterpreter"'.  If you
    use a sitewide PEAK_CONFIG file, you can add your own shortcuts to
    the 'peak.running.shortcuts' namespace.  (See the 'peak.ini' file for
    current shortcuts, and examples of how to define them.)

    The object designated by the name or URL in 'argv[1]' must be an
    'IExecutable'; that is to say it must implement one of the 'IExecutable'
    sub-interfaces, or else be callable without arguments.  (See the
    'running.IExecutable' interface for more details.)

    Here's an example bootstrap script (which is installed as the 'peak'
    script by the PEAK distribution on 'posix' operating systems)::

        #!/usr/bin/env python2.2

        from peak.running import commands
        commands.runMain( commands.Bootstrap )

    The script above will look up its first supplied command line argument,
    and then invoke the found object as a command, supplying the remaining
    command line arguments.
    """

    acceptURLs = True

    def interpret(self, name):

        try:
            factory = lookupCommand(self,
                                    name,
                                    default=NoSuchSubcommand,
                                    acceptURLs=self.acceptURLs)
        except exceptions.InvalidName:
            factory = InvalidSubcommandName

        executable = ICmdLineAppFactory(factory, None)
        if executable is None:
            raise InvocationError("Invalid command object", factory,
                                  "found at", name)
        return self.getSubcommand(factory)

    cmdConfig = binding.Make(list, [
        options.Append('-c',
                       '--config',
                       type=str,
                       metavar="INI_FILE",
                       help=".ini-style configuration file(s) to load")
    ])

    decorate(binding.Make)

    def cmdParent(self):
        if self.cmdConfig:
            parent = config.ServiceArea(self)
            config.loadConfigFiles(parent, self.cmdConfig)
            return parent

    def getCommandParent(self):
        """Get or create a component to be used as the subcommand's parent"""
        # Default is to use the interpreter as the parent
        parent = self.cmdParent
        if parent is None:
            return self
        return parent

    usage = """
Usage: peak [options] NAME_OR_URL arguments...

The 'peak' script bootstraps and runs a specified command object or command
class.  The NAME_OR_URL argument may be a shortcut name defined in the
'peak.running.shortcuts' property namespace, or a URL of a type
supported by 'peak.naming'.  For example, if you have a class 'MyAppClass'
defined in 'MyPackage', you can use:

    peak import:MyPackage.MyAppClass

to invoke it.  Arguments to the found object are shifted left one position,
so in the example above it will see 'import:MyPackage.MyAppClass' as its
'argv[0]'.

The named object must implement one of the 'peak.running' command interfaces,
or be callable.  See the 'Bootstrap' class in 'peak.running.commands' for
more details on creating command objects for use with 'peak'.  For the
list of available shortcut names, see '%s'""" % config.packageFile(
        'peak', 'peak.ini').address

    if os.environ.get('PEAK_CONFIG'):
        usage += " and '%s'" % os.environ['PEAK_CONFIG']

    usage += ".\n"

    def showHelp(self):
        """Display usage message on stderr"""
        super(Bootstrap, self).showHelp()

        from peak.util.columns import lsFormat
        print >> self.stderr, "Available commands:"
        print >> self.stderr
        self.stderr.writelines(
            lsFormat(80,
                     config.Namespace('peak.running.shortcuts', self).keys()))
        print >> self.stderr
        return 0