[pypy-svn] r12709 - in pypy/dist/pypy: interpreter translator
arigo at codespeak.net
arigo at codespeak.net
Sat May 21 14:12:41 CEST 2005
Author: arigo
Date: Sat May 21 14:12:41 2005
New Revision: 12709
Removed:
pypy/dist/pypy/interpreter/gateway.py
pypy/dist/pypy/translator/geninterplevel.py
Log:
Reverting...
Deleted: /pypy/dist/pypy/interpreter/gateway.py
==============================================================================
--- /pypy/dist/pypy/interpreter/gateway.py Sat May 21 14:12:41 2005
+++ (empty file)
@@ -1,750 +0,0 @@
-"""
-
-Gateway between app-level and interpreter-level:
-* BuiltinCode (call interp-level code from app-level)
-* app2interp (embed an app-level function into an interp-level callable)
-* interp2app (publish an interp-level object to be visible from app-level)
-
-"""
-
-import types, sys, md5, os, autopath
-
-NoneNotWrapped = object()
-
-from pypy.tool.sourcetools import func_with_new_name
-from pypy.interpreter.error import OperationError
-from pypy.interpreter import eval
-from pypy.interpreter.function import Function, Method
-from pypy.interpreter.baseobjspace import W_Root, ObjSpace, BaseWrappable
-from pypy.interpreter.baseobjspace import Wrappable, SpaceCache
-from pypy.interpreter.argument import Arguments
-from pypy.tool.sourcetools import NiceCompile, compile2
-
-# internal non-translatable parts:
-import py
-
-class Signature:
- "NOT_RPYTHON"
- def __init__(self, func=None, argnames=None, varargname=None,
- kwargname=None, name = None):
- self.func = func
- if func is not None:
- self.name = func.__name__
- else:
- self.name = name
- if argnames is None:
- argnames = []
- self.argnames = argnames
- self.varargname = varargname
- self.kwargname = kwargname
-
- def next_arg(self):
- return self._argiter.next()
-
- def append(self, argname):
- self.argnames.append(argname)
-
- def signature(self):
- return self.argnames, self.varargname, self.kwargname
-
- def apply_unwrap_spec(self, unwrap_spec, recipe, new_sig):
- self._argiter = iter(self.argnames)
- for el in unwrap_spec:
- recipe(el, self, new_sig)
- return new_sig
-
-
-class UnwrapSpecRecipe:
- "NOT_RPYTHON"
-
- bases_order = [BaseWrappable, W_Root, ObjSpace, Arguments, object]
-
- def dispatch(self, meth_family, el, orig_sig, new_sig):
- if isinstance(el, str):
- getattr(self, "%s_%s" % (meth_family, el))(el, orig_sig, new_sig)
- elif isinstance(el, tuple):
- getattr(self, "%s_%s" % (meth_family, 'function'))(el, orig_sig, new_sig)
- else:
- for typ in self.bases_order:
- if issubclass(el, typ):
- getattr(self, "%s__%s" % (meth_family, typ.__name__))(el, orig_sig, new_sig)
- break
- else:
- assert False, "no match for unwrap_spec element: %s" % el
-
- def check(self, el, orig_sig, new_sig):
- self.dispatch("check", el, orig_sig, new_sig)
-
- def emit(self, el, orig_sig, new_sig):
- self.dispatch("emit", el, orig_sig, new_sig)
-
-
- # checks for checking interp2app func argument names wrt unwrap_spec
- # and synthetizing an app-level signature
-
- def check_function(self, (func, cls), orig_sig, app_sig):
- self.check(cls, orig_sig, app_sig)
-
- def check__BaseWrappable(self, el, orig_sig, app_sig):
- name = el.__name__
- argname = orig_sig.next_arg()
- assert not argname.startswith('w_'), (
- "unwrapped %s argument %s of built-in function %r should "
- "not start with 'w_'" % (name, argname, orig_sig.func))
- app_sig.append(argname)
-
- def check__ObjSpace(self, el, orig_sig, app_sig):
- orig_sig.next_arg()
-
- def check__W_Root(self, el, orig_sig, app_sig):
- assert el is W_Root, "oops"
- argname = orig_sig.next_arg()
- assert argname.startswith('w_'), (
- "argument %s of built-in function %r should "
- "start with 'w_'" % (argname, orig_sig.func))
- app_sig.append(argname[2:])
-
- def check__Arguments(self, el, orig_sig, app_sig):
- argname = orig_sig.next_arg()
- assert app_sig.varargname is None,(
- "built-in function %r has conflicting rest args specs" % orig_sig.func)
- app_sig.varargname = 'args'
- app_sig.kwargname = 'keywords'
-
- def check_starargs(self, el, orig_sig, app_sig):
- varargname = orig_sig.varargname
- assert varargname.endswith('_w'), (
- "argument *%s of built-in function %r should end in '_w'" %
- (varargname, orig_sig.func))
- assert app_sig.varargname is None,(
- "built-in function %r has conflicting rest args specs" % orig_sig.func)
- app_sig.varargname = varargname[:-2]
-
- def check_args_w(self, el, orig_sig, app_sig):
- argname = orig_sig.next_arg()
- assert argname.endswith('_w'), (
- "rest arguments arg %s of built-in function %r should end in '_w'" %
- (argname, orig_sig.func))
- assert app_sig.varargname is None,(
- "built-in function %r has conflicting rest args specs" % orig_sig.func)
- app_sig.varargname = argname[:-2]
-
- def check_w_args(self, el, orig_sig, app_sig):
- argname = orig_sig.next_arg()
- assert argname.startswith('w_'), (
- "rest arguments arg %s of built-in function %r should start 'w_'" %
- (argname, orig_sig.func))
- assert app_sig.varargname is None,(
- "built-in function %r has conflicting rest args specs" % orig_sig.func)
- app_sig.varargname = argname[2:]
-
- def check__object(self, el, orig_sig, app_sig):
- if el not in (int, str, float):
- assert False, "unsupported basic type in uwnrap_spec"
- name = el.__name__
- argname = orig_sig.next_arg()
- assert not argname.startswith('w_'), (
- "unwrapped %s argument %s of built-in function %r should "
- "not start with 'w_'" % (name, argname, orig_sig.func))
- app_sig.append(argname)
-
- # collect code to emit for interp2app builtin frames based on unwrap_spec
-
- def emit_function(self, (func, cls), orig_sig, emit_sig):
- name = func.__name__
- cur = emit_sig.through_scope_w
- emit_sig.setfastscope.append(
- "obj = %s(scope_w[%d])" % (name, cur))
- emit_sig.miniglobals[name] = func
- emit_sig.setfastscope.append(
- "self.%s_arg%d = obj" % (name,cur))
- emit_sig.through_scope_w += 1
- emit_sig.run_args.append("self.%s_arg%d" % (name,cur))
-
- def emit__BaseWrappable(self, el, orig_sig, emit_sig):
- name = el.__name__
- cur = emit_sig.through_scope_w
- emit_sig.setfastscope.append(
- "obj = self.space.interpclass_w(scope_w[%d])" % cur)
- emit_sig.setfastscope.append(
- "if obj is None or not isinstance(obj, %s):" % name)
- emit_sig.setfastscope.append(
- " raise OperationError(self.space.w_TypeError,self.space.wrap('expected %%s' %% %s.typedef.name ))" % name) # xxx
- emit_sig.miniglobals[name] = el
- emit_sig.miniglobals['OperationError'] = OperationError
- emit_sig.setfastscope.append(
- "self.%s_arg%d = obj" % (name,cur))
- emit_sig.through_scope_w += 1
- emit_sig.run_args.append("self.%s_arg%d" % (name,cur))
-
- def emit__ObjSpace(self, el, orig_sig, emit_sig):
- emit_sig.run_args.append('self.space')
-
- def emit__W_Root(self, el, orig_sig, emit_sig):
- cur = emit_sig.through_scope_w
- emit_sig.setfastscope.append(
- "self.w_arg%d = scope_w[%d]" % (cur,cur))
- emit_sig.through_scope_w += 1
- emit_sig.run_args.append("self.w_arg%d" % cur)
-
- def emit__Arguments(self, el, orig_sig, emit_sig):
- cur = emit_sig.through_scope_w
- emit_sig.through_scope_w += 2
- emit_sig.miniglobals['Arguments'] = Arguments
- emit_sig.setfastscope.append(
- "self.arguments_arg = "
- "Arguments.frompacked(self.space,scope_w[%d],scope_w[%d])"
- % (cur, cur+1))
- emit_sig.run_args.append("self.arguments_arg")
-
- def emit_starargs(self, el, orig_sig, emit_sig):
- emit_sig.setfastscope.append(
- "self.starargs_arg_w = self.space.unpacktuple(scope_w[%d])" %
- (emit_sig.through_scope_w))
- emit_sig.through_scope_w += 1
- emit_sig.run_args.append("*self.starargs_arg_w")
-
- def emit_args_w(self, el, orig_sig, emit_sig):
- emit_sig.setfastscope.append(
- "self.args_w = self.space.unpacktuple(scope_w[%d])" %
- (emit_sig.through_scope_w))
- emit_sig.through_scope_w += 1
- emit_sig.run_args.append("self.args_w")
-
- def emit_w_args(self, el, orig_sig, emit_sig):
- cur = emit_sig.through_scope_w
- emit_sig.setfastscope.append(
- "self.w_args = scope_w[%d]" % cur)
- emit_sig.through_scope_w += 1
- emit_sig.run_args.append("self.w_args")
-
- def emit__object(self, el, orig_sig, emit_sig):
- if el not in (int, str, float):
- assert False, "unsupported basic type in uwnrap_spec"
- name = el.__name__
- cur = emit_sig.through_scope_w
- emit_sig.setfastscope.append(
- "self.%s_arg%d = self.space.%s_w(scope_w[%d])" %
- (name,cur,name,cur))
- emit_sig.through_scope_w += 1
- emit_sig.run_args.append("self.%s_arg%d" % (name,cur))
-
-class BuiltinFrame(eval.Frame):
- "Frame emulation for BuiltinCode."
- # Subclasses of this are defined with the function to delegate to attached through miniglobals.
- # Initialization of locals is already done by the time run() is called,
- # via the interface defined in eval.Frame.
-
- def setfastscope(self, scope_w):
- """Subclasses with behavior specific for an unwrap spec are generated"""
- raise TypeError, "abstract"
-
- def getfastscope(self):
- raise OperationError(self.space.w_TypeError,
- self.space.wrap("cannot get fastscope of a BuiltinFrame"))
-
- def run(self):
- try:
- w_result = self._run()
- except KeyboardInterrupt:
- raise OperationError(self.space.w_KeyboardInterrupt, self.space.w_None)
- except MemoryError:
- raise OperationError(self.space.w_MemoryError, self.space.w_None)
- except RuntimeError, e:
- raise OperationError(self.space.w_RuntimeError,
- self.space.wrap("internal error: " + str(e)))
- if w_result is None:
- w_result = self.space.w_None
- return w_result
-
- def _run(self):
- """Subclasses with behavior specific for an unwrap spec are generated"""
- raise TypeError, "abstract"
-
-class FuncBox(object):
- pass
-
-class BuiltinCodeSignature(Signature):
- "NOT_RPYTHON"
-
- def __init__(self,*args,**kwds):
- self.unwrap_spec = kwds.get('unwrap_spec')
- del kwds['unwrap_spec']
- Signature.__init__(self,*args,**kwds)
- self.setfastscope = []
- self.run_args = []
- self.through_scope_w = 0
- self.miniglobals = {}
-
- def _make_unwrap_frame_class(self, cache={}):
- try:
- key = tuple(self.unwrap_spec)
- frame_cls, box_cls, run_args = cache[key]
- assert run_args == self.run_args,"unexpected: same spec, different run_args"
- return frame_cls, box_cls
- except KeyError:
- parts = []
- for el in self.unwrap_spec:
- if isinstance(el, tuple):
- parts.append(''.join([getattr(subel, '__name__', subel) for subel in el]))
- else:
- parts.append(getattr(el, '__name__', el))
- label = '_'.join(parts)
- #print label
- setfastscope = self.setfastscope
- if not setfastscope:
- setfastscope = ["pass"]
- setfastscope = ["def setfastscope_UWS_%s(self, scope_w):" % label,
- #"print 'ENTER',self.code.func.__name__",
- #"print scope_w"
- ] + setfastscope
- setfastscope = '\n '.join(setfastscope)
- # Python 2.2 SyntaxError without newline: Bug #501622
- setfastscope += '\n'
- d = {}
- exec compile2(setfastscope) in self.miniglobals, d
- d['setfastscope'] = d['setfastscope_UWS_%s' % label]
- del d['setfastscope_UWS_%s' % label]
-
- self.miniglobals['OperationError'] = OperationError
- source = """if 1:
- def _run_UWS_%s(self):
- return self.box.func(%s)
- \n""" % (label, ','.join(self.run_args))
- exec compile2(source) in self.miniglobals, d
- d['_run'] = d['_run_UWS_%s' % label]
- del d['_run_UWS_%s' % label]
- frame_cls = type("BuiltinFrame_UWS_%s" % label, (BuiltinFrame,), d)
- box_cls = type("FuncBox_UWS_%s" % label, (FuncBox,), {})
- cache[key] = frame_cls, box_cls, self.run_args
- return frame_cls, box_cls
-
- def make_frame_class(self, func, cache={}):
- frame_uw_cls, box_cls = self._make_unwrap_frame_class()
- box = box_cls()
- box.func = func
- return type("BuiltinFrame_for_%s" % self.name,
- (frame_uw_cls,),{'box': box})
-
-def make_builtin_frame_class(func, orig_sig, unwrap_spec):
- "NOT_RPYTHON"
- name = (getattr(func, '__module__', None) or '')+'_'+func.__name__
- emit_sig = orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpecRecipe().emit,
- BuiltinCodeSignature(name=name, unwrap_spec=unwrap_spec))
- cls = emit_sig.make_frame_class(func)
- return cls
-
-
-
-class BuiltinCode(eval.Code):
- "The code object implementing a built-in (interpreter-level) hook."
-
- # When a BuiltinCode is stored in a Function object,
- # you get the functionality of CPython's built-in function type.
-
- def __init__(self, func, unwrap_spec = None, self_type = None):
- "NOT_RPYTHON"
- # 'implfunc' is the interpreter-level function.
- # Note that this uses a lot of (construction-time) introspection.
- eval.Code.__init__(self, func.__name__)
- self.docstring = func.__doc__
-
- # unwrap_spec can be passed to interp2app or
- # attached as an attribute to the function.
- # It is a list of types or singleton objects:
- # baseobjspace.ObjSpace is used to specify the space argument
- # baseobjspace.W_Root is for wrapped arguments to keep wrapped
- # baseobjspace.BaseWrappable subclasses imply interpclass_w and a typecheck
- # argument.Arguments is for a final rest arguments Arguments object
- # 'args_w' for unpacktuple applied to rest arguments
- # 'w_args' for rest arguments passed as wrapped tuple
- # str,int,float: unwrap argument as such type
- # (function, cls) use function to check/unwrap argument of type cls
-
- # First extract the signature from the (CPython-level) code object
- from pypy.interpreter import pycode
- argnames, varargname, kwargname = pycode.cpython_code_signature(func.func_code)
-
- if unwrap_spec is None:
- unwrap_spec = getattr(func,'unwrap_spec',None)
-
- if unwrap_spec is None:
- unwrap_spec = [ObjSpace]+ [W_Root] * (len(argnames)-1)
-
- if self_type:
- unwrap_spec = ['self'] + unwrap_spec[1:]
-
- if self_type:
- assert unwrap_spec[0] == 'self',"self_type without 'self' spec element"
- unwrap_spec = list(unwrap_spec)
- unwrap_spec[0] = self_type
-
- orig_sig = Signature(func, argnames, varargname, kwargname)
-
- app_sig = orig_sig.apply_unwrap_spec(unwrap_spec, UnwrapSpecRecipe().check,
- Signature(func))
-
- self.sig = argnames, varargname, kwargname = app_sig.signature()
-
- self.minargs = len(argnames)
- if varargname:
- self.maxargs = sys.maxint
- else:
- self.maxargs = self.minargs
-
- self.framecls = make_builtin_frame_class(func, orig_sig, unwrap_spec)
-
- def create_frame(self, space, w_globals, closure=None):
- return self.framecls(space, self, w_globals)
-
- def signature(self):
- return self.sig
-
- def getdocstring(self):
- return self.docstring
-
-
-class interp2app(Wrappable):
- """Build a gateway that calls 'f' at interp-level."""
-
- # NOTICE interp2app defaults are stored and passed as
- # wrapped values, this to avoid having scope_w be of mixed
- # wrapped and unwrapped types;
- # an exception is made for the NoneNotWrapped special value
- # which is passed around as default as an unwrapped None,
- # unwrapped None and wrapped types are compatible
- #
- # Takes optionally an unwrap_spec, see BuiltinCode
-
- NOT_RPYTHON_ATTRIBUTES = ['_staticdefs']
-
- def __init__(self, f, app_name=None, unwrap_spec = None):
- "NOT_RPYTHON"
- Wrappable.__init__(self)
- # f must be a function whose name does NOT start with 'app_'
- self_type = None
- if hasattr(f, 'im_func'):
- self_type = f.im_class
- f = f.im_func
- if not isinstance(f, types.FunctionType):
- raise TypeError, "function expected, got %r instead" % f
- if app_name is None:
- if f.func_name.startswith('app_'):
- raise ValueError, ("function name %r suspiciously starts "
- "with 'app_'" % f.func_name)
- app_name = f.func_name
- self._code = BuiltinCode(f, unwrap_spec=unwrap_spec, self_type = self_type)
- self.__name__ = f.func_name
- self.name = app_name
- self._staticdefs = list(f.func_defaults or ())
-
- def _getdefaults(self, space):
- "NOT_RPYTHON"
- defs_w = []
- for val in self._staticdefs:
- if val is NoneNotWrapped:
- defs_w.append(None)
- else:
- defs_w.append(space.wrap(val))
- return defs_w
-
- # lazy binding to space
-
- def __spacebind__(self, space):
- # we first make a real Function object out of it
- # and the result is a wrapped version of this Function.
- return self.get_function(space)
-
- def get_function(self, space):
- return self.getcache(space).getorbuild(self)
-
- def getcache(self, space):
- return space.fromcache(GatewayCache)
-
- def get_method(self, obj):
- # to bind this as a method out of an instance, we build a
- # Function and get it.
- # the object space is implicitely fetched out of the instance
- assert self._code.ismethod, (
- 'global built-in function %r used as method' %
- self._code.func)
-
- space = obj.space
- fn = self.get_function(space)
- w_obj = space.wrap(obj)
- return Method(space, space.wrap(fn),
- w_obj, space.type(w_obj))
-
-
-class GatewayCache(SpaceCache):
- def build(cache, gateway):
- "NOT_RPYTHON"
- space = cache.space
- defs = gateway._getdefaults(space) # needs to be implemented by subclass
- code = gateway._code
- fn = Function(space, code, None, defs, forcename = gateway.name)
- return fn
-
-
-#
-# the next gateways are to be used only for
-# temporary/initialization purposes
-
-class interp2app_temp(interp2app):
- "NOT_RPYTHON"
- def getcache(self, space):
- return self.__dict__.setdefault(space, GatewayCache(space))
-
-
-# and now for something completely different ...
-#
-
-class ApplevelClass:
- """A container for app-level source code that should be executed
- as a module in the object space; interphook() builds a static
- interp-level function that invokes the callable with the given
- name at app-level."""
-
- hidden_applevel = True
- use_geninterp = True # change this to disable geninterp globally
-
- def __init__(self, source, filename = None, modname = '__builtin__'):
- self.filename = filename
- self.source = source
- self.modname = modname
- # look at the first three lines for a NOT_RPYTHON tag
- first = "\n".join(source.split("\n", 3)[:3])
- if "NOT_RPYTHON" in first:
- self.use_geninterp = False
-
- def getwdict(self, space):
- return space.fromcache(ApplevelCache).getorbuild(self)
-
- def buildmodule(self, space, name='applevel'):
- from pypy.interpreter.module import Module
- return Module(space, space.wrap(name), self.getwdict(space))
-
- def wget(self, space, name):
- w_globals = self.getwdict(space)
- return space.getitem(w_globals, space.wrap(name))
-
- def interphook(self, name):
- "NOT_RPYTHON"
- def appcaller(space, *args_w):
- if not isinstance(space, ObjSpace):
- raise TypeError("first argument must be a space instance.")
- # redirect if the space handles this specially XXX can this be factored a bit less flow space dependetly
- if hasattr(space, 'specialcases'):
- sc = space.specialcases
- if ApplevelClass in sc:
- ret_w = sc[ApplevelClass](space, self, name, args_w)
- if ret_w is not None: # it was RPython
- return ret_w
- args = Arguments(space, list(args_w))
- w_func = self.wget(space, name)
- return space.call_args(w_func, args)
- def get_function(space):
- w_func = self.wget(space, name)
- return space.unwrap(w_func)
- appcaller = func_with_new_name(appcaller, name)
- appcaller.get_function = get_function
- return appcaller
-
- def _freeze_(self):
- return True # hint for the annotator: applevel instances are constants
-
-
-class ApplevelCache(SpaceCache):
- """The cache mapping each applevel instance to its lazily built w_dict"""
-
- def build(self, app):
- "NOT_RPYTHON. Called indirectly by Applevel.getwdict()."
- if app.use_geninterp:
- return PyPyCacheDir.build_applevelinterp_dict(app, self.space)
- else:
- return build_applevel_dict(app, self.space)
-
-
-# __________ pure applevel version __________
-
-def build_applevel_dict(self, space):
- "NOT_RPYTHON"
- if self.filename is None:
- code = py.code.Source(self.source).compile()
- else:
- code = NiceCompile(self.filename)(self.source)
-
- from pypy.interpreter.pycode import PyCode
- pycode = PyCode(space)._from_code(code, hidden_applevel=self.hidden_applevel)
- w_glob = space.newdict([])
- space.setitem(w_glob, space.wrap('__name__'), space.wrap('__builtin__'))
- space.exec_(pycode, w_glob, w_glob)
- return w_glob
-
-# __________ geninterplevel version __________
-
-class PyPyCacheDir:
- # similar to applevel, but using translation to interp-level.
- # This version maintains a cache folder with single files.
-
- def build_applevelinterp_dict(cls, self, space):
- "NOT_RPYTHON"
- # N.B. 'self' is the ApplevelInterp; this is a class method,
- # just so that we have a convenient place to store the global state.
- if not cls._setup_done:
- cls._setup()
-
- from pypy.translator.geninterplevel import translate_as_module
-
- # XXX HACK HACK HACK XXX
- # XXX allow the app-level code to contain e.g. "import _formatting"
- libdir = os.path.join(autopath.pypydir, "lib")
- sys.path.append(libdir)
- try:
- scramble = md5.new(cls.seed)
- scramble.update(self.source)
- key = scramble.hexdigest()
- initfunc = cls.known_source.get(key)
- if not initfunc:
- # try to get it from file
- name = key
- if self.filename:
- prename = os.path.splitext(os.path.basename(self.filename))[0]
- else:
- prename = 'zznoname'
- name = "%s_%s" % (prename, name)
- try:
- __import__("pypy._cache."+name)
- except ImportError, x:
- # print x
- pass
- else:
- initfunc = cls.known_source[key]
- if not initfunc:
- # build it and put it into a file
- initfunc, newsrc = translate_as_module(
- self.source, self.filename, self.modname)
- fname = cls.cache_path.join(name+".py").strpath
- f = file(fname, "w")
- print >> f, """\
-# self-destruct on double-click:
-if __name__ == "__main__":
- from pypy import _cache
- import os
- namestart = os.path.join(os.path.split(_cache.__file__)[0], '%s')
- for ending in ('.py', '.pyc', '.pyo'):
- try:
- os.unlink(namestart+ending)
- except os.error:
- pass""" % name
- print >> f
- print >> f, newsrc
- print >> f, "from pypy._cache import known_source"
- print >> f, "known_source[%r] = %s" % (key, initfunc.__name__)
- w_glob = initfunc(space)
- finally:
- if libdir in sys.path:
- sys.path.remove(libdir)
- return w_glob
- build_applevelinterp_dict = classmethod(build_applevelinterp_dict)
-
- _setup_done = False
-
- def _setup(cls):
- """NOT_RPYTHON"""
- lp = py.path.local
- import pypy, os
- p = lp(pypy.__file__).new(basename='_cache').ensure(dir=1)
- cls.cache_path = p
- ini = p.join('__init__.py')
- try:
- if not ini.check():
- raise ImportError # don't import if only a .pyc file left!!!
- from pypy._cache import known_source, \
- GI_VERSION_RENDERED
- except ImportError:
- GI_VERSION_RENDERED = 0
- from pypy.translator.geninterplevel import GI_VERSION
- cls.seed = md5.new(str(GI_VERSION)).digest()
- if GI_VERSION != GI_VERSION_RENDERED or GI_VERSION is None:
- for pth in p.listdir():
- try:
- pth.remove()
- except: pass
- file(str(ini), "w").write("""\
-# This folder acts as a cache for code snippets which have been
-# compiled by compile_as_module().
-# It will get a new entry for every piece of code that has
-# not been seen, yet.
-#
-# Caution! Only the code snippet is checked. If something
-# is imported, changes are not detected. Also, changes
-# to geninterplevel or gateway are also not checked.
-# Exception: There is a checked version number in geninterplevel.py
-#
-# If in doubt, remove this file from time to time.
-
-GI_VERSION_RENDERED = %r
-
-known_source = {}
-
-# self-destruct on double-click:
-def harakiri():
- import pypy._cache as _c
- import py
- lp = py.path.local
- for pth in lp(_c.__file__).dirpath().listdir():
- try:
- pth.remove()
- except: pass
-
-if __name__ == "__main__":
- harakiri()
-
-del harakiri
-""" % GI_VERSION)
- import pypy._cache
- cls.known_source = pypy._cache.known_source
- cls._setup_done = True
- _setup = classmethod(_setup)
-
-# ____________________________________________________________
-
-def appdef(source, applevel=ApplevelClass):
- """ NOT_RPYTHON: build an app-level helper function, like for example:
- myfunc = appdef('''myfunc(x, y):
- return x+y
- ''')
- """
- from pypy.interpreter.pycode import PyCode
- if not isinstance(source, str):
- source = str(py.code.Source(source).strip())
- assert source.startswith("def "), "can only transform functions"
- source = source[4:]
- p = source.find('(')
- assert p >= 0
- funcname = source[:p].strip()
- source = source[p:]
- return applevel("def %s%s\n" % (funcname, source)).interphook(funcname)
-
-applevel = ApplevelClass # backward compatibility
-app2interp = appdef # backward compatibility
-
-
-class applevel_temp(ApplevelClass):
- hidden_applevel = False
- def getwdict(self, space): # no cache
- return build_applevel_dict(self, space)
-
-if ApplevelClass.use_geninterp:
- class applevelinterp_temp(ApplevelClass):
- hidden_applevel = False
- def getwdict(self, space): # no cache
- return PyPyCacheDir.build_applevelinterp_dict(self, space)
-else:
- applevelinterp_temp = applevel_temp
-
-# app2interp_temp is used for testing mainly
-def app2interp_temp(func, applevel_temp=applevel_temp):
- """ NOT_RPYTHON """
- return appdef(func, applevel_temp)
Deleted: /pypy/dist/pypy/translator/geninterplevel.py
==============================================================================
--- /pypy/dist/pypy/translator/geninterplevel.py Sat May 21 14:12:41 2005
+++ (empty file)
@@ -1,1366 +0,0 @@
-"""
-Implementation of a translator from application Python to
-interpreter level RPython.
-
-The idea is that we can automatically transform application level
-implementations of methods into some equivalent representation at
-interpreter level. Then, the RPython to C translation might
-hopefully spit out some more efficient code than always interpreting
-these methods.
-
-Note that the application level functions are treated as rpythonic,
-in a sense that globals are constants, for instance. This definition
-is not exact and might change.
-
-The interface for this module is
-
- (initfunc, newsrc) = translate_as_module(
- sourcetext,
- filename=None,
- modname="app2interpexec",
- tmpname=None)
-
-If filename is given, it is used as a reference where
-this sourcetext can be literally found, to produce
-real line numbers. It cannot be just any name but
-must exist and contain the source code somewhere.
-
-modname is optional and will be put into the dictionary
-to be created.
-
-tmpname is optional. If given, a temporary file will
-be created for debugging purposes.
-
-The returned newsrc is the generated source text.
-It is used in gateway.py's caching mechanism.
-The initfunc result is a function named "init"+modname
-It must be called with a space instance and returns
-a wrapped dict which is suitable to use as a module dict,
-containing all trnaslatedobjects with their originalname.
-
-Integration of this module is finished.
-There are no longer hand-generated source
-pieces in pypy svn.
-"""
-
-from __future__ import generators
-import autopath, os, sys, exceptions, inspect, types
-import cPickle as pickle, __builtin__
-from copy_reg import _HEAPTYPE
-from pypy.objspace.flow.model import Variable, Constant, SpaceOperation
-from pypy.objspace.flow.model import FunctionGraph, Block, Link
-from pypy.objspace.flow.model import last_exception
-from pypy.objspace.flow.model import traverse, uniqueitems, checkgraph
-from pypy.interpreter.pycode import CO_VARARGS, CO_VARKEYWORDS
-from pypy.annotation import model as annmodel
-from types import FunctionType, CodeType, ModuleType
-from pypy.interpreter.error import OperationError
-from pypy.interpreter.argument import Arguments
-from pypy.rpython.rarithmetic import r_int, r_uint
-
-from pypy.translator.translator import Translator
-from pypy.objspace.flow import FlowObjSpace
-
-from pypy.tool.sourcetools import render_docstr, NiceCompile
-
-from pypy.translator.gensupp import ordered_blocks, UniqueList, builtin_base, \
- c_string, uniquemodulename, C_IDENTIFIER, NameManager
-
-
-# list of simplifcation passes needed by geninterp
-from pypy.translator.simplify import transform_ovfcheck, all_passes as needed_passes
-
-needed_passes = needed_passes[:]
-needed_passes.remove(transform_ovfcheck)
-
-
-import pypy # __path__
-import py.path
-
-GI_VERSION = '1.1.0' # bump this for substantial changes
-# ____________________________________________________________
-
-def eval_helper(self, typename, expr):
- name = self.uniquename("gtype_%s" % typename)
- unique = self.uniquenameofprebuilt("eval_helper", eval_helper)
- self.initcode.append1(
- 'def %s(expr):\n'
- ' dic = space.newdict([])\n'
- ' if "types." in expr:\n'
- ' space.exec_("import types", dic, dic)\n'
- ' else:\n'
- ' space.exec_("", dic, dic)\n'
- ' return space.eval(expr, dic, dic)' % (unique, ))
- self.initcode.append1('%s = %s(%r)' % (name, unique, expr))
- return name
-
-def unpickle_helper(self, name, value):
- unique = self.uniquenameofprebuilt("unpickle_helper", unpickle_helper)
- self.initcode.append1(
- 'def %s(value):\n'
- ' dic = space.newdict([])\n'
- ' space.exec_("import cPickle as pickle", dic, dic)\n'
- ' return space.eval("pickle.loads(%%r)" %% value, dic, dic)' % unique)
- self.initcode.append1('%s = %s(%r)' % (
- name, unique, pickle.dumps(value, 2)) )
-
-# hey, for longs we can do even easier:
-def long_helper(self, name, value):
- unique = self.uniquenameofprebuilt("long_helper", long_helper)
- self.initcode.append1(
- 'def %s(value):\n'
- ' dic = space.newdict([])\n'
- ' space.exec_("", dic, dic) # init __builtins__\n'
- ' return space.eval("long(%%r, 16)" %% value, dic, dic)' % unique)
- self.initcode.append1('%s = %s(%r)' % (
- name, unique, hex(value)[2:-1] ) )
-
-def bltinmod_helper(self, mod):
- name = self.uniquename("mod_%s" % mod.__name__)
- unique = self.uniquenameofprebuilt("bltinmod_helper", bltinmod_helper)
- self.initcode.append1(
- 'def %s(name):\n'
- ' dic = space.newdict([])\n'
- ' space.exec_("import %%s" %% name, dic, dic)\n'
- ' return space.eval("%%s" %% name, dic, dic)' % (unique, ))
- self.initcode.append1('%s = %s(%r)' % (name, unique, mod.__name__))
- return name
-
-class GenRpy:
- def __init__(self, translator, entrypoint=None, modname=None, moddict=None):
- self.translator = translator
- if entrypoint is None:
- entrypoint = translator.entrypoint
- self.entrypoint = entrypoint
- self.modname = self.trans_funcname(modname or
- uniquemodulename(entrypoint))
- self.moddict = moddict # the dict if we translate a module
-
- def late_OperationError():
- self.initcode.append1(
- 'from pypy.interpreter.error import OperationError as gOperationError')
- return 'gOperationError'
- def late_Arguments():
- self.initcode.append1('from pypy.interpreter import gateway')
- return 'gateway.Arguments'
-
- self.rpynames = {Constant(None).key: 'space.w_None',
- Constant(False).key: 'space.w_False',
- Constant(True).key: 'space.w_True',
- Constant(OperationError).key: late_OperationError,
- Constant(Arguments).key: late_Arguments,
- }
- u = UniqueList
- self.initcode = u() # list of lines for the module's initxxx()
- self.latercode = u() # list of generators generating extra lines
- # for later in initxxx() -- for recursive
- # objects
- self.namespace = NameManager()
- self.namespace.make_reserved_names('__doc__ __args__ space goto')
- self.globaldecl = []
- self.globalobjects = []
- self.pendingfunctions = []
- self.currentfunc = None
- self.debugstack = () # linked list of nested nameof()
-
- # special constructors:
- self.has_listarg = {}
- for name in "newtuple newlist newdict newstring".split():
- self.has_listarg[name] = name
-
- # catching all builtins in advance, to avoid problems
- # with modified builtins
-
- # add a dummy _issubtype() to builtins
- def _issubtype(cls1, cls2):
- raise TypeError, "this dummy should *not* be reached"
- __builtin__._issubtype = _issubtype
-
- class bltinstub:
- def __init__(self, name):
- self.__name__ = name
- def __repr__(self):
- return '<%s>' % self.__name__
-
- self.builtin_ids = dict( [
- (id(value), bltinstub(key))
- for key, value in __builtin__.__dict__.items()
- if callable(value) and type(value) not in [type(Exception), type] ] )
-
- self.space = FlowObjSpace() # for introspection
-
- self.use_fast_call = True
- self.specialize_goto = False
- self._labeltable = {} # unique label names, reused per func
-
- self._space_arities = None
-
- def expr(self, v, localscope, wrapped = True):
- if isinstance(v, Variable):
- return localscope.localname(v.name, wrapped)
- elif isinstance(v, Constant):
- return self.nameof(v.value,
- debug=('Constant in the graph of', self.currentfunc))
- else:
- raise TypeError, "expr(%r)" % (v,)
-
- def arglist(self, args, localscope):
- res = [self.expr(arg, localscope) for arg in args]
- return ", ".join(res)
-
- def oper(self, op, localscope):
- if op.opname == "simple_call":
- v = op.args[0]
- space_shortcut = self.try_space_shortcut_for_builtin(v, len(op.args)-1)
- if space_shortcut is not None:
- # space method call
- exv = space_shortcut
- fmt = "%(res)s = %(func)s(%(args)s)"
- else:
- exv = self.expr(v, localscope)
- # default for a spacecall:
- fmt = "%(res)s = space.call_function(%(func)s, %(args)s)"
- # see if we can optimize for a fast call.
- # we just do the very simple ones.
- if self.use_fast_call and (isinstance(v, Constant)
- and exv.startswith('gfunc_')):
- func = v.value
- if (not func.func_code.co_flags & CO_VARARGS) and (
- func.func_defaults is None):
- fmt = "%(res)s = fastf_%(func)s(space, %(args)s)"
- exv = exv[6:]
- return fmt % {"res" : self.expr(op.result, localscope),
- "func": exv,
- "args": self.arglist(op.args[1:], localscope) }
- if op.opname == "call_args":
- v = op.args[0]
- exv = self.expr(v, localscope)
- fmt = (
- "_args = %(Arg)s.fromshape(space, %(shape)s, [%(data_w)s])\n"
- "%(res)s = space.call_args(%(func)s, _args)")
- assert isinstance(op.args[1], Constant)
- shape = op.args[1].value
- return fmt % {"res": self.expr(op.result, localscope),
- "func": exv,
- "shape": repr(shape),
- "data_w": self.arglist(op.args[2:], localscope),
- 'Arg': self.nameof(Arguments) }
- if op.opname in self.has_listarg:
- fmt = "%s = %s([%s])"
- else:
- fmt = "%s = %s(%s)"
- # special case is_true
- wrapped = op.opname != "is_true"
- oper = "space.%s" % op.opname
- return fmt % (self.expr(op.result, localscope, wrapped), oper,
- self.arglist(op.args, localscope))
-
- def large_assignment(self, left, right, margin=65):
- expr = "(%s) = (%s)" % (", ".join(left), ", ".join(right))
- pieces = expr.split(",")
- res = [pieces.pop(0)]
- for piece in pieces:
- if len(res[-1])+len(piece)+1 > margin:
- res[-1] += ","
- res.append(piece)
- else:
- res[-1] += (","+piece)
- return res
-
- def large_initialize(self, vars, margin=65):
- res = []
- nonestr = "None"
- margin -= len(nonestr)
- for var in vars:
- ass = var+"="
- if not res or len(res[-1]) >= margin:
- res.append(ass)
- else:
- res[-1] += ass
- res = [line + nonestr for line in res]
- return res
-
- def mklabel(self, blocknum):
- if self.specialize_goto:
- lbname = self._labeltable.get(blocknum)
- if not lbname:
- self.initcode.append1(
- 'from pypy.objspace.flow.framestate import SpecTag')
- lbname = self.uniquename("glabel_%d" % blocknum)
- self._labeltable[blocknum] = lbname
- self.initcode.append1('%s = SpecTag()' % lbname)
- return lbname
- else:
- return repr(blocknum)
-
- def gen_link(self, link, localscope, blocknum, block, linklocalvars=None):
- "Generate the code to jump across the given Link."
- linklocalvars = linklocalvars or {}
- left, right = [], []
- for a1, a2 in zip(link.args, link.target.inputargs):
- if a1 in linklocalvars:
- src = linklocalvars[a1]
- else:
- src = self.expr(a1, localscope)
- left.append(self.expr(a2, localscope))
- right.append(src)
- if left: # anything at all?
- txt = "%s = %s" % (", ".join(left), ", ".join(right))
- if len(txt) <= 65: # arbitrary
- yield txt
- else:
- for line in self.large_assignment(left, right):
- yield line
- goto = blocknum[link.target]
- yield 'goto = %s' % self.mklabel(goto)
- if goto <= blocknum[block]:
- yield 'continue'
-
- def register_early(self, obj, name):
- # this was needed for recursive lists.
- # note that self.latercode led to too late initialization.
- key = Constant(obj).key
- self.rpynames[key] = name
-
- def nameof(self, obj, debug=None, namehint=None):
- key = Constant(obj).key
- try:
- txt = self.rpynames[key]
- if type(txt) is not str:
- # this is a predefined constant, initialized on first use
- func = txt
- txt = func()
- self.rpynames[key] = txt
- return txt
-
- except KeyError:
- if debug:
- stackentry = debug, obj
- else:
- stackentry = obj
- self.debugstack = (self.debugstack, stackentry)
- obj_builtin_base = builtin_base(obj)
- if obj_builtin_base in (object, int, long) and type(obj) is not obj_builtin_base:
- # assume it's a user defined thingy
- name = self.nameof_instance(obj)
- else:
- # shortcutting references to __builtin__
- if id(obj) in self.builtin_ids:
- func = self.builtin_ids[id(obj)]
- name = "(space.builtin.get(space.str_w(%s)))" % self.nameof(func.__name__)
- else:
- for cls in type(obj).__mro__:
- meth = getattr(self,
- 'nameof_' + cls.__name__.replace(' ', ''),
- None)
- if meth:
- break
- else:
- raise Exception, "nameof(%r)" % (obj,)
-
- code = meth.im_func.func_code
- if namehint and 'namehint' in code.co_varnames[:code.co_argcount]:
- name = meth(obj, namehint=namehint)
- else:
- name = meth(obj)
- self.debugstack, x = self.debugstack
- assert x is stackentry
- self.rpynames[key] = name
- return name
-
- def uniquename(self, basename):
- name = self.namespace.uniquename(basename)
- self.globalobjects.append(name)
- self.globaldecl.append('# global object %s' % (name,))
- return name
-
- def uniquenameofprebuilt(self, basename, obj):
- # identifying an object and giving it a name,
- # without the attempt to render it.
- key = Constant(obj).key
- try:
- txt = self.rpynames[key]
- except KeyError:
- self.rpynames[key] = txt = self.uniquename(basename)
- return txt
-
-
- def nameof_NotImplementedType(self, value):
- return "space.w_NotImplemented"
-
- def nameof_object(self, value):
- if type(value) is not object:
- # try to just wrap it?
- name = self.uniquename('g_%sinst_%r' % (type(value).__name__, value))
- self.initcode.append1('%s = space.wrap(%r)' % (name, value))
- return name
- name = self.uniquename('g_object')
- self.initcode.append('_tup = space.newtuple([])\n'
- '%s = space.call(space.w_object, _tup)'
- % name)
- return name
-
- def nameof_module(self, value):
- if value is os or not hasattr(value, "__file__") or \
- not (value.__file__.endswith('.pyc') or
- value.__file__.endswith('.py') or
- value.__file__.endswith('.pyo')) :
- return bltinmod_helper(self, value)
- # we might have createda reference to a module
- # that is non-standard.
- # check whether we can import
- try:
- import value
- need_extra_path = False
- except ImportError:
- need_extra_path = True
- name = self.uniquename('mod_%s' % value.__name__)
- if need_extra_path:
- self.initcode.append1('import pypy')
- self.initcode.append1('import sys')
- self.initcode.append1('import os')
- self.initcode.append1('libdir = os.path.join(pypy.__path__[0], "lib")\n'
- 'hold = sys.path[:]\n'
- 'sys.path.insert(0, libdir)\n'
- 'import %s as _tmp\n'
- 'sys.path[:] = hold\n' % value.__name__)
- else:
- self.initcode.append1('import %s as _tmp' % value.__name__)
- self.initcode.append1('%s = space.wrap(_tmp)' % (name))
- return name
-
-
- def nameof_int(self, value):
- if value >= 0:
- name = 'gi_%d' % value
- else:
- # make sure that the type ident is completely described by
- # the prefixbefore the initial '_' for easy postprocessing
- name = 'gi_minus_%d' % abs(value)
- name = self.uniquename(name)
- self.initcode.append1('%s = space.wrap(%d)' % (name, value))
- return name
-
- def nameof_long(self, value):
- # assume we want them in hex most of the time
- if value < 256L:
- s = "%dL" % value
- else:
- s = "0x%08xL" % value
- if value >= 0:
- name = 'glong_%s' % s
- else:
- # mae sure that the type ident is completely described by
- # the prefix before the initial '_'
- name = 'glong_minus_%d' % abs(value)
- name = self.uniquename(name)
- # allow literally short longs only, meaning they
- # must fit into a machine word.
- if (sys.maxint*2+1)&value == value:
- self.initcode.append1('%s = space.wrap(%s) # XXX implement long!' % (name, s))
- else:
- long_helper(self, name, value)
- return name
-
- def nameof_float(self, value):
- name = 'gfloat_%s' % value
- name = (name.replace('-', 'minus')
- .replace('.', 'dot'))
- name = self.uniquename(name)
- self.initcode.append1('%s = space.wrap(%r)' % (name, value))
- return name
-
- def nameof_str(self, value):
- if [c for c in value if c<' ' or c>'~' or c=='"' or c=='\\']:
- # non-printable string
- namestr = repr(value)[1:-1]
- else:
- # printable string
- namestr = value
- if not namestr:
- namestr = "_emptystr_"
- name = self.uniquename('gs_' + namestr[:32])
- if len(value) < 30 and "\n" not in value:
- txt = '%s = space.wrap(%r)' % (name, value)
- else:
- txt = render_docstr(value, '%s = space.wrap(\n' % name, ')')
- txt = txt, # not splitted
- self.initcode.append(txt)
- return name
-
- def skipped_function(self, func):
- # debugging only! Generates a placeholder for missing functions
- # that raises an exception when called.
- name = self.uniquename('gskippedfunc_' + func.__name__)
- self.globaldecl.append('# global decl %s' % (name, ))
- self.initcode.append('# build func %s' % name)
- return name
-
- def skipped_class(self, cls):
- # debugging only! Generates a placeholder for missing classes
- # that raises an exception when called.
- name = self.uniquename('gskippedclass_' + cls.__name__)
- self.globaldecl.append('# global decl %s' % (name, ))
- self.initcode.append1('# build class %s' % name)
- return name
-
- def trans_funcname(self, s):
- return s.translate(C_IDENTIFIER)
-
- def nameof_function(self, func, namehint=''):
- if hasattr(func, 'geninterplevel_name'):
- return func.geninterplevel_name(self)
-
- printable_name = '(%s:%d) %s' % (
- self.trans_funcname(func.func_globals.get('__name__', '?')),
- func.func_code.co_firstlineno,
- func.__name__)
- if self.translator.frozen:
- if func not in self.translator.flowgraphs:
- print "NOT GENERATING", printable_name
- return self.skipped_function(func)
- else:
- if (func.func_doc and
- func.func_doc.lstrip().startswith('NOT_RPYTHON')):
- print "skipped", printable_name
- return self.skipped_function(func)
- name = self.uniquename('gfunc_' + self.trans_funcname(
- namehint + func.__name__))
- f_name = 'f_' + name[6:]
- self.initcode.append1('from pypy.interpreter import gateway')
- self.initcode.append1('%s = space.wrap(gateway.interp2app(%s, unwrap_spec=[gateway.ObjSpace, gateway.Arguments]))' % (name, f_name))
- self.pendingfunctions.append(func)
- return name
-
- def nameof_staticmethod(self, sm):
- # XXX XXX XXXX
- func = sm.__get__(42.5)
- name = self.uniquename('gsm_' + func.__name__)
- functionname = self.nameof(func)
- self.initcode.append1('%s = space.wrap(%s)' % (name, functionname))
- return name
-
- def nameof_instancemethod(self, meth):
- if meth.im_self is None:
- # no error checking here
- return self.nameof(meth.im_func, namehint="%s_" % meth.im_class.__name__)
- else:
- ob = self.nameof(meth.im_self)
- func = self.nameof(meth.im_func)
- typ = self.nameof(meth.im_class)
- name = self.uniquename('gmeth_' + meth.im_func.__name__)
- funcname = self.nameof(meth.im_func.__name__)
- self.initcode.append1(
- '%s = space.getattr(%s, %s)' % (name, ob, funcname))
- return name
-
- def should_translate_attr(self, pbc, attr):
- ann = self.translator.annotator
- if ann is None:
- ignore = getattr(pbc.__class__, 'NOT_RPYTHON_ATTRIBUTES', [])
- if attr in ignore:
- return False
- else:
- return "probably" # True
- classdef = ann.getuserclasses().get(pbc.__class__)
- if classdef and classdef.about_attribute(attr) is not None:
- return True
- return False
-
- def later(self, gen):
- self.latercode.append1((gen, self.debugstack))
-
- def nameof_instance(self, instance):
- klass = instance.__class__
- name = self.uniquename('ginst_' + klass.__name__)
- cls = self.nameof(klass)
- if hasattr(klass, '__base__'):
- base_class = builtin_base(instance)
- base = self.nameof(base_class)
- else:
- base_class = None
- base = cls
- def initinstance():
- content = instance.__dict__.items()
- content.sort()
- for key, value in content:
- if self.should_translate_attr(instance, key):
- try:
- yield 'space.setattr(%s, %s, %s)' % (
- name, self.nameof(key), self.nameof(value))
- except:
- print >> sys.stderr, "Problem while generating %s of %r" % (
- name, instance)
- raise
- self.initcode.append1("%s = space.call_method(%s, '__new__', %s)" % (
- name, cls, cls))
- self.later(initinstance())
- return name
-
- def space_arities(self):
- if self._space_arities is None:
- arities = self._space_arities = {}
- for name, sym, arity, specnames in self.space.MethodTable:
- arities[name] = arity
- arities['isinstance'] = 2
- return self._space_arities
-
- def try_space_shortcut_for_builtin(self, v, nargs):
- if isinstance(v, Constant) and id(v.value) in self.builtin_ids:
- name = self.builtin_ids[id(v.value)].__name__
- if hasattr(self.space, name):
- if self.space_arities().get(name, -1) == nargs:
- return "space.%s" % name
- return None
-
- def nameof_builtin_function_or_method(self, func):
- if func.__self__ is None:
- # builtin function
- if id(func) in self.builtin_ids:
- func = self.builtin_ids[id(func)]
- return "(space.builtin.get(space.str_w(%s)))" % self.nameof(func.__name__)
- # where does it come from? Python2.2 doesn't have func.__module__
- for modname, module in sys.modules.items():
- if hasattr(module, '__file__'):
- if (module.__file__.endswith('.py') or
- module.__file__.endswith('.pyc') or
- module.__file__.endswith('.pyo')):
- continue # skip non-builtin modules
- if func is getattr(module, func.__name__, None):
- break
- else:
- raise Exception, '%r not found in any built-in module' % (func,)
- #if modname == '__builtin__':
- # # be lazy
- # return "(space.builtin.get(space.str_w(%s)))" % self.nameof(func.__name__)
- if modname == 'sys':
- # be lazy
- return "(space.sys.get(space.str_w(%s)))" % self.nameof(func.__name__)
- else:
- name = self.uniquename('gbltin_' + func.__name__)
- self.initcode.append1('%s = space.getattr(%s, %s)' % (
- name, self.nameof(module), self.nameof(func.__name__)))
- else:
- # builtin (bound) method
- name = self.uniquename('gbltinmethod_' + func.__name__)
- self.initcode.append1('%s = space.getattr(%s, %s)' % (
- name, self.nameof(func.__self__), self.nameof(func.__name__)))
- return name
-
- def nameof_classobj(self, cls):
- printable_name = cls.__name__
- if cls.__doc__ and cls.__doc__.lstrip().startswith('NOT_RPYTHON'):
- #raise Exception, "%r should never be reached" % (cls,)
- print "skipped class", printable_name
- return self.skipped_class(cls)
-
- metaclass = "space.w_type"
- name = self.uniquename('gcls_' + cls.__name__)
-
- if issubclass(cls, Exception):
- # if cls.__module__ == 'exceptions':
- # don't rely on this, py.magic redefines AssertionError
- if getattr(__builtin__,cls.__name__,None) is cls:
- # exception are defined on the space
- return 'space.w_%s' % cls.__name__
-
- if not isinstance(cls, type):
- assert type(cls) is type(Exception)
- # do *not* change metaclass, but leave the
- # decision to what PyPy thinks is correct.
- # metaclass = 'space.w_classobj'
-
- basenames = [self.nameof(base) for base in cls.__bases__]
-
- def initclassobj():
- content = cls.__dict__.items()
- content.sort()
- for key, value in content:
- if key.startswith('__'):
- if key in ['__module__', '__doc__', '__dict__',
- '__weakref__', '__metaclass__', '__slots__','__new__']:
- continue
-
- # redirect value through class interface, in order to
- # get methods instead of functions.
- value = getattr(cls, key)
-
- if isinstance(value, staticmethod) and value.__get__(1) not in self.translator.flowgraphs and self.translator.frozen:
- print "skipped staticmethod:", value
- continue
- if isinstance(value, FunctionType) and value not in self.translator.flowgraphs and self.translator.frozen:
- print "skipped function:", value
- continue
-
- yield 'space.setattr(%s, %s, %s)' % (
- name, self.nameof(key), self.nameof(value))
-
- baseargs = ", ".join(basenames)
- self.initcode.append('_dic = space.newdict([])')
- for key, value in cls.__dict__.items():
- if key.startswith('__'):
- if key in ['__module__', '__metaclass__', '__slots__','__new__']:
- keyname = self.nameof(key)
- valname = self.nameof(value)
- self.initcode.append("space.setitem(_dic, %s, %s)" % (
- keyname, valname))
-
- if cls.__doc__ is not None:
- sdoc = self.nameof("__doc__")
- docobj = cls.__dict__["__doc__"]
- if type(docobj) in (str, unicode):
- docstr = render_docstr(cls, "_doc = space.wrap(", ")")
- self.initcode.append((docstr,)) # not splitted
- else:
- self.initcode.append("_doc = %s" % self.nameof(docobj) )
- self.initcode.append("space.setitem(_dic, %s, _doc)" % (sdoc,))
- self.initcode.append1('_bases = space.newtuple([%(bases)s])\n'
- '_args = space.newtuple([%(name)s, _bases, _dic])\n'
- '%(klass)s = space.call(%(meta)s, _args)'
- % {"bases": baseargs,
- "klass": name,
- "name" : self.nameof(cls.__name__),
- "meta" : metaclass} )
-
- self.later(initclassobj())
- return name
-
- nameof_class = nameof_classobj # for Python 2.2
-
- typename_mapping = {
- object: 'space.w_object',
- int: 'space.w_int',
- long: 'space.w_long',
- bool: 'space.w_bool',
- list: 'space.w_list',
- tuple: 'space.w_tuple',
- dict: 'space.w_dict',
- str: 'space.w_str',
- float: 'space.w_float',
- slice: 'space.w_slice',
- type(Exception()): 'space.wrap(types.InstanceType)',
- type: 'space.w_type',
- complex:'space.wrap(types.ComplexType)',
- unicode:'space.w_unicode',
- basestring: (eval_helper, 'basestring', 'basestring'),
- file: (eval_helper, 'file', 'file'),
- type(None): (eval_helper, 'NoneType', 'type(None)'),
- CodeType: (eval_helper, 'code', 'type((lambda:42).func_code)'),
- ModuleType: (eval_helper, 'ModuleType', 'types.ModuleType'),
- xrange: (eval_helper, 'xrange', 'xrange'),
-
- ##r_int: 'space.w_int',
- ##r_uint: 'space.w_int',
-
- type(len): (eval_helper, 'FunctionType', 'type(lambda:42)'),
- # type 'method_descriptor':
- # XXX small problem here:
- # XXX with space.eval, we get <W_TypeObject(method)>
- # XXX but with wrap, we get <W_TypeObject(instancemethod)>
- type(list.append): (eval_helper, "method_descriptor", "type(list.append)"),
- # type 'wrapper_descriptor':
- type(type(None).__repr__): (eval_helper, "wrapper_descriptor",
- "type(type(None).__repr__)"),
- # type 'getset_descriptor':
- # XXX here we get <W_TypeObject(FakeDescriptor)>,
- # while eval gives us <W_TypeObject(GetSetProperty)>
- type(type.__dict__['__dict__']): (eval_helper, "getset_descriptor",
- "type(type.__dict__[\'__dict__\'])"),
- # type 'member_descriptor':
- # XXX this does not work in eval!
- # type(type.__dict__['__basicsize__']): "cannot eval type(type.__dict__['__basicsize__'])",
- # XXX there seems to be no working support for member descriptors ???
- type(types.GeneratorType.gi_frame):
- (eval_helper, "member_descriptor", 'type(property.fdel)'),
- types.ClassType: 'space.w_classobj',
- types.MethodType: (eval_helper, "instancemethod",
- "type((lambda:42).__get__(42))"),
- property: (eval_helper, "property", 'property'),
- }
-
- def nameof_type(self, cls):
- if cls in self.typename_mapping:
- ret = self.typename_mapping[cls]
- if type(ret) is tuple:
- ret = ret[0](self, ret[1], ret[2])
- return ret
- assert cls.__module__ != '__builtin__' or cls.__flags__&_HEAPTYPE, (
- "built-in class %r not found in typename_mapping "
- "while compiling %s" % (cls, self.currentfunc and
- self.currentfunc.__name__ or "*no function at all*"))
- return self.nameof_classobj(cls)
-
- def nameof_tuple(self, tup):
- name = self.uniquename('g%dtuple' % len(tup))
- args = [self.nameof(x) for x in tup]
- args = ', '.join(args)
- self.initcode.append1('%s = space.newtuple([%s])' % (name, args))
- return name
-
- def nameof_list(self, lis):
- name = self.uniquename('g%dlist' % len(lis))
- # note that self.latercode led to too late initialization.
- self.register_early(lis, name)
- # try to save at least one assignment.
- if lis and lis[0] is not lis:
- default = lis[0]
- else:
- default = None
- self.initcode.append('%s = space.newlist([%s])' % (name, self.nameof(default)))
- self.initcode.append('%s = space.mul(%s, %s)' % (name, name, self.nameof(len(lis))))
- for i in range(len(lis)):
- if lis[i] is not default:
- item = self.nameof(lis[i])
- self.initcode.append('space.setitem(%s, %s, %s);' % (
- name, self.nameof(i), item))
- return name
-
- def nameof_dict(self, dic):
- assert dic is not __builtins__
- name = self.uniquename('g%ddict' % len(dic))
- self.register_early(dic, name)
- self.initcode.append('%s = space.newdict([])' % (name,))
- for k in dic:
- if k == '__builtins__':
- continue
- self.initcode.append('space.setitem(%s, %s, %s)'%(
- name, self.nameof(k), self.nameof(dic[k])))
- return name
-
- # strange prebuilt instances below, don't look too closely
- # XXX oh well.
- def nameof_member_descriptor(self, md):
- name = self.uniquename('gdescriptor_%s_%s' % (
- md.__objclass__.__name__, md.__name__))
- cls = self.nameof(md.__objclass__)
- # do I need to take the dict and then getitem???
- self.initcode.append1('%s = space.getattr(%s, %s)' %
- (name, cls, self.nameof(md.__name__)))
- return name
- nameof_getset_descriptor = nameof_member_descriptor
- nameof_method_descriptor = nameof_member_descriptor
- nameof_wrapper_descriptor = nameof_member_descriptor
-
- def nameof_file(self, fil):
- if fil is sys.stdin:
- return 'space.sys.get("stdin")'
- if fil is sys.stdout:
- return 'space.sys.get("stdout")'
- if fil is sys.stderr:
- return 'space.sys.get("stderr")'
- raise Exception, 'Cannot translate an already-open file: %r' % (fil,)
-
- def gen_source(self, fname, ftmpname=None, file=file):
- self.fname = fname
- self.ftmpname = ftmpname
-
- # generate unordered source file, first.
- # I prefer this over ordering everything in memory.
- fname = self.fname
- if self.ftmpname:
- fname = self.ftmpname
- f = file(fname, "w")
- # generate ordered source file
- try:
- self.f = f
- self.gen_source_temp()
- finally:
- f.close()
-
- def copyfile(source, target):
- file(target, "w").write(file(source).read())
-
- def order_sections(fname):
- sep = "\n##SECTION##\n"
- txt = file(fname).read()
- pieces = txt.split(sep)
- prelude = pieces.pop(0)
- postlude = pieces.pop()
- dic = {}
- while pieces:
- func = pieces.pop()
- head = pieces.pop()
- key = makekey(head, len(pieces))
- dic[key] = head + sep + func
- lis = dic.items()
- lis.sort()
- lis = [prelude] + [func for head, func in lis] + [postlude]
- txt = sep.join(lis)
- file(fname, "w").write(txt)
-
- def makekey(txt, uniqueno):
- dic = {}
- for line in txt.split("\n"):
- ign, name, value = line.split(None, 2)
- dic[name] = eval(value, {})
- key = (dic["filename"], dic["firstlineno"],
- dic["function"], uniqueno)
- return key
-
- order_sections(fname)
- if self.ftmpname:
- copyfile(self.ftmpname, self.fname)
-
- def gen_source_temp(self):
- f = self.f
-
- # header
- print >> f, self.RPY_HEADER
- print >> f
-
- info = {
- 'modname': self.modname,
- # the side-effects of this is kick-start the process
- 'entrypoint': None # self.nameof(self.entrypoint),
- }
- # header """def initmodule(space):"""
- print >> f, self.RPY_INIT_HEADER % info
-
- # doc
- if self.moddict and self.moddict.get("__doc__"):
- doc = self.moddict["__doc__"]
- print >> f, render_docstr(doc, " __doc__ = \\\n")
- print >> f
- # make sure it is not rendered again
- key = Constant(doc).key
- self.rpynames[key] = "w__doc__"
- self.initcode.append("w__doc__ = space.wrap(__doc__)")
-
- # info.entrypoint must be done *after* __doc__ is handled,
- # because nameof(entrypoint) might touch __doc__ early.
- info["entrypoint"] = self.nameof(self.entrypoint)
-
- # function implementations
- while self.pendingfunctions or self.latercode:
- if self.pendingfunctions:
- func = self.pendingfunctions.pop()
- self.currentfunc = func
- self.gen_rpyfunction(func)
- # collect more of the latercode after each function
- while self.latercode:
- gen, self.debugstack = self.latercode.pop()
- #self.initcode.extend(gen) -- eats TypeError! bad CPython!
- for line in gen:
- self.initcode.append1(line)
- self.debugstack = ()
- self.gen_global_declarations()
-
- # set the final splitter
- print >> f, "##SECTION##"
- # footer, init code
- for codelines in self.initcode:
- # keep docstrings unindented
- indent = " "
- if type(codelines) is tuple:
- codelines = codelines[0].split("\n", 1)
- codelines[0] = indent + codelines[0]
- indent = ""
- else:
- codelines = codelines.split("\n")
- for codeline in codelines:
- print >> f, indent + codeline
-
- self.gen_trailer(info, " ")
- # do not close the file here!
-
- def gen_trailer(self, info, indent):
- if self.moddict:
- # we are generating a module, no __main__ etc.
- print >> self.f, indent + "return %s" % self.nameof(self.entrypoint)
- print >> self.f
- else:
- # we should have an entrypoint function
- info['entrypointname'] = self.trans_funcname(self.entrypoint.__name__)
- print >> self.f, self.RPY_INIT_FOOTER % info
-
- def gen_global_declarations(self):
- g = self.globaldecl
- if g:
- f = self.f
- print >> f, '# global declaration%s' % ('s'*(len(g)>1))
- for line in g:
- print >> f, line
- print >> f
- del g[:]
- g = self.globalobjects
- for name in g:
- pass # self.initcode.append1('# REGISTER_GLOBAL(%s)' % (name,))
- del g[:]
-
- def rel_filename(self, name):
- # try to find a name relative to pypy and unify.
- # if not possible, stick with the original.
- ref = py.path.local(pypy.__path__[0])
- rel = py.path.local(name).relto(ref)
- if rel:
- # make it os independent
- return rel.replace('\\', '/')
- return name # no success
-
- def gen_rpyfunction(self, func):
-
- f = self.f
- print >> f, "##SECTION##" # simple to split, afterwards
- print >> f, ("## filename %r\n"
- "## function %r\n"
- "## firstlineno %d") % (
- self.rel_filename(func.func_code.co_filename),
- func.func_code.co_name,
- func.func_code.co_firstlineno)
- print >> f, "##SECTION##"
- localscope = self.namespace.localScope()
- body = list(self.rpyfunction_body(func, localscope))
- name_of_defaults = [self.nameof(x, debug=('Default argument of', func))
- for x in (func.func_defaults or ())]
- self.gen_global_declarations()
-
- # print header
- docstr = render_docstr(func, " ")
- cname = self.nameof(func)
- assert cname.startswith('gfunc_')
- f_name = 'f_' + cname[6:]
-
- # collect all the local variables
- graph = self.translator.getflowgraph(func)
- localslst = []
- def visit(node):
- if isinstance(node, Block):
- localslst.extend(node.getvariables())
- traverse(visit, graph)
- localnames = [self.expr(a, localscope) for a in uniqueitems(localslst)]
-
- # collect all the arguments
- vararg = varkw = None
- varargname = varkwname = None
- all_args = graph.getargs()
- p = len(all_args)
- if func.func_code.co_flags & CO_VARKEYWORDS:
- p -= 1
- varkw = graph.getargs()[p]
- varkwname = func.func_code.co_varnames[p]
- if func.func_code.co_flags & CO_VARARGS:
- p -= 1
- vararg = graph.getargs()[p]
- varargname = func.func_code.co_varnames[p]
- positional_args = all_args[:p]
-
- fast_args = [self.expr(a, localscope) for a in positional_args]
- if vararg is not None:
- vararg = self.expr(vararg, localscope)
- fast_args.append(vararg)
- if varkw is not None:
- varkw = self.expr(varkw, localscope)
- fast_args.append(varkw)
- fast_name = 'fast' + f_name
-
- fast_set = dict(zip(fast_args, fast_args))
-
- # create function declaration
- name = self.trans_funcname(func.__name__) # for <lambda>
- argstr = ", ".join(['space'] + fast_args)
- fast_function_header = (' def %s(%s):'
- % (name, argstr))
-
- def install_func(f_name, name):
- yield ''
- yield ' %s = %s' % (f_name, name)
- #import __builtin__
- #dic = __builtin__.__dict__
- #if dic.get(name):
- # yield 'del %s # hiding a builtin!' % name
- #else:
- # self.initcode.append1('del m.%s' % (name,))
-
- print >> f, ' def %s(space, __args__):' % (name,)
- if docstr is not None:
- print >> f, docstr
- print >> f
- def tupstr(seq):
- if len(seq) == 1:
- fmt = '%s,'
- else:
- fmt = '%s'
- return fmt % ', '.join(seq)
- def tupassstr(seq):
- if not seq:
- return ""
- else:
- return tupstr(seq) + " = "
-
- print >> f, ' funcname = "%s"' % func.__name__
-
- kwlist = list(func.func_code.co_varnames[:func.func_code.co_argcount])
- signature = ' signature = %r' % kwlist
- signature = ", ".join([signature, repr(varargname), repr(varkwname)])
- print >> f, signature
-
- print >> f, ' defaults_w = [%s]' % ", ".join(name_of_defaults)
-
- print >> f, ' %s__args__.parse(funcname, signature, defaults_w)' % (
- tupassstr(fast_args),)
- print >> f, ' return %s(%s)' % (fast_name, ', '.join(["space"]+fast_args))
-
- for line in install_func(f_name, name):
- print >> f, line
-
- print >> f
- print >> f, fast_function_header
- if docstr is not None:
- print >> f, docstr
-
- fast_locals = [arg for arg in localnames if arg not in fast_set]
-## # if goto is specialized, the false detection of
-## # uninitialized variables goes away.
-## if fast_locals and not self.specialize_goto:
-## print >> f
-## for line in self.large_initialize(fast_locals):
-## print >> f, " %s" % line
-## print >> f
-
- # print the body
- for line in body:
- print >> f, line
- for line in install_func("fast"+f_name, name):
- print >> f, line
- print >> f
-
- # print the PyMethodDef
- # skipped
-
- if not self.translator.frozen:
- # this is only to keep the RAM consumption under control
- pass # del self.translator.flowgraphs[func]
- # got duplicate flowgraphs when doing this!
-
- def rpyfunction_body(self, func, localscope):
- try:
- graph = self.translator.getflowgraph(func)
- except Exception, e:
- print 20*"*", e
- print func
- raise
- # not needed, we use tuple assignment!
- # remove_direct_loops(graph)
- checkgraph(graph)
-
- allblocks = []
-
- f = self.f
- t = self.translator
- #t.simplify(func)
- graph = t.getflowgraph(func)
-
-
- start = graph.startblock
- allblocks = ordered_blocks(graph)
- nblocks = len(allblocks)
-
- blocknum = {}
- for block in allblocks:
- blocknum[block] = len(blocknum)+1
-
- yield " goto = %s # startblock" % self.mklabel(blocknum[start])
- yield " while True:"
-
- def render_block(block):
- catch_exception = block.exitswitch == Constant(last_exception)
- regular_op = len(block.operations) - catch_exception
- # render all but maybe the last op
- for op in block.operations[:regular_op]:
- for line in self.oper(op, localscope).split("\n"):
- yield "%s" % line
- # render the last op if it is exception handled
- for op in block.operations[regular_op:]:
- yield "try:"
- for line in self.oper(op, localscope).split("\n"):
- yield " %s" % line
-
- if len(block.exits) == 0:
- if len(block.inputargs) == 2: # exc_cls, exc_value
- # exceptional return block
- exc_cls = self.expr(block.inputargs[0], localscope)
- exc_val = self.expr(block.inputargs[1], localscope)
- yield "raise %s(%s, %s)" % (self.nameof(OperationError),
- exc_cls, exc_val)
- else:
- # regular return block
- retval = self.expr(block.inputargs[0], localscope)
- yield "return %s" % retval
- return
- elif block.exitswitch is None:
- # single-exit block
- assert len(block.exits) == 1
- for op in self.gen_link(block.exits[0], localscope, blocknum, block):
- yield "%s" % op
- elif catch_exception:
- # block catching the exceptions raised by its last operation
- # we handle the non-exceptional case first
- link = block.exits[0]
- assert link.exitcase is None
- for op in self.gen_link(link, localscope, blocknum, block):
- yield " %s" % op
- # we must catch the exception raised by the last operation,
- # which goes to the last err%d_%d label written above.
- # Since we only have OperationError, we need to select:
- yield "except %s, e:" % (self.nameof(OperationError),)
- yield " e.normalize_exception(space)"
- q = "if"
- for link in block.exits[1:]:
- assert issubclass(link.exitcase, Exception)
- # Exeption classes come unwrapped in link.exitcase
- yield " %s space.is_true(space.issubtype(e.w_type, %s)):" % (q,
- self.nameof(link.exitcase))
- q = "elif"
- for op in self.gen_link(link, localscope, blocknum, block, {
- link.last_exception: 'e.w_type',
- link.last_exc_value: 'e.w_value'}):
- yield " %s" % op
- yield " else:raise # unhandled case, should not happen"
- else:
- # block ending in a switch on a value
- exits = list(block.exits)
- if len(exits) == 2 and (
- exits[0].exitcase is False and exits[1].exitcase is True):
- # order these guys like Python does
- exits.reverse()
- q = "if"
- for link in exits[:-1]:
- yield "%s %s == %s:" % (q, self.expr(block.exitswitch,
- localscope),
- link.exitcase)
- for op in self.gen_link(link, localscope, blocknum, block):
- yield " %s" % op
- q = "elif"
- link = exits[-1]
- yield "else:"
- yield " assert %s == %s" % (self.expr(block.exitswitch,
- localscope),
- link.exitcase)
- for op in self.gen_link(exits[-1], localscope, blocknum, block):
- yield " %s" % op
-
- cmpop = ('==', 'is') [self.specialize_goto]
- for block in allblocks:
- blockno = blocknum[block]
- yield ""
- yield " if goto %s %s:" % (cmpop, self.mklabel(blockno))
- for line in render_block(block):
- yield " %s" % line
-
-# ____________________________________________________________
-
- RPY_HEADER = '''#!/bin/env python
-# -*- coding: LATIN-1 -*-'''
-
- RPY_SEP = "#*************************************************************"
-
- RPY_INIT_HEADER = RPY_SEP + '''
-
-def init%(modname)s(space):
- """NOT_RPYTHON"""
-'''
-
- RPY_INIT_FOOTER = '''
-# entry point: %(entrypointname)s, %(entrypoint)s
-if __name__ == "__main__":
- from pypy.objspace.std import StdObjSpace
- from pypy.objspace.std.model import UnwrapError
- space = StdObjSpace()
- init%(modname)s(space)
- ret = space.call(%(entrypoint)s, space.newtuple([]))
- try:
- print space.unwrap(ret)
- except UnwrapError:
- print "cannot unwrap, here the wrapped result:"
- print ret
-'''
-
-# _____________________________________________________________________
-
-# implementation of the interface that is finally only
-# used: translate_as_module
-
-import py.code
-import cStringIO as StringIO
-
-class memfile(object):
- _storage = {}
- def __init__(self, name, mode="r"):
- if mode == "w":
- self._storage[name] = StringIO.StringIO()
- elif mode == "r":
- try:
- data = self._storage[name].getvalue()
- except IndexError:
- data = file(name).read()
- self._storage[name] = StringIO.StringIO(data)
- else:
- raise ValueError, "mode %s not supported" % mode
- self._file = self._storage[name]
- def __getattr__(self, name):
- return getattr(self._file, name)
- def close(self):
- pass
-
-def translate_as_module(sourcetext, filename=None, modname="app2interpexec",
- do_imports_immediately=False, tmpname=None):
- """ compile sourcetext as a module, translating to interp level.
- The result is the init function that creates the wrapped module dict,
- together with the generated source text.
- This init function needs a space as argument.
- tmpname can be passed for debugging purposes.
-
- Example:
-
- initfunc, newsrc = translate_as_module(text)
- from pypy.objspace.std import Space
- space = Space()
- dic = initfunc(space)
- # and now use the members of the dict
- """
- # create something like a module
- if filename is None:
- code = py.code.Source(sourcetext).compile()
- else:
- code = NiceCompile(filename)(sourcetext)
- dic = {'__name__': modname}
- if filename:
- dic['__file__'] = filename
- exec code in dic
-
- entrypoint = dic
- t = Translator(None, verbose=False, simplifying=needed_passes,
- do_imports_immediately=do_imports_immediately,
- builtins_can_raise_exceptions=True)
- gen = GenRpy(t, entrypoint, modname, dic)
- if tmpname:
- _file = file
- else:
- _file = memfile
- tmpname = 'nada'
- out = _file(tmpname, 'w')
- gen.f = out
- gen.gen_source(tmpname, file=_file)
- out.close()
- newsrc = _file(tmpname).read()
- code = py.code.Source(newsrc).compile()
- dic = {'__name__': modname}
- exec code in dic
- # now we just need to return the init function,
- # which then needs to be called with the space to return the dict.
- return dic['init%s' % modname], newsrc
-
-#___________________________________________________________________
-
-# some testing code
-
-testcode = """
-def f(a, b):
- return a + b
-
-def g():
- return f(f(1, 2), f(4, 8))
-"""
-
-if __name__ == '__main__':
- res = translate_as_module(testcode, tmpname='/tmp/look.py')
More information about the Pypy-commit
mailing list